github.com/consensys/gnark-crypto@v0.14.0/ecc/utils.go (about) 1 package ecc 2 3 import ( 4 "math/big" 5 "math/bits" 6 ) 7 8 //------------------------------------------------------- 9 // Ate loop counter (not used for each curve) 10 11 // NafDecomposition gets the naf decomposition of a big number 12 func NafDecomposition(a *big.Int, result []int8) int { 13 14 var zero, one, two, three big.Int 15 16 one.SetUint64(1) 17 two.SetUint64(2) 18 three.SetUint64(3) 19 20 length := 0 21 22 // some buffers 23 var buf, aCopy big.Int 24 aCopy.Set(a) 25 26 for aCopy.Cmp(&zero) != 0 { 27 28 // if aCopy % 2 == 0 29 buf.And(&aCopy, &one) 30 31 // aCopy even 32 if buf.Cmp(&zero) == 0 { 33 result[length] = 0 34 } else { // aCopy odd 35 buf.And(&aCopy, &three) 36 if buf.Cmp(&three) == 0 { 37 result[length] = -1 38 aCopy.Add(&aCopy, &one) 39 } else { 40 result[length] = 1 41 } 42 } 43 aCopy.Rsh(&aCopy, 1) 44 length++ 45 } 46 return length 47 } 48 49 //------------------------------------------------------- 50 // GLV utils 51 52 // Lattice represents a Z module spanned by V1, V2. 53 // det is the associated determinant. 54 type Lattice struct { 55 V1, V2 [2]big.Int 56 Det, b1, b2 big.Int 57 } 58 59 // PrecomputeLattice res such that res.V1, res.V2 60 // are short vectors satisfying v11+v12.λ=v21+v22.λ=0[r]. 61 // cf https://www.iacr.org/archive/crypto2001/21390189.pdf 62 func PrecomputeLattice(r, lambda *big.Int, res *Lattice) { 63 64 var rst [2][3]big.Int 65 var tmp [3]big.Int 66 var quotient, remainder, sqroot, _r, _t big.Int 67 68 rst[0][0].Set(r) 69 rst[0][1].SetUint64(1) 70 rst[0][2].SetUint64(0) 71 72 rst[1][0].Set(lambda) 73 rst[1][1].SetUint64(0) 74 rst[1][2].SetUint64(1) 75 76 sqroot.Sqrt(r) 77 78 var one big.Int 79 one.SetUint64(1) 80 81 // r_i+1 = r_i-1 - q_i.r_i 82 // s_i+1 = s_i-1 - q_i.s_i 83 // t_i+1 = t_i-1 - q_i.s_i 84 for rst[1][0].Cmp(&sqroot) >= 1 { 85 86 quotient.Div(&rst[0][0], &rst[1][0]) 87 remainder.Mod(&rst[0][0], &rst[1][0]) 88 89 tmp[0].Set(&rst[1][0]) 90 tmp[1].Set(&rst[1][1]) 91 tmp[2].Set(&rst[1][2]) 92 93 rst[1][0].Set(&remainder) 94 rst[1][1].Mul(&rst[1][1], "ient).Sub(&rst[0][1], &rst[1][1]) 95 rst[1][2].Mul(&rst[1][2], "ient).Sub(&rst[0][2], &rst[1][2]) 96 97 rst[0][0].Set(&tmp[0]) 98 rst[0][1].Set(&tmp[1]) 99 rst[0][2].Set(&tmp[2]) 100 } 101 102 quotient.Div(&rst[0][0], &rst[1][0]) 103 remainder.Mod(&rst[0][0], &rst[1][0]) 104 _r.Set(&remainder) 105 _t.Mul(&rst[1][2], "ient).Sub(&rst[0][2], &_t) 106 107 res.V1[0].Set(&rst[1][0]) 108 res.V1[1].Neg(&rst[1][2]) 109 110 // take the shorter of [rst[0][0], rst[0][2]], [_r, _t] 111 tmp[1].Mul(&rst[0][2], &rst[0][2]) 112 tmp[0].Mul(&rst[0][0], &rst[0][0]).Add(&tmp[1], &tmp[0]) 113 tmp[2].Mul(&_r, &_r) 114 tmp[1].Mul(&_t, &_t).Add(&tmp[2], &tmp[1]) 115 if tmp[0].Cmp(&tmp[1]) == 1 { 116 res.V2[0].Set(&_r) 117 res.V2[1].Neg(&_t) 118 } else { 119 res.V2[0].Set(&rst[0][0]) 120 res.V2[1].Neg(&rst[0][2]) 121 } 122 123 // sets determinant 124 tmp[0].Mul(&res.V1[1], &res.V2[0]) 125 res.Det.Mul(&res.V1[0], &res.V2[1]).Sub(&res.Det, &tmp[0]) 126 127 // sets roundings of 2^n*v21/d and 2^n*v11/d (where 2ⁿ > d) 128 n := 2 * uint(((res.Det.BitLen()+32)>>6)<<6) 129 res.b1.Lsh(&res.V2[1], n) 130 rounding(&res.b1, &res.Det, &res.b1) 131 res.b2.Lsh(&res.V1[1], n) 132 rounding(&res.b2, &res.Det, &res.b2) 133 } 134 135 // SplitScalar outputs u,v such that u+vlambda=s[r]. 136 // The method is to view s as (s,0) in ZxZ, and find a close 137 // vector w of (s,0) in <l>, where l is a sub Z-module of 138 // ker((a,b) → a+b.λ[r]): then (u,v)=w-(s,0), and 139 // u+v.λ=s[r]. 140 // cf https://www.iacr.org/archive/crypto2001/21390189.pdf 141 func SplitScalar(s *big.Int, l *Lattice) [2]big.Int { 142 143 var k1, k2 big.Int 144 k1.Mul(s, &l.b1) 145 k2.Mul(s, &l.b2).Neg(&k2) 146 // right-shift instead of division by lattice determinant 147 // this increases the bounds on k1 and k2 by 1 148 // but we check this ScalarMultiplication alg. (not constant-time) 149 n := 2 * uint(((l.Det.BitLen()+32)>>6)<<6) 150 k1.Rsh(&k1, n) 151 k2.Rsh(&k2, n) 152 v := getVector(l, &k1, &k2) 153 v[0].Sub(s, &v[0]) 154 v[1].Neg(&v[1]) 155 return v 156 } 157 158 // sets res to the closest integer from n/d 159 func rounding(n, d, res *big.Int) { 160 var dshift, r, one big.Int 161 one.SetUint64(1) 162 dshift.Rsh(d, 1) 163 r.Mod(n, d) 164 res.Div(n, d) 165 if r.Cmp(&dshift) == 1 { 166 res.Add(res, &one) 167 } 168 } 169 170 // getVector returns aV1 + bV2 171 func getVector(l *Lattice, a, b *big.Int) [2]big.Int { 172 var res [2]big.Int 173 var tmp big.Int 174 tmp.Mul(b, &l.V2[0]) 175 res[0].Mul(a, &l.V1[0]).Add(&res[0], &tmp) 176 tmp.Mul(b, &l.V2[1]) 177 res[1].Mul(a, &l.V1[1]).Add(&res[1], &tmp) 178 return res 179 } 180 181 // NextPowerOfTwo returns the next power of 2 of n 182 func NextPowerOfTwo(n uint64) uint64 { 183 c := bits.OnesCount64(n) 184 if c == 0 { 185 return 1 186 } 187 if c == 1 { 188 return n 189 } 190 t := bits.LeadingZeros64(n) 191 if t == 0 { 192 panic("next power of 2 overflows uint64") 193 } 194 return uint64(1) << (64 - t) 195 }