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.

152 lines
3.8 KiB

  1. package ecc
  2. import (
  3. "bytes"
  4. "errors"
  5. "math/big"
  6. )
  7. // EC is the data structure for the elliptic curve parameters
  8. type EC struct {
  9. A *big.Int
  10. B *big.Int
  11. Q *big.Int
  12. }
  13. // NewEC (y^2 = x^3 + ax + b) mod q, where q is a prime number
  14. func NewEC(a, b, q *big.Int) (ec EC) {
  15. ec.A = a
  16. ec.B = b
  17. ec.Q = q
  18. return ec
  19. }
  20. // At gets a point x in the curve
  21. func (ec *EC) At(x *big.Int) (Point, Point, error) {
  22. if x.Cmp(ec.Q) > 0 {
  23. return Point{}, Point{}, errors.New("x<ec.Q")
  24. }
  25. // y^2 = (x^3 + ax + b) mod q
  26. // y = sqrt (x^3 + ax + b) mod q
  27. // x^3
  28. x3 := new(big.Int).Exp(x, big.NewInt(int64(3)), nil)
  29. // a^x
  30. aX := new(big.Int).Mul(ec.A, x)
  31. // x^3 + a^x
  32. x3aX := new(big.Int).Add(x3, aX)
  33. // x^3 + a^x + b
  34. x3aXb := new(big.Int).Add(x3aX, ec.B)
  35. // y = sqrt (x^3 + ax + b) mod q
  36. y := new(big.Int).ModSqrt(x3aXb, ec.Q)
  37. return Point{x, y}, Point{x, new(big.Int).Sub(ec.Q, y)}, nil
  38. }
  39. // TODO add valid checker point function Valid()
  40. // Neg returns the inverse of the P point on the elliptic curve
  41. func (ec *EC) Neg(p Point) Point {
  42. // TODO get error when point not found on the ec
  43. return Point{p.X, new(big.Int).Sub(ec.Q, p.Y)}
  44. }
  45. // Add adds two points p1 and p2 and gets q, returns the negate of q
  46. func (ec *EC) Add(p1, p2 Point) (Point, error) {
  47. if p1.Equal(ZeroPoint) {
  48. return p2, nil
  49. }
  50. if p2.Equal(ZeroPoint) {
  51. return p1, nil
  52. }
  53. var numerator, denominator, sRaw, s *big.Int
  54. if bytes.Equal(p1.X.Bytes(), p2.X.Bytes()) && (!bytes.Equal(p1.Y.Bytes(), p2.Y.Bytes()) || bytes.Equal(p1.Y.Bytes(), BigZero.Bytes())) {
  55. return ZeroPoint, nil
  56. } else if bytes.Equal(p1.X.Bytes(), p2.X.Bytes()) {
  57. // use tangent as slope
  58. // x^2
  59. x2 := new(big.Int).Mul(p1.X, p1.X)
  60. // 3 * x^2
  61. x23 := new(big.Int).Mul(big.NewInt(int64(3)), x2)
  62. // 3 * x^2 + a
  63. numerator = new(big.Int).Add(x23, ec.A)
  64. // 2 * y
  65. denominator = new(big.Int).Mul(big.NewInt(int64(2)), p1.Y)
  66. // s = (3 * x^2 + a) / (2 * y) mod ec.Q
  67. denInv := new(big.Int).ModInverse(denominator, ec.Q)
  68. sRaw = new(big.Int).Mul(numerator, denInv)
  69. s = new(big.Int).Mod(sRaw, ec.Q)
  70. } else {
  71. // slope
  72. // y0-y1
  73. numerator = new(big.Int).Sub(p1.Y, p2.Y)
  74. // x0-x1
  75. denominator = new(big.Int).Sub(p1.X, p2.X)
  76. // s = (y0-y1) / (x0-x1) mod ec.Q
  77. denInv := new(big.Int).ModInverse(denominator, ec.Q)
  78. sRaw = new(big.Int).Mul(numerator, denInv)
  79. s = new(big.Int).Mod(sRaw, ec.Q)
  80. }
  81. // q: new point
  82. var q Point
  83. // s^2
  84. s2 := new(big.Int).Exp(s, big.NewInt(int64(2)), nil)
  85. // s^2 - p1.X
  86. x2Xo := new(big.Int).Sub(s2, p1.X)
  87. // s^2 - p1.X - p2.X
  88. x2XoX2 := new(big.Int).Sub(x2Xo, p2.X)
  89. q.X = new(big.Int).Mod(x2XoX2, ec.Q)
  90. // p1.X - q.X
  91. xoX2 := new(big.Int).Sub(p1.X, q.X)
  92. // s(p1.X - q.X)
  93. sXoX2 := new(big.Int).Mul(s, xoX2)
  94. // s(p1.X - q.X) - p1.Y
  95. sXoX2Y := new(big.Int).Sub(sXoX2, p1.Y)
  96. // q.Y = (s(p1.X - q.X) - p1.Y) mod ec.Q
  97. q.Y = new(big.Int).Mod(sXoX2Y, ec.Q)
  98. // negate q
  99. // q = ec.Neg(q)
  100. return q, nil
  101. }
  102. // Mul multiplies a point n times on the elliptic curve
  103. func (ec *EC) Mul(p Point, n *big.Int) (Point, error) {
  104. var err error
  105. p2 := p
  106. r := ZeroPoint
  107. for BigZero.Cmp(n) == -1 { // 0<n
  108. z := new(big.Int).And(n, BigOne) // n&1
  109. if bytes.Equal(z.Bytes(), BigOne.Bytes()) { // n&1==1
  110. r, err = ec.Add(r, p2)
  111. if err != nil {
  112. return p, err
  113. }
  114. }
  115. n = n.Rsh(n, 1) // n = n>>1
  116. p2, err = ec.Add(p2, p2)
  117. if err != nil {
  118. return p, err
  119. }
  120. }
  121. return r, nil
  122. }
  123. // Order returns smallest n where nG = O (point at zero)
  124. func (ec *EC) Order(g Point) (*big.Int, error) {
  125. // loop from i:=1 to i<ec.Q+1
  126. start := big.NewInt(1)
  127. end := new(big.Int).Add(ec.Q, BigOne)
  128. for i := new(big.Int).Set(start); i.Cmp(end) <= 0; i.Add(i, BigOne) {
  129. iCopy := new(big.Int).SetBytes(i.Bytes())
  130. mPoint, err := ec.Mul(g, iCopy)
  131. if err != nil {
  132. return i, err
  133. }
  134. if mPoint.Equal(ZeroPoint) {
  135. return i, nil
  136. }
  137. }
  138. return BigZero, errors.New("invalid order")
  139. }