curve25519.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2012 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. // We have a implementation in amd64 assembly so this code is only run on
  5. // non-amd64 platforms.
  6. // +build !amd64
  7. package curve25519
  8. import (
  9. "math/big"
  10. )
  11. // p is the prime order of the underlying field: 2^255-19
  12. var p *big.Int
  13. // pMinus2 is p-2
  14. var pMinus2 *big.Int
  15. // a is a parameter of the elliptic curve: 486662
  16. var a *big.Int
  17. func init() {
  18. p, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16)
  19. pMinus2, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb", 16)
  20. a = new(big.Int).SetInt64(486662)
  21. }
  22. // context contains state shared throughout the computation, including scratch
  23. // variables to save on allocation.
  24. type context struct {
  25. tmp1, tmp2, tmp3, tmp4 *big.Int
  26. x1 *big.Int
  27. }
  28. // add sets (outx, outz) to the sum of two points in the elliptic curve group.
  29. // See http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m
  30. // outx and outz should not alias any of the other inputs.
  31. func (c *context) add(outx, outz, xn, zn, xm, zm *big.Int) {
  32. // x₃ = 4(x·x′ - z·z′)² · z1
  33. // (z1 == 1 here)
  34. c.tmp1.Mul(xn, xm)
  35. c.tmp2.Mul(zn, zm)
  36. c.tmp3.Sub(c.tmp1, c.tmp2)
  37. outx.Mul(c.tmp3, c.tmp3)
  38. outx.Lsh(outx, 2)
  39. outx.Mod(outx, p)
  40. // z₃ = 4(x·z′ - z·x′)² · x1
  41. // (x1 == 1 here)
  42. c.tmp1.Mul(xm, zn)
  43. c.tmp2.Mul(zm, xn)
  44. c.tmp3.Sub(c.tmp1, c.tmp2)
  45. outz.Mul(c.tmp3, c.tmp3)
  46. outz.Mul(outz, c.x1)
  47. outz.Lsh(outz, 2)
  48. outz.Mod(outz, p)
  49. return
  50. }
  51. // double sets (outx, outz) to 2*(x,z) in the elliptic curve group. See
  52. // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m
  53. // outx and outz should not alias any of the other inputs.
  54. func (c *context) double(outx, outz, x, z *big.Int) {
  55. // x₂ = (x² - z²)²
  56. c.tmp1.Mul(x, x)
  57. c.tmp2.Mul(z, z)
  58. c.tmp3.Sub(c.tmp1, c.tmp2)
  59. outx.Mul(c.tmp3, c.tmp3)
  60. outx.Mod(outx, p)
  61. // z₂ = 4xz·(x² + Axz + z²)
  62. c.tmp3.Add(c.tmp1, c.tmp2)
  63. c.tmp1.Mul(x, z)
  64. c.tmp2.Mul(c.tmp1, a)
  65. outz.Add(c.tmp3, c.tmp2)
  66. c.tmp2.Lsh(c.tmp1, 2)
  67. outz.Mul(outz, c.tmp2)
  68. outz.Mod(outz, p)
  69. return
  70. }
  71. func scalarMult(out, in, base *[32]byte) {
  72. var baseReversed, inCopy [32]byte
  73. for i := 0; i < 32; i++ {
  74. baseReversed[31-i] = base[i]
  75. inCopy[i] = in[i]
  76. }
  77. inCopy[31] &= 127
  78. inCopy[31] |= 64
  79. inCopy[0] &= 248
  80. c := &context{new(big.Int), new(big.Int), new(big.Int), new(big.Int), nil}
  81. c.x1 = new(big.Int).SetBytes(baseReversed[:])
  82. x1 := new(big.Int).SetInt64(1)
  83. z1 := new(big.Int)
  84. x2 := new(big.Int).Set(c.x1)
  85. z2 := new(big.Int).SetInt64(1)
  86. outx := new(big.Int)
  87. outz := new(big.Int)
  88. for i := 0; i < 32; i++ {
  89. b := inCopy[31-i]
  90. for j := 0; j < 8; j++ {
  91. if b&0x80 != 0 {
  92. c.add(outx, outz, x1, z1, x2, z2)
  93. x1, z1, outx, outz = outx, outz, x1, z1
  94. c.double(outx, outz, x2, z2)
  95. x2, z2, outx, outz = outx, outz, x2, z2
  96. } else {
  97. c.add(outx, outz, x1, z1, x2, z2)
  98. x2, z2, outx, outz = outx, outz, x2, z2
  99. c.double(outx, outz, x1, z1)
  100. x1, z1, outx, outz = outx, outz, x1, z1
  101. }
  102. b <<= 1
  103. }
  104. }
  105. c.tmp1.Exp(z1, pMinus2, p)
  106. c.tmp2.Mul(x1, c.tmp1)
  107. c.tmp3.Mod(c.tmp2, p)
  108. outReversed := c.tmp3.Bytes()
  109. for i := 0; i < len(outReversed); i++ {
  110. out[i] = outReversed[len(outReversed)-(1+i)]
  111. }
  112. for i := len(outReversed); i < 32; i++ {
  113. out[i] = 0
  114. }
  115. }