| use core::cmp::min; |
| use core::ops::{Add, Sub}; |
| |
| use super::error::*; |
| use super::field25519::*; |
| |
| #[derive(Clone, Copy)] |
| pub struct GeP2 { |
| x: Fe, |
| y: Fe, |
| z: Fe, |
| } |
| |
| #[derive(Clone, Copy)] |
| pub struct GeP3 { |
| x: Fe, |
| y: Fe, |
| z: Fe, |
| t: Fe, |
| } |
| |
| #[derive(Clone, Copy, Default)] |
| pub struct GeP1P1 { |
| x: Fe, |
| y: Fe, |
| z: Fe, |
| t: Fe, |
| } |
| |
| #[derive(Clone, Copy)] |
| pub struct GePrecomp { |
| y_plus_x: Fe, |
| y_minus_x: Fe, |
| xy2d: Fe, |
| } |
| |
| #[derive(Clone, Copy, Default)] |
| pub struct GeCached { |
| y_plus_x: Fe, |
| y_minus_x: Fe, |
| z: Fe, |
| t2d: Fe, |
| } |
| |
| impl GeCached { |
| pub fn maybe_set(&mut self, other: &GeCached, do_swap: u8) { |
| self.y_plus_x.maybe_set(&other.y_plus_x, do_swap); |
| self.y_minus_x.maybe_set(&other.y_minus_x, do_swap); |
| self.z.maybe_set(&other.z, do_swap); |
| self.t2d.maybe_set(&other.t2d, do_swap); |
| } |
| } |
| |
| impl GeP1P1 { |
| fn to_p2(&self) -> GeP2 { |
| GeP2 { |
| x: self.x * self.t, |
| y: self.y * self.z, |
| z: self.z * self.t, |
| } |
| } |
| |
| fn to_p3(&self) -> GeP3 { |
| GeP3 { |
| x: self.x * self.t, |
| y: self.y * self.z, |
| z: self.z * self.t, |
| t: self.x * self.y, |
| } |
| } |
| } |
| |
| impl From<GeP2> for GeP3 { |
| fn from(p: GeP2) -> GeP3 { |
| GeP3 { |
| x: p.x, |
| y: p.y, |
| z: p.z, |
| t: p.x * p.y, |
| } |
| } |
| } |
| |
| impl GeP2 { |
| fn zero() -> GeP2 { |
| GeP2 { |
| x: FE_ZERO, |
| y: FE_ONE, |
| z: FE_ONE, |
| } |
| } |
| |
| fn dbl(&self) -> GeP1P1 { |
| let xx = self.x.square(); |
| let yy = self.y.square(); |
| let b = self.z.square_and_double(); |
| let a = self.x + self.y; |
| let aa = a.square(); |
| let y3 = yy + xx; |
| let z3 = yy - xx; |
| let x3 = aa - y3; |
| let t3 = b - z3; |
| |
| GeP1P1 { |
| x: x3, |
| y: y3, |
| z: z3, |
| t: t3, |
| } |
| } |
| |
| fn slide(a: &[u8]) -> [i8; 256] { |
| let mut r = [0i8; 256]; |
| for i in 0..256 { |
| r[i] = (1 & (a[i >> 3] >> (i & 7))) as i8; |
| } |
| for i in 0..256 { |
| if r[i] != 0 { |
| for b in 1..min(7, 256 - i) { |
| if r[i + b] != 0 { |
| if r[i] + (r[i + b] << b) <= 15 { |
| r[i] += r[i + b] << b; |
| r[i + b] = 0; |
| } else if r[i] - (r[i + b] << b) >= -15 { |
| r[i] -= r[i + b] << b; |
| for k in i + b..256 { |
| if r[k] == 0 { |
| r[k] = 1; |
| break; |
| } |
| r[k] = 0; |
| } |
| } else { |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| r |
| } |
| |
| #[allow(clippy::comparison_chain)] |
| pub fn double_scalarmult_vartime(a_scalar: &[u8], a_point: GeP3, b_scalar: &[u8]) -> GeP2 { |
| let aslide = GeP2::slide(a_scalar); |
| let bslide = GeP2::slide(b_scalar); |
| |
| let mut ai = [GeCached { |
| y_plus_x: FE_ZERO, |
| y_minus_x: FE_ZERO, |
| z: FE_ZERO, |
| t2d: FE_ZERO, |
| }; 8]; // A,3A,5A,7A,9A,11A,13A,15A |
| ai[0] = a_point.to_cached(); |
| let a2 = a_point.dbl().to_p3(); |
| ai[1] = (a2 + ai[0]).to_p3().to_cached(); |
| ai[2] = (a2 + ai[1]).to_p3().to_cached(); |
| ai[3] = (a2 + ai[2]).to_p3().to_cached(); |
| ai[4] = (a2 + ai[3]).to_p3().to_cached(); |
| ai[5] = (a2 + ai[4]).to_p3().to_cached(); |
| ai[6] = (a2 + ai[5]).to_p3().to_cached(); |
| ai[7] = (a2 + ai[6]).to_p3().to_cached(); |
| |
| let mut r = GeP2::zero(); |
| |
| let mut i: usize = 255; |
| loop { |
| if aslide[i] != 0 || bslide[i] != 0 { |
| break; |
| } |
| if i == 0 { |
| return r; |
| } |
| i -= 1; |
| } |
| |
| loop { |
| let mut t = r.dbl(); |
| if aslide[i] > 0 { |
| t = t.to_p3() + ai[(aslide[i] / 2) as usize]; |
| } else if aslide[i] < 0 { |
| t = t.to_p3() - ai[(-aslide[i] / 2) as usize]; |
| } |
| |
| if bslide[i] > 0 { |
| t = t.to_p3() + BI[(bslide[i] / 2) as usize]; |
| } else if bslide[i] < 0 { |
| t = t.to_p3() - BI[(-bslide[i] / 2) as usize]; |
| } |
| |
| r = t.to_p2(); |
| |
| if i == 0 { |
| return r; |
| } |
| i -= 1; |
| } |
| } |
| } |
| |
| impl GeP3 { |
| pub fn from_bytes_negate_vartime(s: &[u8; 32]) -> Option<GeP3> { |
| let y = Fe::from_bytes(s); |
| let z = FE_ONE; |
| let y_squared = y.square(); |
| let u = y_squared - FE_ONE; |
| let v = (y_squared * FE_D) + FE_ONE; |
| let mut x = (u * v).pow25523() * u; |
| |
| let vxx = x.square() * v; |
| let check = vxx - u; |
| if !check.is_zero() { |
| let check2 = vxx + u; |
| if !check2.is_zero() { |
| return None; |
| } |
| x = x * FE_SQRTM1; |
| } |
| |
| if x.is_negative() == ((s[31] >> 7) != 0) { |
| x = x.neg(); |
| } |
| |
| let t = x * y; |
| |
| Some(GeP3 { x, y, z, t }) |
| } |
| |
| pub fn from_bytes_vartime(s: &[u8; 32]) -> Option<GeP3> { |
| Self::from_bytes_negate_vartime(s).map(|p| GeP3 { |
| x: p.x.neg(), |
| y: p.y, |
| z: p.z, |
| t: p.t.neg(), |
| }) |
| } |
| |
| fn to_p2(&self) -> GeP2 { |
| GeP2 { |
| x: self.x, |
| y: self.y, |
| z: self.z, |
| } |
| } |
| |
| fn to_cached(&self) -> GeCached { |
| GeCached { |
| y_plus_x: self.y + self.x, |
| y_minus_x: self.y - self.x, |
| z: self.z, |
| t2d: self.t * FE_D2, |
| } |
| } |
| |
| fn zero() -> GeP3 { |
| GeP3 { |
| x: FE_ZERO, |
| y: FE_ONE, |
| z: FE_ONE, |
| t: FE_ZERO, |
| } |
| } |
| |
| fn dbl(&self) -> GeP1P1 { |
| self.to_p2().dbl() |
| } |
| |
| pub fn to_bytes(&self) -> [u8; 32] { |
| let recip = self.z.invert(); |
| let x = self.x * recip; |
| let y = self.y * recip; |
| let mut bs = y.to_bytes(); |
| bs[31] ^= (if x.is_negative() { 1 } else { 0 }) << 7; |
| bs |
| } |
| |
| pub fn has_small_order(&self) -> bool { |
| let recip = self.z.invert(); |
| let x = self.x * recip; |
| let y = self.y * recip; |
| let x_neg = x.neg(); |
| let y_sqrtm1 = y * FE_SQRTM1; |
| x.is_zero() | y.is_zero() | (y_sqrtm1 == x) | (y_sqrtm1 == x_neg) |
| } |
| } |
| |
| impl Add<GeP3> for GeP3 { |
| type Output = GeP3; |
| |
| fn add(self, other: GeP3) -> GeP3 { |
| (self + other.to_cached()).to_p3() |
| } |
| } |
| |
| impl Sub<GeP3> for GeP3 { |
| type Output = GeP3; |
| |
| fn sub(self, other: GeP3) -> GeP3 { |
| (self - other.to_cached()).to_p3() |
| } |
| } |
| |
| impl Add<GeCached> for GeP3 { |
| type Output = GeP1P1; |
| |
| fn add(self, _rhs: GeCached) -> GeP1P1 { |
| let y1_plus_x1 = self.y + self.x; |
| let y1_minus_x1 = self.y - self.x; |
| let a = y1_plus_x1 * _rhs.y_plus_x; |
| let b = y1_minus_x1 * _rhs.y_minus_x; |
| let c = _rhs.t2d * self.t; |
| let zz = self.z * _rhs.z; |
| let d = zz + zz; |
| let x3 = a - b; |
| let y3 = a + b; |
| let z3 = d + c; |
| let t3 = d - c; |
| |
| GeP1P1 { |
| x: x3, |
| y: y3, |
| z: z3, |
| t: t3, |
| } |
| } |
| } |
| |
| impl Add<GePrecomp> for GeP3 { |
| type Output = GeP1P1; |
| |
| fn add(self, _rhs: GePrecomp) -> GeP1P1 { |
| let y1_plus_x1 = self.y + self.x; |
| let y1_minus_x1 = self.y - self.x; |
| let a = y1_plus_x1 * _rhs.y_plus_x; |
| let b = y1_minus_x1 * _rhs.y_minus_x; |
| let c = _rhs.xy2d * self.t; |
| let d = self.z + self.z; |
| let x3 = a - b; |
| let y3 = a + b; |
| let z3 = d + c; |
| let t3 = d - c; |
| |
| GeP1P1 { |
| x: x3, |
| y: y3, |
| z: z3, |
| t: t3, |
| } |
| } |
| } |
| |
| impl Sub<GeCached> for GeP3 { |
| type Output = GeP1P1; |
| |
| fn sub(self, _rhs: GeCached) -> GeP1P1 { |
| let y1_plus_x1 = self.y + self.x; |
| let y1_minus_x1 = self.y - self.x; |
| let a = y1_plus_x1 * _rhs.y_minus_x; |
| let b = y1_minus_x1 * _rhs.y_plus_x; |
| let c = _rhs.t2d * self.t; |
| let zz = self.z * _rhs.z; |
| let d = zz + zz; |
| let x3 = a - b; |
| let y3 = a + b; |
| let z3 = d - c; |
| let t3 = d + c; |
| |
| GeP1P1 { |
| x: x3, |
| y: y3, |
| z: z3, |
| t: t3, |
| } |
| } |
| } |
| |
| impl Sub<GePrecomp> for GeP3 { |
| type Output = GeP1P1; |
| |
| fn sub(self, _rhs: GePrecomp) -> GeP1P1 { |
| let y1_plus_x1 = self.y + self.x; |
| let y1_minus_x1 = self.y - self.x; |
| let a = y1_plus_x1 * _rhs.y_minus_x; |
| let b = y1_minus_x1 * _rhs.y_plus_x; |
| let c = _rhs.xy2d * self.t; |
| let d = self.z + self.z; |
| let x3 = a - b; |
| let y3 = a + b; |
| let z3 = d - c; |
| let t3 = d + c; |
| |
| GeP1P1 { |
| x: x3, |
| y: y3, |
| z: z3, |
| t: t3, |
| } |
| } |
| } |
| |
| fn ge_precompute(base: &GeP3) -> [GeCached; 16] { |
| let base_cached = base.to_cached(); |
| let mut pc = [GeP3::zero(); 16]; |
| pc[1] = *base; |
| for i in 2..16 { |
| pc[i] = if i % 2 == 0 { |
| pc[i / 2].dbl().to_p3() |
| } else { |
| pc[i - 1].add(base_cached).to_p3() |
| } |
| } |
| let mut pc_cached: [GeCached; 16] = Default::default(); |
| for i in 0..16 { |
| pc_cached[i] = pc[i].to_cached(); |
| } |
| pc_cached |
| } |
| |
| pub fn ge_scalarmult(scalar: &[u8], base: &GeP3) -> GeP3 { |
| let pc = ge_precompute(base); |
| let mut q = GeP3::zero(); |
| let mut pos = 252; |
| loop { |
| let slot = ((scalar[pos >> 3] >> (pos & 7)) & 15) as usize; |
| let mut t = pc[0]; |
| for i in 1..16 { |
| t.maybe_set(&pc[i], (((slot ^ i).wrapping_sub(1)) >> 8) as u8 & 1); |
| } |
| q = q.add(t).to_p3(); |
| if pos == 0 { |
| break; |
| } |
| q = q.dbl().to_p3().dbl().to_p3().dbl().to_p3().dbl().to_p3(); |
| pos -= 4; |
| } |
| q |
| } |
| |
| pub fn ge_scalarmult_base(scalar: &[u8]) -> GeP3 { |
| const BXP: [u8; 32] = [ |
| 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, |
| 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, |
| 0x69, 0x21, |
| ]; |
| const BYP: [u8; 32] = [ |
| 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, |
| 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, |
| 0x66, 0x66, |
| ]; |
| let bx = Fe::from_bytes(&BXP); |
| let by = Fe::from_bytes(&BYP); |
| let base = GeP3 { |
| x: bx, |
| y: by, |
| z: FE_ONE, |
| t: bx * by, |
| }; |
| ge_scalarmult(scalar, &base) |
| } |
| |
| #[cfg(feature = "x25519")] |
| pub fn ge_to_x25519_vartime(s: &[u8; 32]) -> Option<[u8; 32]> { |
| let p = GeP3::from_bytes_vartime(s)?; |
| let yed = p.y; |
| let x_mont = (FE_ONE + yed) * ((FE_ONE - yed).invert()); |
| Some(x_mont.to_bytes()) |
| } |
| |
| pub fn sc_reduce32(s: &mut [u8; 32]) { |
| let mut t = [0u8; 64]; |
| t[0..32].copy_from_slice(s); |
| sc_reduce(&mut t); |
| s.copy_from_slice(&t[0..32]); |
| } |
| |
| pub fn sc_reduce(s: &mut [u8]) { |
| let mut s0: i64 = 2097151 & load_3i(s); |
| let mut s1: i64 = 2097151 & (load_4i(&s[2..6]) >> 5); |
| let mut s2: i64 = 2097151 & (load_3i(&s[5..8]) >> 2); |
| let mut s3: i64 = 2097151 & (load_4i(&s[7..11]) >> 7); |
| let mut s4: i64 = 2097151 & (load_4i(&s[10..14]) >> 4); |
| let mut s5: i64 = 2097151 & (load_3i(&s[13..16]) >> 1); |
| let mut s6: i64 = 2097151 & (load_4i(&s[15..19]) >> 6); |
| let mut s7: i64 = 2097151 & (load_3i(&s[18..21]) >> 3); |
| let mut s8: i64 = 2097151 & load_3i(&s[21..24]); |
| let mut s9: i64 = 2097151 & (load_4i(&s[23..27]) >> 5); |
| let mut s10: i64 = 2097151 & (load_3i(&s[26..29]) >> 2); |
| let mut s11: i64 = 2097151 & (load_4i(&s[28..32]) >> 7); |
| let mut s12: i64 = 2097151 & (load_4i(&s[31..35]) >> 4); |
| let mut s13: i64 = 2097151 & (load_3i(&s[34..37]) >> 1); |
| let mut s14: i64 = 2097151 & (load_4i(&s[36..40]) >> 6); |
| let mut s15: i64 = 2097151 & (load_3i(&s[39..42]) >> 3); |
| let mut s16: i64 = 2097151 & load_3i(&s[42..45]); |
| let mut s17: i64 = 2097151 & (load_4i(&s[44..48]) >> 5); |
| let s18: i64 = 2097151 & (load_3i(&s[47..50]) >> 2); |
| let s19: i64 = 2097151 & (load_4i(&s[49..53]) >> 7); |
| let s20: i64 = 2097151 & (load_4i(&s[52..56]) >> 4); |
| let s21: i64 = 2097151 & (load_3i(&s[55..58]) >> 1); |
| let s22: i64 = 2097151 & (load_4i(&s[57..61]) >> 6); |
| let s23: i64 = load_4i(&s[60..64]) >> 3; |
| |
| s11 += s23 * 666643; |
| s12 += s23 * 470296; |
| s13 += s23 * 654183; |
| s14 -= s23 * 997805; |
| s15 += s23 * 136657; |
| s16 -= s23 * 683901; |
| |
| s10 += s22 * 666643; |
| s11 += s22 * 470296; |
| s12 += s22 * 654183; |
| s13 -= s22 * 997805; |
| s14 += s22 * 136657; |
| s15 -= s22 * 683901; |
| |
| s9 += s21 * 666643; |
| s10 += s21 * 470296; |
| s11 += s21 * 654183; |
| s12 -= s21 * 997805; |
| s13 += s21 * 136657; |
| s14 -= s21 * 683901; |
| |
| s8 += s20 * 666643; |
| s9 += s20 * 470296; |
| s10 += s20 * 654183; |
| s11 -= s20 * 997805; |
| s12 += s20 * 136657; |
| s13 -= s20 * 683901; |
| |
| s7 += s19 * 666643; |
| s8 += s19 * 470296; |
| s9 += s19 * 654183; |
| s10 -= s19 * 997805; |
| s11 += s19 * 136657; |
| s12 -= s19 * 683901; |
| |
| s6 += s18 * 666643; |
| s7 += s18 * 470296; |
| s8 += s18 * 654183; |
| s9 -= s18 * 997805; |
| s10 += s18 * 136657; |
| s11 -= s18 * 683901; |
| |
| let mut carry6: i64 = (s6 + (1 << 20)) >> 21; |
| s7 += carry6; |
| s6 -= carry6 << 21; |
| let mut carry8: i64 = (s8 + (1 << 20)) >> 21; |
| s9 += carry8; |
| s8 -= carry8 << 21; |
| let mut carry10: i64 = (s10 + (1 << 20)) >> 21; |
| s11 += carry10; |
| s10 -= carry10 << 21; |
| let carry12: i64 = (s12 + (1 << 20)) >> 21; |
| s13 += carry12; |
| s12 -= carry12 << 21; |
| let carry14: i64 = (s14 + (1 << 20)) >> 21; |
| s15 += carry14; |
| s14 -= carry14 << 21; |
| let carry16: i64 = (s16 + (1 << 20)) >> 21; |
| s17 += carry16; |
| s16 -= carry16 << 21; |
| |
| let mut carry7: i64 = (s7 + (1 << 20)) >> 21; |
| s8 += carry7; |
| s7 -= carry7 << 21; |
| let mut carry9: i64 = (s9 + (1 << 20)) >> 21; |
| s10 += carry9; |
| s9 -= carry9 << 21; |
| let mut carry11: i64 = (s11 + (1 << 20)) >> 21; |
| s12 += carry11; |
| s11 -= carry11 << 21; |
| let carry13: i64 = (s13 + (1 << 20)) >> 21; |
| s14 += carry13; |
| s13 -= carry13 << 21; |
| let carry15: i64 = (s15 + (1 << 20)) >> 21; |
| s16 += carry15; |
| s15 -= carry15 << 21; |
| |
| s5 += s17 * 666643; |
| s6 += s17 * 470296; |
| s7 += s17 * 654183; |
| s8 -= s17 * 997805; |
| s9 += s17 * 136657; |
| s10 -= s17 * 683901; |
| |
| s4 += s16 * 666643; |
| s5 += s16 * 470296; |
| s6 += s16 * 654183; |
| s7 -= s16 * 997805; |
| s8 += s16 * 136657; |
| s9 -= s16 * 683901; |
| |
| s3 += s15 * 666643; |
| s4 += s15 * 470296; |
| s5 += s15 * 654183; |
| s6 -= s15 * 997805; |
| s7 += s15 * 136657; |
| s8 -= s15 * 683901; |
| |
| s2 += s14 * 666643; |
| s3 += s14 * 470296; |
| s4 += s14 * 654183; |
| s5 -= s14 * 997805; |
| s6 += s14 * 136657; |
| s7 -= s14 * 683901; |
| |
| s1 += s13 * 666643; |
| s2 += s13 * 470296; |
| s3 += s13 * 654183; |
| s4 -= s13 * 997805; |
| s5 += s13 * 136657; |
| s6 -= s13 * 683901; |
| |
| s0 += s12 * 666643; |
| s1 += s12 * 470296; |
| s2 += s12 * 654183; |
| s3 -= s12 * 997805; |
| s4 += s12 * 136657; |
| s5 -= s12 * 683901; |
| s12 = 0; |
| |
| let mut carry0: i64 = (s0 + (1 << 20)) >> 21; |
| s1 += carry0; |
| s0 -= carry0 << 21; |
| let mut carry2: i64 = (s2 + (1 << 20)) >> 21; |
| s3 += carry2; |
| s2 -= carry2 << 21; |
| let mut carry4: i64 = (s4 + (1 << 20)) >> 21; |
| s5 += carry4; |
| s4 -= carry4 << 21; |
| carry6 = (s6 + (1 << 20)) >> 21; |
| s7 += carry6; |
| s6 -= carry6 << 21; |
| carry8 = (s8 + (1 << 20)) >> 21; |
| s9 += carry8; |
| s8 -= carry8 << 21; |
| carry10 = (s10 + (1 << 20)) >> 21; |
| s11 += carry10; |
| s10 -= carry10 << 21; |
| |
| let mut carry1: i64 = (s1 + (1 << 20)) >> 21; |
| s2 += carry1; |
| s1 -= carry1 << 21; |
| let mut carry3: i64 = (s3 + (1 << 20)) >> 21; |
| s4 += carry3; |
| s3 -= carry3 << 21; |
| let mut carry5: i64 = (s5 + (1 << 20)) >> 21; |
| s6 += carry5; |
| s5 -= carry5 << 21; |
| carry7 = (s7 + (1 << 20)) >> 21; |
| s8 += carry7; |
| s7 -= carry7 << 21; |
| carry9 = (s9 + (1 << 20)) >> 21; |
| s10 += carry9; |
| s9 -= carry9 << 21; |
| carry11 = (s11 + (1 << 20)) >> 21; |
| s12 += carry11; |
| s11 -= carry11 << 21; |
| |
| s0 += s12 * 666643; |
| s1 += s12 * 470296; |
| s2 += s12 * 654183; |
| s3 -= s12 * 997805; |
| s4 += s12 * 136657; |
| s5 -= s12 * 683901; |
| s12 = 0; |
| |
| carry0 = s0 >> 21; |
| s1 += carry0; |
| s0 -= carry0 << 21; |
| carry1 = s1 >> 21; |
| s2 += carry1; |
| s1 -= carry1 << 21; |
| carry2 = s2 >> 21; |
| s3 += carry2; |
| s2 -= carry2 << 21; |
| carry3 = s3 >> 21; |
| s4 += carry3; |
| s3 -= carry3 << 21; |
| carry4 = s4 >> 21; |
| s5 += carry4; |
| s4 -= carry4 << 21; |
| carry5 = s5 >> 21; |
| s6 += carry5; |
| s5 -= carry5 << 21; |
| carry6 = s6 >> 21; |
| s7 += carry6; |
| s6 -= carry6 << 21; |
| carry7 = s7 >> 21; |
| s8 += carry7; |
| s7 -= carry7 << 21; |
| carry8 = s8 >> 21; |
| s9 += carry8; |
| s8 -= carry8 << 21; |
| carry9 = s9 >> 21; |
| s10 += carry9; |
| s9 -= carry9 << 21; |
| carry10 = s10 >> 21; |
| s11 += carry10; |
| s10 -= carry10 << 21; |
| carry11 = s11 >> 21; |
| s12 += carry11; |
| s11 -= carry11 << 21; |
| |
| s0 += s12 * 666643; |
| s1 += s12 * 470296; |
| s2 += s12 * 654183; |
| s3 -= s12 * 997805; |
| s4 += s12 * 136657; |
| s5 -= s12 * 683901; |
| |
| carry0 = s0 >> 21; |
| s1 += carry0; |
| s0 -= carry0 << 21; |
| carry1 = s1 >> 21; |
| s2 += carry1; |
| s1 -= carry1 << 21; |
| carry2 = s2 >> 21; |
| s3 += carry2; |
| s2 -= carry2 << 21; |
| carry3 = s3 >> 21; |
| s4 += carry3; |
| s3 -= carry3 << 21; |
| carry4 = s4 >> 21; |
| s5 += carry4; |
| s4 -= carry4 << 21; |
| carry5 = s5 >> 21; |
| s6 += carry5; |
| s5 -= carry5 << 21; |
| carry6 = s6 >> 21; |
| s7 += carry6; |
| s6 -= carry6 << 21; |
| carry7 = s7 >> 21; |
| s8 += carry7; |
| s7 -= carry7 << 21; |
| carry8 = s8 >> 21; |
| s9 += carry8; |
| s8 -= carry8 << 21; |
| carry9 = s9 >> 21; |
| s10 += carry9; |
| s9 -= carry9 << 21; |
| carry10 = s10 >> 21; |
| s11 += carry10; |
| s10 -= carry10 << 21; |
| |
| s[0] = (s0 >> 0) as u8; |
| s[1] = (s0 >> 8) as u8; |
| s[2] = ((s0 >> 16) | (s1 << 5)) as u8; |
| s[3] = (s1 >> 3) as u8; |
| s[4] = (s1 >> 11) as u8; |
| s[5] = ((s1 >> 19) | (s2 << 2)) as u8; |
| s[6] = (s2 >> 6) as u8; |
| s[7] = ((s2 >> 14) | (s3 << 7)) as u8; |
| s[8] = (s3 >> 1) as u8; |
| s[9] = (s3 >> 9) as u8; |
| s[10] = ((s3 >> 17) | (s4 << 4)) as u8; |
| s[11] = (s4 >> 4) as u8; |
| s[12] = (s4 >> 12) as u8; |
| s[13] = ((s4 >> 20) | (s5 << 1)) as u8; |
| s[14] = (s5 >> 7) as u8; |
| s[15] = ((s5 >> 15) | (s6 << 6)) as u8; |
| s[16] = (s6 >> 2) as u8; |
| s[17] = (s6 >> 10) as u8; |
| s[18] = ((s6 >> 18) | (s7 << 3)) as u8; |
| s[19] = (s7 >> 5) as u8; |
| s[20] = (s7 >> 13) as u8; |
| s[21] = (s8 >> 0) as u8; |
| s[22] = (s8 >> 8) as u8; |
| s[23] = ((s8 >> 16) | (s9 << 5)) as u8; |
| s[24] = (s9 >> 3) as u8; |
| s[25] = (s9 >> 11) as u8; |
| s[26] = ((s9 >> 19) | (s10 << 2)) as u8; |
| s[27] = (s10 >> 6) as u8; |
| s[28] = ((s10 >> 14) | (s11 << 7)) as u8; |
| s[29] = (s11 >> 1) as u8; |
| s[30] = (s11 >> 9) as u8; |
| s[31] = (s11 >> 17) as u8; |
| } |
| |
| #[cfg(feature = "blind-keys")] |
| pub fn sc_mul(a: &[u8], b: &[u8]) -> [u8; 32] { |
| let mut s = [0u8; 32]; |
| sc_muladd(&mut s, a, b, &[0; 32]); |
| s |
| } |
| |
| #[cfg(feature = "blind-keys")] |
| pub fn sc_sq(s: &[u8]) -> [u8; 32] { |
| sc_mul(s, s) |
| } |
| |
| #[cfg(feature = "blind-keys")] |
| pub fn sc_sqmul(s: &[u8], n: usize, a: &[u8]) -> [u8; 32] { |
| let mut t = [0u8; 32]; |
| t.copy_from_slice(s); |
| for _ in 0..n { |
| t = sc_sq(&t); |
| } |
| sc_mul(&t, a) |
| } |
| |
| #[cfg(feature = "blind-keys")] |
| pub fn sc_invert(s: &[u8; 32]) -> [u8; 32] { |
| let _10 = sc_sq(s); |
| let _11 = sc_mul(s, &_10); |
| let _100 = sc_mul(s, &_11); |
| let _1000 = sc_sq(&_100); |
| let _1010 = sc_mul(&_10, &_1000); |
| let _1011 = sc_mul(s, &_1010); |
| let _10000 = sc_sq(&_1000); |
| let _10110 = sc_sq(&_1011); |
| let _100000 = sc_mul(&_1010, &_10110); |
| let _100110 = sc_mul(&_10000, &_10110); |
| let _1000000 = sc_sq(&_100000); |
| let _1010000 = sc_mul(&_10000, &_1000000); |
| let _1010011 = sc_mul(&_11, &_1010000); |
| let _1100011 = sc_mul(&_10000, &_1010011); |
| let _1100111 = sc_mul(&_100, &_1100011); |
| let _1101011 = sc_mul(&_100, &_1100111); |
| let _10010011 = sc_mul(&_1000000, &_1010011); |
| let _10010111 = sc_mul(&_100, &_10010011); |
| let _10111101 = sc_mul(&_100110, &_10010111); |
| let _11010011 = sc_mul(&_10110, &_10111101); |
| let _11100111 = sc_mul(&_1010000, &_10010111); |
| let _11101011 = sc_mul(&_100, &_11100111); |
| let _11110101 = sc_mul(&_1010, &_11101011); |
| |
| let mut recip = sc_mul(&_1011, &_11110101); |
| recip = sc_sqmul(&recip, 126, &_1010011); |
| recip = sc_sqmul(&recip, 9, &_10); |
| recip = sc_mul(&recip, &_11110101); |
| recip = sc_sqmul(&recip, 7, &_1100111); |
| recip = sc_sqmul(&recip, 9, &_11110101); |
| recip = sc_sqmul(&recip, 11, &_10111101); |
| recip = sc_sqmul(&recip, 8, &_11100111); |
| recip = sc_sqmul(&recip, 9, &_1101011); |
| recip = sc_sqmul(&recip, 6, &_1011); |
| recip = sc_sqmul(&recip, 14, &_10010011); |
| recip = sc_sqmul(&recip, 10, &_1100011); |
| recip = sc_sqmul(&recip, 9, &_10010111); |
| recip = sc_sqmul(&recip, 10, &_11110101); |
| recip = sc_sqmul(&recip, 8, &_11010011); |
| recip = sc_sqmul(&recip, 8, &_11101011); |
| recip |
| } |
| |
| pub fn sc_muladd(s: &mut [u8], a: &[u8], b: &[u8], c: &[u8]) { |
| let a0 = 2097151 & load_3i(&a[0..3]); |
| let a1 = 2097151 & (load_4i(&a[2..6]) >> 5); |
| let a2 = 2097151 & (load_3i(&a[5..8]) >> 2); |
| let a3 = 2097151 & (load_4i(&a[7..11]) >> 7); |
| let a4 = 2097151 & (load_4i(&a[10..14]) >> 4); |
| let a5 = 2097151 & (load_3i(&a[13..16]) >> 1); |
| let a6 = 2097151 & (load_4i(&a[15..19]) >> 6); |
| let a7 = 2097151 & (load_3i(&a[18..21]) >> 3); |
| let a8 = 2097151 & load_3i(&a[21..24]); |
| let a9 = 2097151 & (load_4i(&a[23..27]) >> 5); |
| let a10 = 2097151 & (load_3i(&a[26..29]) >> 2); |
| let a11 = load_4i(&a[28..32]) >> 7; |
| let b0 = 2097151 & load_3i(&b[0..3]); |
| let b1 = 2097151 & (load_4i(&b[2..6]) >> 5); |
| let b2 = 2097151 & (load_3i(&b[5..8]) >> 2); |
| let b3 = 2097151 & (load_4i(&b[7..11]) >> 7); |
| let b4 = 2097151 & (load_4i(&b[10..14]) >> 4); |
| let b5 = 2097151 & (load_3i(&b[13..16]) >> 1); |
| let b6 = 2097151 & (load_4i(&b[15..19]) >> 6); |
| let b7 = 2097151 & (load_3i(&b[18..21]) >> 3); |
| let b8 = 2097151 & load_3i(&b[21..24]); |
| let b9 = 2097151 & (load_4i(&b[23..27]) >> 5); |
| let b10 = 2097151 & (load_3i(&b[26..29]) >> 2); |
| let b11 = load_4i(&b[28..32]) >> 7; |
| let c0 = 2097151 & load_3i(&c[0..3]); |
| let c1 = 2097151 & (load_4i(&c[2..6]) >> 5); |
| let c2 = 2097151 & (load_3i(&c[5..8]) >> 2); |
| let c3 = 2097151 & (load_4i(&c[7..11]) >> 7); |
| let c4 = 2097151 & (load_4i(&c[10..14]) >> 4); |
| let c5 = 2097151 & (load_3i(&c[13..16]) >> 1); |
| let c6 = 2097151 & (load_4i(&c[15..19]) >> 6); |
| let c7 = 2097151 & (load_3i(&c[18..21]) >> 3); |
| let c8 = 2097151 & load_3i(&c[21..24]); |
| let c9 = 2097151 & (load_4i(&c[23..27]) >> 5); |
| let c10 = 2097151 & (load_3i(&c[26..29]) >> 2); |
| let c11 = load_4i(&c[28..32]) >> 7; |
| |
| let mut s0: i64 = c0 + a0 * b0; |
| let mut s1: i64 = c1 + a0 * b1 + a1 * b0; |
| let mut s2: i64 = c2 + a0 * b2 + a1 * b1 + a2 * b0; |
| let mut s3: i64 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; |
| let mut s4: i64 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; |
| let mut s5: i64 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; |
| let mut s6: i64 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; |
| let mut s7: i64 = |
| c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0; |
| let mut s8: i64 = c8 |
| + a0 * b8 |
| + a1 * b7 |
| + a2 * b6 |
| + a3 * b5 |
| + a4 * b4 |
| + a5 * b3 |
| + a6 * b2 |
| + a7 * b1 |
| + a8 * b0; |
| let mut s9: i64 = c9 |
| + a0 * b9 |
| + a1 * b8 |
| + a2 * b7 |
| + a3 * b6 |
| + a4 * b5 |
| + a5 * b4 |
| + a6 * b3 |
| + a7 * b2 |
| + a8 * b1 |
| + a9 * b0; |
| let mut s10: i64 = c10 |
| + a0 * b10 |
| + a1 * b9 |
| + a2 * b8 |
| + a3 * b7 |
| + a4 * b6 |
| + a5 * b5 |
| + a6 * b4 |
| + a7 * b3 |
| + a8 * b2 |
| + a9 * b1 |
| + a10 * b0; |
| let mut s11: i64 = c11 |
| + a0 * b11 |
| + a1 * b10 |
| + a2 * b9 |
| + a3 * b8 |
| + a4 * b7 |
| + a5 * b6 |
| + a6 * b5 |
| + a7 * b4 |
| + a8 * b3 |
| + a9 * b2 |
| + a10 * b1 |
| + a11 * b0; |
| let mut s12: i64 = a1 * b11 |
| + a2 * b10 |
| + a3 * b9 |
| + a4 * b8 |
| + a5 * b7 |
| + a6 * b6 |
| + a7 * b5 |
| + a8 * b4 |
| + a9 * b3 |
| + a10 * b2 |
| + a11 * b1; |
| let mut s13: i64 = a2 * b11 |
| + a3 * b10 |
| + a4 * b9 |
| + a5 * b8 |
| + a6 * b7 |
| + a7 * b6 |
| + a8 * b5 |
| + a9 * b4 |
| + a10 * b3 |
| + a11 * b2; |
| let mut s14: i64 = |
| a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3; |
| let mut s15: i64 = |
| a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4; |
| let mut s16: i64 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; |
| let mut s17: i64 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; |
| let mut s18: i64 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; |
| let mut s19: i64 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; |
| let mut s20: i64 = a9 * b11 + a10 * b10 + a11 * b9; |
| let mut s21: i64 = a10 * b11 + a11 * b10; |
| let mut s22: i64 = a11 * b11; |
| let mut s23: i64 = 0; |
| |
| let mut carry0: i64 = (s0 + (1 << 20)) >> 21; |
| s1 += carry0; |
| s0 -= carry0 << 21; |
| let mut carry2: i64 = (s2 + (1 << 20)) >> 21; |
| s3 += carry2; |
| s2 -= carry2 << 21; |
| let mut carry4: i64 = (s4 + (1 << 20)) >> 21; |
| s5 += carry4; |
| s4 -= carry4 << 21; |
| let mut carry6: i64 = (s6 + (1 << 20)) >> 21; |
| s7 += carry6; |
| s6 -= carry6 << 21; |
| let mut carry8: i64 = (s8 + (1 << 20)) >> 21; |
| s9 += carry8; |
| s8 -= carry8 << 21; |
| let mut carry10: i64 = (s10 + (1 << 20)) >> 21; |
| s11 += carry10; |
| s10 -= carry10 << 21; |
| let mut carry12: i64 = (s12 + (1 << 20)) >> 21; |
| s13 += carry12; |
| s12 -= carry12 << 21; |
| let mut carry14: i64 = (s14 + (1 << 20)) >> 21; |
| s15 += carry14; |
| s14 -= carry14 << 21; |
| let mut carry16: i64 = (s16 + (1 << 20)) >> 21; |
| s17 += carry16; |
| s16 -= carry16 << 21; |
| let carry18: i64 = (s18 + (1 << 20)) >> 21; |
| s19 += carry18; |
| s18 -= carry18 << 21; |
| let carry20: i64 = (s20 + (1 << 20)) >> 21; |
| s21 += carry20; |
| s20 -= carry20 << 21; |
| let carry22: i64 = (s22 + (1 << 20)) >> 21; |
| s23 += carry22; |
| s22 -= carry22 << 21; |
| |
| let mut carry1: i64 = (s1 + (1 << 20)) >> 21; |
| s2 += carry1; |
| s1 -= carry1 << 21; |
| let mut carry3: i64 = (s3 + (1 << 20)) >> 21; |
| s4 += carry3; |
| s3 -= carry3 << 21; |
| let mut carry5: i64 = (s5 + (1 << 20)) >> 21; |
| s6 += carry5; |
| s5 -= carry5 << 21; |
| let mut carry7: i64 = (s7 + (1 << 20)) >> 21; |
| s8 += carry7; |
| s7 -= carry7 << 21; |
| let mut carry9: i64 = (s9 + (1 << 20)) >> 21; |
| s10 += carry9; |
| s9 -= carry9 << 21; |
| let mut carry11: i64 = (s11 + (1 << 20)) >> 21; |
| s12 += carry11; |
| s11 -= carry11 << 21; |
| let mut carry13: i64 = (s13 + (1 << 20)) >> 21; |
| s14 += carry13; |
| s13 -= carry13 << 21; |
| let mut carry15: i64 = (s15 + (1 << 20)) >> 21; |
| s16 += carry15; |
| s15 -= carry15 << 21; |
| let carry17: i64 = (s17 + (1 << 20)) >> 21; |
| s18 += carry17; |
| s17 -= carry17 << 21; |
| let carry19: i64 = (s19 + (1 << 20)) >> 21; |
| s20 += carry19; |
| s19 -= carry19 << 21; |
| let carry21: i64 = (s21 + (1 << 20)) >> 21; |
| s22 += carry21; |
| s21 -= carry21 << 21; |
| |
| s11 += s23 * 666643; |
| s12 += s23 * 470296; |
| s13 += s23 * 654183; |
| s14 -= s23 * 997805; |
| s15 += s23 * 136657; |
| s16 -= s23 * 683901; |
| |
| s10 += s22 * 666643; |
| s11 += s22 * 470296; |
| s12 += s22 * 654183; |
| s13 -= s22 * 997805; |
| s14 += s22 * 136657; |
| s15 -= s22 * 683901; |
| |
| s9 += s21 * 666643; |
| s10 += s21 * 470296; |
| s11 += s21 * 654183; |
| s12 -= s21 * 997805; |
| s13 += s21 * 136657; |
| s14 -= s21 * 683901; |
| |
| s8 += s20 * 666643; |
| s9 += s20 * 470296; |
| s10 += s20 * 654183; |
| s11 -= s20 * 997805; |
| s12 += s20 * 136657; |
| s13 -= s20 * 683901; |
| |
| s7 += s19 * 666643; |
| s8 += s19 * 470296; |
| s9 += s19 * 654183; |
| s10 -= s19 * 997805; |
| s11 += s19 * 136657; |
| s12 -= s19 * 683901; |
| |
| s6 += s18 * 666643; |
| s7 += s18 * 470296; |
| s8 += s18 * 654183; |
| s9 -= s18 * 997805; |
| s10 += s18 * 136657; |
| s11 -= s18 * 683901; |
| |
| carry6 = (s6 + (1 << 20)) >> 21; |
| s7 += carry6; |
| s6 -= carry6 << 21; |
| carry8 = (s8 + (1 << 20)) >> 21; |
| s9 += carry8; |
| s8 -= carry8 << 21; |
| carry10 = (s10 + (1 << 20)) >> 21; |
| s11 += carry10; |
| s10 -= carry10 << 21; |
| carry12 = (s12 + (1 << 20)) >> 21; |
| s13 += carry12; |
| s12 -= carry12 << 21; |
| carry14 = (s14 + (1 << 20)) >> 21; |
| s15 += carry14; |
| s14 -= carry14 << 21; |
| carry16 = (s16 + (1 << 20)) >> 21; |
| s17 += carry16; |
| s16 -= carry16 << 21; |
| |
| carry7 = (s7 + (1 << 20)) >> 21; |
| s8 += carry7; |
| s7 -= carry7 << 21; |
| carry9 = (s9 + (1 << 20)) >> 21; |
| s10 += carry9; |
| s9 -= carry9 << 21; |
| carry11 = (s11 + (1 << 20)) >> 21; |
| s12 += carry11; |
| s11 -= carry11 << 21; |
| carry13 = (s13 + (1 << 20)) >> 21; |
| s14 += carry13; |
| s13 -= carry13 << 21; |
| carry15 = (s15 + (1 << 20)) >> 21; |
| s16 += carry15; |
| s15 -= carry15 << 21; |
| |
| s5 += s17 * 666643; |
| s6 += s17 * 470296; |
| s7 += s17 * 654183; |
| s8 -= s17 * 997805; |
| s9 += s17 * 136657; |
| s10 -= s17 * 683901; |
| |
| s4 += s16 * 666643; |
| s5 += s16 * 470296; |
| s6 += s16 * 654183; |
| s7 -= s16 * 997805; |
| s8 += s16 * 136657; |
| s9 -= s16 * 683901; |
| |
| s3 += s15 * 666643; |
| s4 += s15 * 470296; |
| s5 += s15 * 654183; |
| s6 -= s15 * 997805; |
| s7 += s15 * 136657; |
| s8 -= s15 * 683901; |
| |
| s2 += s14 * 666643; |
| s3 += s14 * 470296; |
| s4 += s14 * 654183; |
| s5 -= s14 * 997805; |
| s6 += s14 * 136657; |
| s7 -= s14 * 683901; |
| |
| s1 += s13 * 666643; |
| s2 += s13 * 470296; |
| s3 += s13 * 654183; |
| s4 -= s13 * 997805; |
| s5 += s13 * 136657; |
| s6 -= s13 * 683901; |
| |
| s0 += s12 * 666643; |
| s1 += s12 * 470296; |
| s2 += s12 * 654183; |
| s3 -= s12 * 997805; |
| s4 += s12 * 136657; |
| s5 -= s12 * 683901; |
| s12 = 0; |
| |
| carry0 = (s0 + (1 << 20)) >> 21; |
| s1 += carry0; |
| s0 -= carry0 << 21; |
| carry2 = (s2 + (1 << 20)) >> 21; |
| s3 += carry2; |
| s2 -= carry2 << 21; |
| carry4 = (s4 + (1 << 20)) >> 21; |
| s5 += carry4; |
| s4 -= carry4 << 21; |
| carry6 = (s6 + (1 << 20)) >> 21; |
| s7 += carry6; |
| s6 -= carry6 << 21; |
| carry8 = (s8 + (1 << 20)) >> 21; |
| s9 += carry8; |
| s8 -= carry8 << 21; |
| carry10 = (s10 + (1 << 20)) >> 21; |
| s11 += carry10; |
| s10 -= carry10 << 21; |
| |
| carry1 = (s1 + (1 << 20)) >> 21; |
| s2 += carry1; |
| s1 -= carry1 << 21; |
| carry3 = (s3 + (1 << 20)) >> 21; |
| s4 += carry3; |
| s3 -= carry3 << 21; |
| carry5 = (s5 + (1 << 20)) >> 21; |
| s6 += carry5; |
| s5 -= carry5 << 21; |
| carry7 = (s7 + (1 << 20)) >> 21; |
| s8 += carry7; |
| s7 -= carry7 << 21; |
| carry9 = (s9 + (1 << 20)) >> 21; |
| s10 += carry9; |
| s9 -= carry9 << 21; |
| carry11 = (s11 + (1 << 20)) >> 21; |
| s12 += carry11; |
| s11 -= carry11 << 21; |
| |
| s0 += s12 * 666643; |
| s1 += s12 * 470296; |
| s2 += s12 * 654183; |
| s3 -= s12 * 997805; |
| s4 += s12 * 136657; |
| s5 -= s12 * 683901; |
| s12 = 0; |
| |
| carry0 = s0 >> 21; |
| s1 += carry0; |
| s0 -= carry0 << 21; |
| carry1 = s1 >> 21; |
| s2 += carry1; |
| s1 -= carry1 << 21; |
| carry2 = s2 >> 21; |
| s3 += carry2; |
| s2 -= carry2 << 21; |
| carry3 = s3 >> 21; |
| s4 += carry3; |
| s3 -= carry3 << 21; |
| carry4 = s4 >> 21; |
| s5 += carry4; |
| s4 -= carry4 << 21; |
| carry5 = s5 >> 21; |
| s6 += carry5; |
| s5 -= carry5 << 21; |
| carry6 = s6 >> 21; |
| s7 += carry6; |
| s6 -= carry6 << 21; |
| carry7 = s7 >> 21; |
| s8 += carry7; |
| s7 -= carry7 << 21; |
| carry8 = s8 >> 21; |
| s9 += carry8; |
| s8 -= carry8 << 21; |
| carry9 = s9 >> 21; |
| s10 += carry9; |
| s9 -= carry9 << 21; |
| carry10 = s10 >> 21; |
| s11 += carry10; |
| s10 -= carry10 << 21; |
| carry11 = s11 >> 21; |
| s12 += carry11; |
| s11 -= carry11 << 21; |
| |
| s0 += s12 * 666643; |
| s1 += s12 * 470296; |
| s2 += s12 * 654183; |
| s3 -= s12 * 997805; |
| s4 += s12 * 136657; |
| s5 -= s12 * 683901; |
| |
| carry0 = s0 >> 21; |
| s1 += carry0; |
| s0 -= carry0 << 21; |
| carry1 = s1 >> 21; |
| s2 += carry1; |
| s1 -= carry1 << 21; |
| carry2 = s2 >> 21; |
| s3 += carry2; |
| s2 -= carry2 << 21; |
| carry3 = s3 >> 21; |
| s4 += carry3; |
| s3 -= carry3 << 21; |
| carry4 = s4 >> 21; |
| s5 += carry4; |
| s4 -= carry4 << 21; |
| carry5 = s5 >> 21; |
| s6 += carry5; |
| s5 -= carry5 << 21; |
| carry6 = s6 >> 21; |
| s7 += carry6; |
| s6 -= carry6 << 21; |
| carry7 = s7 >> 21; |
| s8 += carry7; |
| s7 -= carry7 << 21; |
| carry8 = s8 >> 21; |
| s9 += carry8; |
| s8 -= carry8 << 21; |
| carry9 = s9 >> 21; |
| s10 += carry9; |
| s9 -= carry9 << 21; |
| carry10 = s10 >> 21; |
| s11 += carry10; |
| s10 -= carry10 << 21; |
| |
| s[0] = (s0 >> 0) as u8; |
| s[1] = (s0 >> 8) as u8; |
| s[2] = ((s0 >> 16) | (s1 << 5)) as u8; |
| s[3] = (s1 >> 3) as u8; |
| s[4] = (s1 >> 11) as u8; |
| s[5] = ((s1 >> 19) | (s2 << 2)) as u8; |
| s[6] = (s2 >> 6) as u8; |
| s[7] = ((s2 >> 14) | (s3 << 7)) as u8; |
| s[8] = (s3 >> 1) as u8; |
| s[9] = (s3 >> 9) as u8; |
| s[10] = ((s3 >> 17) | (s4 << 4)) as u8; |
| s[11] = (s4 >> 4) as u8; |
| s[12] = (s4 >> 12) as u8; |
| s[13] = ((s4 >> 20) | (s5 << 1)) as u8; |
| s[14] = (s5 >> 7) as u8; |
| s[15] = ((s5 >> 15) | (s6 << 6)) as u8; |
| s[16] = (s6 >> 2) as u8; |
| s[17] = (s6 >> 10) as u8; |
| s[18] = ((s6 >> 18) | (s7 << 3)) as u8; |
| s[19] = (s7 >> 5) as u8; |
| s[20] = (s7 >> 13) as u8; |
| s[21] = (s8 >> 0) as u8; |
| s[22] = (s8 >> 8) as u8; |
| s[23] = ((s8 >> 16) | (s9 << 5)) as u8; |
| s[24] = (s9 >> 3) as u8; |
| s[25] = (s9 >> 11) as u8; |
| s[26] = ((s9 >> 19) | (s10 << 2)) as u8; |
| s[27] = (s10 >> 6) as u8; |
| s[28] = ((s10 >> 14) | (s11 << 7)) as u8; |
| s[29] = (s11 >> 1) as u8; |
| s[30] = (s11 >> 9) as u8; |
| s[31] = (s11 >> 17) as u8; |
| } |
| |
| pub fn sc_reject_noncanonical(s: &[u8]) -> Result<(), Error> { |
| static L: [u8; 32] = [ |
| 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, |
| 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x10, |
| ]; |
| if s.len() != 32 { |
| panic!("Invalid compressed length") |
| } |
| let mut c: u8 = 0; |
| let mut n: u8 = 1; |
| |
| let mut i = 31; |
| loop { |
| c |= ((((s[i] as i32) - (L[i] as i32)) >> 8) as u8) & n; |
| n &= ((((s[i] ^ L[i]) as i32) - 1) >> 8) as u8; |
| if i == 0 { |
| break; |
| } |
| i -= 1; |
| } |
| if c != 0 { |
| Ok(()) |
| } else { |
| Err(Error::NonCanonical) |
| } |
| } |
| |
| pub fn is_identity(s: &[u8; 32]) -> bool { |
| let mut c = s[0] ^ 0x01; |
| for i in 1..31 { |
| c |= s[i]; |
| } |
| c |= s[31] & 0x7f; |
| c == 0 |
| } |
| |
| static BI: [GePrecomp; 8] = [ |
| GePrecomp { |
| y_plus_x: Fe([ |
| 1288382639258501, |
| 245678601348599, |
| 269427782077623, |
| 1462984067271730, |
| 137412439391563, |
| ]), |
| y_minus_x: Fe([ |
| 62697248952638, |
| 204681361388450, |
| 631292143396476, |
| 338455783676468, |
| 1213667448819585, |
| ]), |
| xy2d: Fe([ |
| 301289933810280, |
| 1259582250014073, |
| 1422107436869536, |
| 796239922652654, |
| 1953934009299142, |
| ]), |
| }, |
| GePrecomp { |
| y_plus_x: Fe([ |
| 1601611775252272, |
| 1720807796594148, |
| 1132070835939856, |
| 1260455018889551, |
| 2147779492816911, |
| ]), |
| y_minus_x: Fe([ |
| 316559037616741, |
| 2177824224946892, |
| 1459442586438991, |
| 1461528397712656, |
| 751590696113597, |
| ]), |
| xy2d: Fe([ |
| 1850748884277385, |
| 1200145853858453, |
| 1068094770532492, |
| 672251375690438, |
| 1586055907191707, |
| ]), |
| }, |
| GePrecomp { |
| y_plus_x: Fe([ |
| 769950342298419, |
| 132954430919746, |
| 844085933195555, |
| 974092374476333, |
| 726076285546016, |
| ]), |
| y_minus_x: Fe([ |
| 425251763115706, |
| 608463272472562, |
| 442562545713235, |
| 837766094556764, |
| 374555092627893, |
| ]), |
| xy2d: Fe([ |
| 1086255230780037, |
| 274979815921559, |
| 1960002765731872, |
| 929474102396301, |
| 1190409889297339, |
| ]), |
| }, |
| GePrecomp { |
| y_plus_x: Fe([ |
| 665000864555967, |
| 2065379846933859, |
| 370231110385876, |
| 350988370788628, |
| 1233371373142985, |
| ]), |
| y_minus_x: Fe([ |
| 2019367628972465, |
| 676711900706637, |
| 110710997811333, |
| 1108646842542025, |
| 517791959672113, |
| ]), |
| xy2d: Fe([ |
| 965130719900578, |
| 247011430587952, |
| 526356006571389, |
| 91986625355052, |
| 2157223321444601, |
| ]), |
| }, |
| GePrecomp { |
| y_plus_x: Fe([ |
| 1802695059465007, |
| 1664899123557221, |
| 593559490740857, |
| 2160434469266659, |
| 927570450755031, |
| ]), |
| y_minus_x: Fe([ |
| 1725674970513508, |
| 1933645953859181, |
| 1542344539275782, |
| 1767788773573747, |
| 1297447965928905, |
| ]), |
| xy2d: Fe([ |
| 1381809363726107, |
| 1430341051343062, |
| 2061843536018959, |
| 1551778050872521, |
| 2036394857967624, |
| ]), |
| }, |
| GePrecomp { |
| y_plus_x: Fe([ |
| 1970894096313054, |
| 528066325833207, |
| 1619374932191227, |
| 2207306624415883, |
| 1169170329061080, |
| ]), |
| y_minus_x: Fe([ |
| 2070390218572616, |
| 1458919061857835, |
| 624171843017421, |
| 1055332792707765, |
| 433987520732508, |
| ]), |
| xy2d: Fe([ |
| 893653801273833, |
| 1168026499324677, |
| 1242553501121234, |
| 1306366254304474, |
| 1086752658510815, |
| ]), |
| }, |
| GePrecomp { |
| y_plus_x: Fe([ |
| 213454002618221, |
| 939771523987438, |
| 1159882208056014, |
| 317388369627517, |
| 621213314200687, |
| ]), |
| y_minus_x: Fe([ |
| 1971678598905747, |
| 338026507889165, |
| 762398079972271, |
| 655096486107477, |
| 42299032696322, |
| ]), |
| xy2d: Fe([ |
| 177130678690680, |
| 1754759263300204, |
| 1864311296286618, |
| 1180675631479880, |
| 1292726903152791, |
| ]), |
| }, |
| GePrecomp { |
| y_plus_x: Fe([ |
| 1913163449625248, |
| 460779200291993, |
| 2193883288642314, |
| 1008900146920800, |
| 1721983679009502, |
| ]), |
| y_minus_x: Fe([ |
| 1070401523076875, |
| 1272492007800961, |
| 1910153608563310, |
| 2075579521696771, |
| 1191169788841221, |
| ]), |
| xy2d: Fe([ |
| 692896803108118, |
| 500174642072499, |
| 2068223309439677, |
| 1162190621851337, |
| 1426986007309901, |
| ]), |
| }, |
| ]; |