scalarmult.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright (c) 2019 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package edwards25519
  5. import "sync"
  6. // basepointTable is a set of 32 affineLookupTables, where table i is generated
  7. // from 256i * basepoint. It is precomputed the first time it's used.
  8. func basepointTable() *[32]affineLookupTable {
  9. basepointTablePrecomp.initOnce.Do(func() {
  10. p := NewGeneratorPoint()
  11. for i := 0; i < 32; i++ {
  12. basepointTablePrecomp.table[i].FromP3(p)
  13. for j := 0; j < 8; j++ {
  14. p.Add(p, p)
  15. }
  16. }
  17. })
  18. return &basepointTablePrecomp.table
  19. }
  20. var basepointTablePrecomp struct {
  21. table [32]affineLookupTable
  22. initOnce sync.Once
  23. }
  24. // ScalarBaseMult sets v = x * B, where B is the canonical generator, and
  25. // returns v.
  26. //
  27. // The scalar multiplication is done in constant time.
  28. func (v *Point) ScalarBaseMult(x *Scalar) *Point {
  29. basepointTable := basepointTable()
  30. // Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i )
  31. // as described in the Ed25519 paper
  32. //
  33. // Group even and odd coefficients
  34. // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
  35. // + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B
  36. // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
  37. // + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B)
  38. //
  39. // We use a lookup table for each i to get x_i*16^(2*i)*B
  40. // and do four doublings to multiply by 16.
  41. digits := x.signedRadix16()
  42. multiple := &affineCached{}
  43. tmp1 := &projP1xP1{}
  44. tmp2 := &projP2{}
  45. // Accumulate the odd components first
  46. v.Set(NewIdentityPoint())
  47. for i := 1; i < 64; i += 2 {
  48. basepointTable[i/2].SelectInto(multiple, digits[i])
  49. tmp1.AddAffine(v, multiple)
  50. v.fromP1xP1(tmp1)
  51. }
  52. // Multiply by 16
  53. tmp2.FromP3(v) // tmp2 = v in P2 coords
  54. tmp1.Double(tmp2) // tmp1 = 2*v in P1xP1 coords
  55. tmp2.FromP1xP1(tmp1) // tmp2 = 2*v in P2 coords
  56. tmp1.Double(tmp2) // tmp1 = 4*v in P1xP1 coords
  57. tmp2.FromP1xP1(tmp1) // tmp2 = 4*v in P2 coords
  58. tmp1.Double(tmp2) // tmp1 = 8*v in P1xP1 coords
  59. tmp2.FromP1xP1(tmp1) // tmp2 = 8*v in P2 coords
  60. tmp1.Double(tmp2) // tmp1 = 16*v in P1xP1 coords
  61. v.fromP1xP1(tmp1) // now v = 16*(odd components)
  62. // Accumulate the even components
  63. for i := 0; i < 64; i += 2 {
  64. basepointTable[i/2].SelectInto(multiple, digits[i])
  65. tmp1.AddAffine(v, multiple)
  66. v.fromP1xP1(tmp1)
  67. }
  68. return v
  69. }
  70. // ScalarMult sets v = x * q, and returns v.
  71. //
  72. // The scalar multiplication is done in constant time.
  73. func (v *Point) ScalarMult(x *Scalar, q *Point) *Point {
  74. checkInitialized(q)
  75. var table projLookupTable
  76. table.FromP3(q)
  77. // Write x = sum(x_i * 16^i)
  78. // so x*Q = sum( Q*x_i*16^i )
  79. // = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... )
  80. // <------compute inside out---------
  81. //
  82. // We use the lookup table to get the x_i*Q values
  83. // and do four doublings to compute 16*Q
  84. digits := x.signedRadix16()
  85. // Unwrap first loop iteration to save computing 16*identity
  86. multiple := &projCached{}
  87. tmp1 := &projP1xP1{}
  88. tmp2 := &projP2{}
  89. table.SelectInto(multiple, digits[63])
  90. v.Set(NewIdentityPoint())
  91. tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords
  92. for i := 62; i >= 0; i-- {
  93. tmp2.FromP1xP1(tmp1) // tmp2 = (prev) in P2 coords
  94. tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords
  95. tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords
  96. tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords
  97. tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords
  98. tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords
  99. tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords
  100. tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords
  101. v.fromP1xP1(tmp1) // v = 16*(prev) in P3 coords
  102. table.SelectInto(multiple, digits[i])
  103. tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords
  104. }
  105. v.fromP1xP1(tmp1)
  106. return v
  107. }
  108. // basepointNafTable is the nafLookupTable8 for the basepoint.
  109. // It is precomputed the first time it's used.
  110. func basepointNafTable() *nafLookupTable8 {
  111. basepointNafTablePrecomp.initOnce.Do(func() {
  112. basepointNafTablePrecomp.table.FromP3(NewGeneratorPoint())
  113. })
  114. return &basepointNafTablePrecomp.table
  115. }
  116. var basepointNafTablePrecomp struct {
  117. table nafLookupTable8
  118. initOnce sync.Once
  119. }
  120. // VarTimeDoubleScalarBaseMult sets v = a * A + b * B, where B is the canonical
  121. // generator, and returns v.
  122. //
  123. // Execution time depends on the inputs.
  124. func (v *Point) VarTimeDoubleScalarBaseMult(a *Scalar, A *Point, b *Scalar) *Point {
  125. checkInitialized(A)
  126. // Similarly to the single variable-base approach, we compute
  127. // digits and use them with a lookup table. However, because
  128. // we are allowed to do variable-time operations, we don't
  129. // need constant-time lookups or constant-time digit
  130. // computations.
  131. //
  132. // So we use a non-adjacent form of some width w instead of
  133. // radix 16. This is like a binary representation (one digit
  134. // for each binary place) but we allow the digits to grow in
  135. // magnitude up to 2^{w-1} so that the nonzero digits are as
  136. // sparse as possible. Intuitively, this "condenses" the
  137. // "mass" of the scalar onto sparse coefficients (meaning
  138. // fewer additions).
  139. basepointNafTable := basepointNafTable()
  140. var aTable nafLookupTable5
  141. aTable.FromP3(A)
  142. // Because the basepoint is fixed, we can use a wider NAF
  143. // corresponding to a bigger table.
  144. aNaf := a.nonAdjacentForm(5)
  145. bNaf := b.nonAdjacentForm(8)
  146. // Find the first nonzero coefficient.
  147. i := 255
  148. for j := i; j >= 0; j-- {
  149. if aNaf[j] != 0 || bNaf[j] != 0 {
  150. break
  151. }
  152. }
  153. multA := &projCached{}
  154. multB := &affineCached{}
  155. tmp1 := &projP1xP1{}
  156. tmp2 := &projP2{}
  157. tmp2.Zero()
  158. // Move from high to low bits, doubling the accumulator
  159. // at each iteration and checking whether there is a nonzero
  160. // coefficient to look up a multiple of.
  161. for ; i >= 0; i-- {
  162. tmp1.Double(tmp2)
  163. // Only update v if we have a nonzero coeff to add in.
  164. if aNaf[i] > 0 {
  165. v.fromP1xP1(tmp1)
  166. aTable.SelectInto(multA, aNaf[i])
  167. tmp1.Add(v, multA)
  168. } else if aNaf[i] < 0 {
  169. v.fromP1xP1(tmp1)
  170. aTable.SelectInto(multA, -aNaf[i])
  171. tmp1.Sub(v, multA)
  172. }
  173. if bNaf[i] > 0 {
  174. v.fromP1xP1(tmp1)
  175. basepointNafTable.SelectInto(multB, bNaf[i])
  176. tmp1.AddAffine(v, multB)
  177. } else if bNaf[i] < 0 {
  178. v.fromP1xP1(tmp1)
  179. basepointNafTable.SelectInto(multB, -bNaf[i])
  180. tmp1.SubAffine(v, multB)
  181. }
  182. tmp2.FromP1xP1(tmp1)
  183. }
  184. v.fromP2(tmp2)
  185. return v
  186. }