genstatics.go 5.5 KB

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