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.

136 lines
2.8 KiB

  1. package schnorr
  2. import (
  3. "crypto/rand"
  4. "crypto/sha256"
  5. "math/big"
  6. "github.com/arnaucube/cryptofun/ecc"
  7. )
  8. const (
  9. bits = 512 // 2048
  10. )
  11. // PubK is the public key of the Schnorr scheme
  12. type PubK struct {
  13. P ecc.Point
  14. Q ecc.Point
  15. }
  16. // PrivK is the private key of the Schnorr scheme
  17. type PrivK struct {
  18. PubK PubK
  19. A *big.Int
  20. }
  21. // Schnorr is the data structure for the Schnorr scheme
  22. type Schnorr struct {
  23. EC ecc.EC
  24. D *big.Int // K
  25. G ecc.Point
  26. Q ecc.Point // P
  27. N int // order of curve
  28. }
  29. // Hash calculates a hash concatenating a given message bytes with a given EC Point. H(M||R)
  30. func Hash(m []byte, c ecc.Point) *big.Int {
  31. var b []byte
  32. b = append(b, m...)
  33. cXBytes := c.X.Bytes()
  34. cYBytes := c.Y.Bytes()
  35. b = append(b, cXBytes...)
  36. b = append(b, cYBytes...)
  37. h := sha256.New()
  38. h.Write(b)
  39. hash := h.Sum(nil)
  40. r := new(big.Int).SetBytes(hash)
  41. return r
  42. }
  43. // Gen generates the Schnorr scheme
  44. func Gen(ec ecc.EC, g ecc.Point, r *big.Int) (Schnorr, PrivK, error) {
  45. var err error
  46. var schnorr Schnorr
  47. var sk PrivK
  48. schnorr.EC = ec
  49. schnorr.G = g
  50. sk.PubK.P, _, err = ec.At(r)
  51. if err != nil {
  52. return schnorr, sk, err
  53. }
  54. orderP, err := ec.Order(sk.PubK.P)
  55. if err != nil {
  56. return schnorr, sk, err
  57. }
  58. // rand int between 1 and oerder of P
  59. sk.A, err = rand.Int(rand.Reader, orderP)
  60. if err != nil {
  61. return schnorr, sk, err
  62. }
  63. sk.A = big.NewInt(int64(7))
  64. skACopy := new(big.Int).SetBytes(sk.A.Bytes())
  65. // pk.Q = k x P
  66. sk.PubK.Q, err = ec.Mul(sk.PubK.P, skACopy)
  67. if err != nil {
  68. return schnorr, sk, err
  69. }
  70. return schnorr, sk, nil
  71. }
  72. // Sign performs the signature of the message m with the given private key
  73. func (schnorr Schnorr) Sign(sk PrivK, m []byte) (*big.Int, ecc.Point, error) {
  74. var e *big.Int
  75. orderP, err := schnorr.EC.Order(sk.PubK.P)
  76. if err != nil {
  77. return e, ecc.Point{}, err
  78. }
  79. // rand k <-[1,r]
  80. k, err := rand.Int(rand.Reader, orderP)
  81. if err != nil {
  82. return e, ecc.Point{}, err
  83. }
  84. // R = k x P
  85. rPoint, err := schnorr.EC.Mul(sk.PubK.P, k)
  86. if err != nil {
  87. return e, ecc.Point{}, err
  88. }
  89. // e = H(M||R)
  90. e = Hash(m, rPoint)
  91. // a*e
  92. ae := new(big.Int).Mul(sk.A, e)
  93. // k + a*e
  94. kae := new(big.Int).Add(k, ae)
  95. // k + a*e mod r, where r is order of P
  96. s := new(big.Int).Mod(kae, orderP)
  97. return s, rPoint, nil
  98. }
  99. // Verify checks if the given public key matches with the given signature of the message m, in the given EC
  100. func Verify(ec ecc.EC, pk PubK, m []byte, s *big.Int, rPoint ecc.Point) (bool, error) {
  101. // e = H(M||R)
  102. e := Hash(m, rPoint)
  103. eCopy := new(big.Int).SetBytes(e.Bytes())
  104. // e x Q
  105. eQ, err := ec.Mul(pk.Q, eCopy)
  106. if err != nil {
  107. return false, err
  108. }
  109. // R + e x Q
  110. // reQ, err := schnorr.EC.Add(rPoint, eQ)
  111. // if err != nil {
  112. // return false, err
  113. // }
  114. // s x P
  115. sp, err := ec.Mul(pk.P, s)
  116. // return reQ.Equal(sp), nil
  117. return eQ.Equal(sp), nil
  118. }