github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/btcec/gensecp256k1.go (about) 1 // Copyright (c) 2014-2015 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 // This file is ignored during the regular build due to the following build tag. 7 // This build tag is set during go generate. 8 // +build gensecp256k1 9 10 package btcec 11 12 // References: 13 // [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone) 14 15 import ( 16 "encoding/binary" 17 "math/big" 18 ) 19 20 // secp256k1BytePoints are dummy points used so the code which generates the 21 // real values can compile. 22 var secp256k1BytePoints = "" 23 24 // getDoublingPoints returns all the possible G^(2^i) for i in 25 // 0..n-1 where n is the curve's bit size (256 in the case of secp256k1) 26 // the coordinates are recorded as Jacobian coordinates. 27 func (curve *KoblitzCurve) getDoublingPoints() [][3]fieldVal { 28 doublingPoints := make([][3]fieldVal, curve.BitSize) 29 30 // initialize px, py, pz to the Jacobian coordinates for the base point 31 px, py := curve.bigAffineToField(curve.Gx, curve.Gy) 32 pz := new(fieldVal).SetInt(1) 33 for i := 0; i < curve.BitSize; i++ { 34 doublingPoints[i] = [3]fieldVal{*px, *py, *pz} 35 // P = 2*P 36 curve.doubleJacobian(px, py, pz, px, py, pz) 37 } 38 return doublingPoints 39 } 40 41 // SerializedBytePoints returns a serialized byte slice which contains all of 42 // the possible points per 8-bit window. This is used to when generating 43 // secp256k1.go. 44 func (curve *KoblitzCurve) SerializedBytePoints() []byte { 45 doublingPoints := curve.getDoublingPoints() 46 47 // Segregate the bits into byte-sized windows 48 serialized := make([]byte, curve.byteSize*256*3*10*4) 49 offset := 0 50 for byteNum := 0; byteNum < curve.byteSize; byteNum++ { 51 // Grab the 8 bits that make up this byte from doublingPoints. 52 startingBit := 8 * (curve.byteSize - byteNum - 1) 53 computingPoints := doublingPoints[startingBit : startingBit+8] 54 55 // Compute all points in this window and serialize them. 56 for i := 0; i < 256; i++ { 57 px, py, pz := new(fieldVal), new(fieldVal), new(fieldVal) 58 for j := 0; j < 8; j++ { 59 if i>>uint(j)&1 == 1 { 60 curve.addJacobian(px, py, pz, &computingPoints[j][0], 61 &computingPoints[j][1], &computingPoints[j][2], px, py, pz) 62 } 63 } 64 for i := 0; i < 10; i++ { 65 binary.LittleEndian.PutUint32(serialized[offset:], px.n[i]) 66 offset += 4 67 } 68 for i := 0; i < 10; i++ { 69 binary.LittleEndian.PutUint32(serialized[offset:], py.n[i]) 70 offset += 4 71 } 72 for i := 0; i < 10; i++ { 73 binary.LittleEndian.PutUint32(serialized[offset:], pz.n[i]) 74 offset += 4 75 } 76 } 77 } 78 79 return serialized 80 } 81 82 // sqrt returns the square root of the provided big integer using Newton's 83 // method. It's only compiled and used during generation of pre-computed 84 // values, so speed is not a huge concern. 85 func sqrt(n *big.Int) *big.Int { 86 // Initial guess = 2^(log_2(n)/2) 87 guess := big.NewInt(2) 88 guess.Exp(guess, big.NewInt(int64(n.BitLen()/2)), nil) 89 90 // Now refine using Newton's method. 91 big2 := big.NewInt(2) 92 prevGuess := big.NewInt(0) 93 for { 94 prevGuess.Set(guess) 95 guess.Add(guess, new(big.Int).Div(n, guess)) 96 guess.Div(guess, big2) 97 if guess.Cmp(prevGuess) == 0 { 98 break 99 } 100 } 101 return guess 102 } 103 104 // EndomorphismVectors runs the first 3 steps of algorithm 3.74 from [GECC] to 105 // generate the linearly independent vectors needed to generate a balanced 106 // length-two representation of a multiplier such that k = k1 + k2λ (mod N) and 107 // returns them. Since the values will always be the same given the fact that N 108 // and λ are fixed, the final results can be accelerated by storing the 109 // precomputed values with the curve. 110 func (curve *KoblitzCurve) EndomorphismVectors() (a1, b1, a2, b2 *big.Int) { 111 bigMinus1 := big.NewInt(-1) 112 113 // This section uses an extended Euclidean algorithm to generate a 114 // sequence of equations: 115 // s[i] * N + t[i] * λ = r[i] 116 117 nSqrt := sqrt(curve.N) 118 u, v := new(big.Int).Set(curve.N), new(big.Int).Set(curve.lambda) 119 x1, y1 := big.NewInt(1), big.NewInt(0) 120 x2, y2 := big.NewInt(0), big.NewInt(1) 121 q, r := new(big.Int), new(big.Int) 122 qu, qx1, qy1 := new(big.Int), new(big.Int), new(big.Int) 123 s, t := new(big.Int), new(big.Int) 124 ri, ti := new(big.Int), new(big.Int) 125 a1, b1, a2, b2 = new(big.Int), new(big.Int), new(big.Int), new(big.Int) 126 found, oneMore := false, false 127 for u.Sign() != 0 { 128 // q = v/u 129 q.Div(v, u) 130 131 // r = v - q*u 132 qu.Mul(q, u) 133 r.Sub(v, qu) 134 135 // s = x2 - q*x1 136 qx1.Mul(q, x1) 137 s.Sub(x2, qx1) 138 139 // t = y2 - q*y1 140 qy1.Mul(q, y1) 141 t.Sub(y2, qy1) 142 143 // v = u, u = r, x2 = x1, x1 = s, y2 = y1, y1 = t 144 v.Set(u) 145 u.Set(r) 146 x2.Set(x1) 147 x1.Set(s) 148 y2.Set(y1) 149 y1.Set(t) 150 151 // As soon as the remainder is less than the sqrt of n, the 152 // values of a1 and b1 are known. 153 if !found && r.Cmp(nSqrt) < 0 { 154 // When this condition executes ri and ti represent the 155 // r[i] and t[i] values such that i is the greatest 156 // index for which r >= sqrt(n). Meanwhile, the current 157 // r and t values are r[i+1] and t[i+1], respectively. 158 159 // a1 = r[i+1], b1 = -t[i+1] 160 a1.Set(r) 161 b1.Mul(t, bigMinus1) 162 found = true 163 oneMore = true 164 165 // Skip to the next iteration so ri and ti are not 166 // modified. 167 continue 168 169 } else if oneMore { 170 // When this condition executes ri and ti still 171 // represent the r[i] and t[i] values while the current 172 // r and t are r[i+2] and t[i+2], respectively. 173 174 // sum1 = r[i]^2 + t[i]^2 175 rSquared := new(big.Int).Mul(ri, ri) 176 tSquared := new(big.Int).Mul(ti, ti) 177 sum1 := new(big.Int).Add(rSquared, tSquared) 178 179 // sum2 = r[i+2]^2 + t[i+2]^2 180 r2Squared := new(big.Int).Mul(r, r) 181 t2Squared := new(big.Int).Mul(t, t) 182 sum2 := new(big.Int).Add(r2Squared, t2Squared) 183 184 // if (r[i]^2 + t[i]^2) <= (r[i+2]^2 + t[i+2]^2) 185 if sum1.Cmp(sum2) <= 0 { 186 // a2 = r[i], b2 = -t[i] 187 a2.Set(ri) 188 b2.Mul(ti, bigMinus1) 189 } else { 190 // a2 = r[i+2], b2 = -t[i+2] 191 a2.Set(r) 192 b2.Mul(t, bigMinus1) 193 } 194 195 // All done. 196 break 197 } 198 199 ri.Set(r) 200 ti.Set(t) 201 } 202 203 return a1, b1, a2, b2 204 }