You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

curve_impl.go 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package curve25519
  2. import (
  3. "crypto/elliptic"
  4. "math/big"
  5. "sync"
  6. )
  7. var cv25519 cv25519Curve
  8. type cv25519Curve struct {
  9. *elliptic.CurveParams
  10. }
  11. func copyReverse(dst []byte, src []byte) {
  12. // Curve 25519 multiplication functions expect scalars in reverse
  13. // order than PGP. To keep the curve25519Curve type consistent
  14. // with other curves, we reverse it here.
  15. for i, j := 0, len(src)-1; j >= 0 && i < len(dst); i, j = i+1, j-1 {
  16. dst[i] = src[j]
  17. }
  18. }
  19. func copyTruncate(dst []byte, src []byte) {
  20. lenDst, lenSrc := len(dst), len(src)
  21. if lenDst == lenSrc {
  22. copy(dst, src)
  23. } else if lenDst > lenSrc {
  24. copy(dst[lenDst-lenSrc:lenDst], src)
  25. } else if lenDst < lenSrc {
  26. copy(dst, src[:lenDst])
  27. }
  28. }
  29. func (cv25519Curve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) {
  30. // Assume y1 is 0 with cv25519.
  31. var dst [32]byte
  32. var x1Bytes [32]byte
  33. var scalarBytes [32]byte
  34. copyTruncate(x1Bytes[:], x1.Bytes())
  35. copyReverse(scalarBytes[:], scalar)
  36. scalarMult(&dst, &scalarBytes, &x1Bytes)
  37. x = new(big.Int).SetBytes(dst[:])
  38. y = new(big.Int)
  39. return x, y
  40. }
  41. func (cv25519Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
  42. var dst [32]byte
  43. var scalarBytes [32]byte
  44. copyReverse(scalarBytes[:], scalar[:32])
  45. scalarMult(&dst, &scalarBytes, &basePoint)
  46. x = new(big.Int).SetBytes(dst[:])
  47. y = new(big.Int)
  48. return x, y
  49. }
  50. func (cv25519Curve) IsOnCurve(bigX, bigY *big.Int) bool {
  51. return bigY.Sign() == 0 // bigY == 0 ?
  52. }
  53. // More information about 0x40 point format:
  54. // https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-00#section-3
  55. // In addition to uncompressed point format described here:
  56. // https://tools.ietf.org/html/rfc6637#section-6
  57. func (cv25519Curve) MarshalType40(x, y *big.Int) []byte {
  58. byteLen := 32
  59. ret := make([]byte, 1+byteLen)
  60. ret[0] = 0x40
  61. xBytes := x.Bytes()
  62. copyTruncate(ret[1:], xBytes)
  63. return ret
  64. }
  65. func (cv25519Curve) UnmarshalType40(data []byte) (x, y *big.Int) {
  66. if len(data) != 1+32 {
  67. return nil, nil
  68. }
  69. if data[0] != 0x40 {
  70. return nil, nil
  71. }
  72. x = new(big.Int).SetBytes(data[1:])
  73. // Any x is a valid curve point.
  74. return x, new(big.Int)
  75. }
  76. // ToCurve25519 casts given elliptic.Curve type to Curve25519 type, or
  77. // returns nil, false if cast was unsuccessful.
  78. func ToCurve25519(cv elliptic.Curve) (cv25519Curve, bool) {
  79. cv2, ok := cv.(cv25519Curve)
  80. return cv2, ok
  81. }
  82. func initCv25519() {
  83. cv25519.CurveParams = &elliptic.CurveParams{Name: "Curve 25519"}
  84. // Some code relies on these parameters being available for
  85. // checking Curve coordinate length. They should not be used
  86. // directly for any calculations.
  87. cv25519.P, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16)
  88. cv25519.N, _ = new(big.Int).SetString("1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", 16)
  89. cv25519.Gx, _ = new(big.Int).SetString("9", 16)
  90. cv25519.Gy, _ = new(big.Int).SetString("20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9", 16)
  91. cv25519.BitSize = 256
  92. }
  93. var initonce sync.Once
  94. // Cv25519 returns a Curve which (partially) implements Cv25519. Only
  95. // ScalarMult and ScalarBaseMult are valid for this curve. Add and
  96. // Double should not be used.
  97. func Cv25519() elliptic.Curve {
  98. initonce.Do(initCv25519)
  99. return cv25519
  100. }
  101. func (curve cv25519Curve) Params() *elliptic.CurveParams {
  102. return curve.CurveParams
  103. }