本站源代码
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.

114 lines
3.0KB

  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, j = i+1, j-1 {
  16. dst[i] = src[j]
  17. }
  18. }
  19. func (cv25519Curve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) {
  20. // Assume y1 is 0 with cv25519.
  21. var dst [32]byte
  22. var x1Bytes [32]byte
  23. var scalarBytes [32]byte
  24. copy(x1Bytes[:], x1.Bytes()[:32])
  25. copyReverse(scalarBytes[:], scalar[:32])
  26. scalarMult(&dst, &scalarBytes, &x1Bytes)
  27. x = new(big.Int).SetBytes(dst[:])
  28. y = new(big.Int)
  29. return x, y
  30. }
  31. func (cv25519Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
  32. var dst [32]byte
  33. var scalarBytes [32]byte
  34. copyReverse(scalarBytes[:], scalar[:32])
  35. scalarMult(&dst, &scalarBytes, &basePoint)
  36. x = new(big.Int).SetBytes(dst[:])
  37. y = new(big.Int)
  38. return x, y
  39. }
  40. func (cv25519Curve) IsOnCurve(bigX, bigY *big.Int) bool {
  41. return bigY.Sign() == 0 // bigY == 0 ?
  42. }
  43. // More information about 0x40 point format:
  44. // https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-00#section-3
  45. // In addition to uncompressed point format described here:
  46. // https://tools.ietf.org/html/rfc6637#section-6
  47. func (cv25519Curve) MarshalType40(x, y *big.Int) []byte {
  48. byteLen := 32
  49. ret := make([]byte, 1+byteLen)
  50. ret[0] = 0x40
  51. xBytes := x.Bytes()
  52. copy(ret[1+byteLen-len(xBytes):], xBytes)
  53. return ret
  54. }
  55. func (cv25519Curve) UnmarshalType40(data []byte) (x, y *big.Int) {
  56. if len(data) != 1+32 {
  57. return nil, nil
  58. }
  59. if data[0] != 0x40 {
  60. return nil, nil
  61. }
  62. x = new(big.Int).SetBytes(data[1:])
  63. // Any x is a valid curve point.
  64. return x, new(big.Int)
  65. }
  66. // ToCurve25519 casts given elliptic.Curve type to Curve25519 type, or
  67. // returns nil, false if cast was unsuccessful.
  68. func ToCurve25519(cv elliptic.Curve) (cv25519Curve, bool) {
  69. cv2, ok := cv.(cv25519Curve)
  70. return cv2, ok
  71. }
  72. func initCv25519() {
  73. cv25519.CurveParams = &elliptic.CurveParams{Name: "Curve 25519"}
  74. // Some code relies on these parameters being available for
  75. // checking Curve coordinate length. They should not be used
  76. // directly for any calculations.
  77. cv25519.P, _ = new (big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16)
  78. cv25519.N, _ = new (big.Int).SetString("1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", 16)
  79. cv25519.Gx, _ = new (big.Int).SetString("9", 16)
  80. cv25519.Gy, _ = new (big.Int).SetString("20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9", 16)
  81. cv25519.BitSize = 256
  82. }
  83. var initonce sync.Once
  84. // Cv25519 returns a Curve which (partially) implements Cv25519. Only
  85. // ScalarMult and ScalarBaseMult are valid for this curve. Add and
  86. // Double should not be used.
  87. func Cv25519() elliptic.Curve {
  88. initonce.Do(initCv25519)
  89. return cv25519
  90. }
  91. func (curve cv25519Curve) Params() *elliptic.CurveParams {
  92. return curve.CurveParams
  93. }
上海开阖软件有限公司 沪ICP备12045867号-1