curve25519.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright 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 curve25519 provides an implementation of the X25519 function, which
  5. // performs scalar multiplication on the elliptic curve known as Curve25519.
  6. // See RFC 7748.
  7. package curve25519 // import "golang.org/x/crypto/curve25519"
  8. import (
  9. "crypto/subtle"
  10. "errors"
  11. "strconv"
  12. "golang.org/x/crypto/curve25519/internal/field"
  13. )
  14. // ScalarMult sets dst to the product scalar * point.
  15. //
  16. // Deprecated: when provided a low-order point, ScalarMult will set dst to all
  17. // zeroes, irrespective of the scalar. Instead, use the X25519 function, which
  18. // will return an error.
  19. func ScalarMult(dst, scalar, point *[32]byte) {
  20. var e [32]byte
  21. copy(e[:], scalar[:])
  22. e[0] &= 248
  23. e[31] &= 127
  24. e[31] |= 64
  25. var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element
  26. x1.SetBytes(point[:])
  27. x2.One()
  28. x3.Set(&x1)
  29. z3.One()
  30. swap := 0
  31. for pos := 254; pos >= 0; pos-- {
  32. b := e[pos/8] >> uint(pos&7)
  33. b &= 1
  34. swap ^= int(b)
  35. x2.Swap(&x3, swap)
  36. z2.Swap(&z3, swap)
  37. swap = int(b)
  38. tmp0.Subtract(&x3, &z3)
  39. tmp1.Subtract(&x2, &z2)
  40. x2.Add(&x2, &z2)
  41. z2.Add(&x3, &z3)
  42. z3.Multiply(&tmp0, &x2)
  43. z2.Multiply(&z2, &tmp1)
  44. tmp0.Square(&tmp1)
  45. tmp1.Square(&x2)
  46. x3.Add(&z3, &z2)
  47. z2.Subtract(&z3, &z2)
  48. x2.Multiply(&tmp1, &tmp0)
  49. tmp1.Subtract(&tmp1, &tmp0)
  50. z2.Square(&z2)
  51. z3.Mult32(&tmp1, 121666)
  52. x3.Square(&x3)
  53. tmp0.Add(&tmp0, &z3)
  54. z3.Multiply(&x1, &z2)
  55. z2.Multiply(&tmp1, &tmp0)
  56. }
  57. x2.Swap(&x3, swap)
  58. z2.Swap(&z3, swap)
  59. z2.Invert(&z2)
  60. x2.Multiply(&x2, &z2)
  61. copy(dst[:], x2.Bytes())
  62. }
  63. // ScalarBaseMult sets dst to the product scalar * base where base is the
  64. // standard generator.
  65. //
  66. // It is recommended to use the X25519 function with Basepoint instead, as
  67. // copying into fixed size arrays can lead to unexpected bugs.
  68. func ScalarBaseMult(dst, scalar *[32]byte) {
  69. ScalarMult(dst, scalar, &basePoint)
  70. }
  71. const (
  72. // ScalarSize is the size of the scalar input to X25519.
  73. ScalarSize = 32
  74. // PointSize is the size of the point input to X25519.
  75. PointSize = 32
  76. )
  77. // Basepoint is the canonical Curve25519 generator.
  78. var Basepoint []byte
  79. var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  80. func init() { Basepoint = basePoint[:] }
  81. func checkBasepoint() {
  82. if subtle.ConstantTimeCompare(Basepoint, []byte{
  83. 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  84. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  85. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  86. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  87. }) != 1 {
  88. panic("curve25519: global Basepoint value was modified")
  89. }
  90. }
  91. // X25519 returns the result of the scalar multiplication (scalar * point),
  92. // according to RFC 7748, Section 5. scalar, point and the return value are
  93. // slices of 32 bytes.
  94. //
  95. // scalar can be generated at random, for example with crypto/rand. point should
  96. // be either Basepoint or the output of another X25519 call.
  97. //
  98. // If point is Basepoint (but not if it's a different slice with the same
  99. // contents) a precomputed implementation might be used for performance.
  100. func X25519(scalar, point []byte) ([]byte, error) {
  101. // Outline the body of function, to let the allocation be inlined in the
  102. // caller, and possibly avoid escaping to the heap.
  103. var dst [32]byte
  104. return x25519(&dst, scalar, point)
  105. }
  106. func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
  107. var in [32]byte
  108. if l := len(scalar); l != 32 {
  109. return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32")
  110. }
  111. if l := len(point); l != 32 {
  112. return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32")
  113. }
  114. copy(in[:], scalar)
  115. if &point[0] == &Basepoint[0] {
  116. checkBasepoint()
  117. ScalarBaseMult(dst, &in)
  118. } else {
  119. var base, zero [32]byte
  120. copy(base[:], point)
  121. ScalarMult(dst, &in, &base)
  122. if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
  123. return nil, errors.New("bad input point: low order point")
  124. }
  125. }
  126. return dst[:], nil
  127. }