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.

211 lines
6.0 KiB

  1. package babyjub
  2. import (
  3. "crypto/rand"
  4. // "encoding/hex"
  5. // "fmt"
  6. common3 "github.com/iden3/go-iden3/common"
  7. "github.com/iden3/go-iden3/crypto/mimc7"
  8. // "golang.org/x/crypto/blake2b"
  9. "math/big"
  10. )
  11. // pruneBuffer prunes the buffer during key generation according to RFC 8032.
  12. // https://tools.ietf.org/html/rfc8032#page-13
  13. func pruneBuffer(buf *[32]byte) *[32]byte {
  14. buf[0] = buf[0] & 0xF8
  15. buf[31] = buf[31] & 0x7F
  16. buf[31] = buf[31] | 0x40
  17. return buf
  18. }
  19. // PrivateKey is an EdDSA private key, which is a 32byte buffer.
  20. type PrivateKey [32]byte
  21. // NewRandPrivKey generates a new random private key (using cryptographically
  22. // secure randomness).
  23. func NewRandPrivKey() PrivateKey {
  24. var k PrivateKey
  25. _, err := rand.Read(k[:])
  26. if err != nil {
  27. panic(err)
  28. }
  29. return k
  30. }
  31. // Scalar converts a private key into the scalar value s following the EdDSA
  32. // standard, and using blake-512 hash.
  33. func (k *PrivateKey) Scalar() *PrivKeyScalar {
  34. sBuf := Blake512(k[:])
  35. sBuf32 := [32]byte{}
  36. copy(sBuf32[:], sBuf[:32])
  37. pruneBuffer(&sBuf32)
  38. s := new(big.Int)
  39. SetBigIntFromLEBytes(s, sBuf32[:])
  40. s.Rsh(s, 3)
  41. return NewPrivKeyScalar(s)
  42. }
  43. // Pub returns the public key corresponding to a private key.
  44. func (k *PrivateKey) Public() *PublicKey {
  45. return k.Scalar().Public()
  46. }
  47. // PrivKeyScalar represents the scalar s output of a private key
  48. type PrivKeyScalar big.Int
  49. // NewPrivKeyScalar creates a new PrivKeyScalar from a big.Int
  50. func NewPrivKeyScalar(s *big.Int) *PrivKeyScalar {
  51. sk := PrivKeyScalar(*s)
  52. return &sk
  53. }
  54. // Pub returns the public key corresponding to the scalar value s of a private
  55. // key.
  56. func (s *PrivKeyScalar) Public() *PublicKey {
  57. p := NewPoint().Mul((*big.Int)(s), B8)
  58. pk := PublicKey(*p)
  59. return &pk
  60. }
  61. // BigInt returns the big.Int corresponding to a PrivKeyScalar.
  62. func (s *PrivKeyScalar) BigInt() *big.Int {
  63. return (*big.Int)(s)
  64. }
  65. // PublicKey represents an EdDSA public key, which is a curve point.
  66. type PublicKey Point
  67. func (pk PublicKey) MarshalText() ([]byte, error) {
  68. pkc := pk.Compress()
  69. return common3.Hex(pkc[:]).MarshalText()
  70. }
  71. func (pk PublicKey) String() string {
  72. pkc := pk.Compress()
  73. return common3.Hex(pkc[:]).String()
  74. }
  75. func (pk *PublicKey) UnmarshalText(h []byte) error {
  76. var pkc PublicKeyComp
  77. if err := common3.HexDecodeInto(pkc[:], h); err != nil {
  78. return err
  79. }
  80. pkd, err := pkc.Decompress()
  81. if err != nil {
  82. return err
  83. }
  84. *pk = *pkd
  85. return nil
  86. }
  87. // Point returns the Point corresponding to a PublicKey.
  88. func (p *PublicKey) Point() *Point {
  89. return (*Point)(p)
  90. }
  91. // PublicKeyComp represents a compressed EdDSA Public key; it's a compressed curve
  92. // point.
  93. type PublicKeyComp [32]byte
  94. func (buf PublicKeyComp) MarshalText() ([]byte, error) { return common3.Hex(buf[:]).MarshalText() }
  95. func (buf PublicKeyComp) String() string { return common3.Hex(buf[:]).String() }
  96. func (buf *PublicKeyComp) UnmarshalText(h []byte) error { return common3.HexDecodeInto(buf[:], h) }
  97. func (p *PublicKey) Compress() PublicKeyComp {
  98. return PublicKeyComp((*Point)(p).Compress())
  99. }
  100. func (p *PublicKeyComp) Decompress() (*PublicKey, error) {
  101. point, err := NewPoint().Decompress(*p)
  102. if err != nil {
  103. return nil, err
  104. }
  105. pk := PublicKey(*point)
  106. return &pk, nil
  107. }
  108. // Signature represents an EdDSA uncompressed signature.
  109. type Signature struct {
  110. R8 *Point
  111. S *big.Int
  112. }
  113. // SignatureComp represents a compressed EdDSA signature.
  114. type SignatureComp [64]byte
  115. func (buf SignatureComp) MarshalText() ([]byte, error) { return common3.Hex(buf[:]).MarshalText() }
  116. func (buf SignatureComp) String() string { return common3.Hex(buf[:]).String() }
  117. func (buf *SignatureComp) UnmarshalText(h []byte) error { return common3.HexDecodeInto(buf[:], h) }
  118. // Compress an EdDSA signature by concatenating the compression of
  119. // the point R8 and the Little-Endian encoding of S.
  120. func (s *Signature) Compress() SignatureComp {
  121. R8p := s.R8.Compress()
  122. Sp := BigIntLEBytes(s.S)
  123. buf := [64]byte{}
  124. copy(buf[:32], R8p[:])
  125. copy(buf[32:], Sp[:])
  126. return SignatureComp(buf)
  127. }
  128. // Decompress a compressed signature into s, and also returns the decompressed
  129. // signature. Returns error if the Point decompression fails.
  130. func (s *Signature) Decompress(buf [64]byte) (*Signature, error) {
  131. R8p := [32]byte{}
  132. copy(R8p[:], buf[:32])
  133. var err error
  134. if s.R8, err = NewPoint().Decompress(R8p); err != nil {
  135. return nil, err
  136. }
  137. s.S = SetBigIntFromLEBytes(new(big.Int), buf[32:])
  138. return s, nil
  139. }
  140. // Decompress a compressed signature. Returns error if the Point decompression
  141. // fails.
  142. func (s *SignatureComp) Decompress() (*Signature, error) {
  143. return new(Signature).Decompress(*s)
  144. }
  145. // SignMimc7 signs a message encoded as a big.Int in Zq using blake-512 hash
  146. // for buffer hashing and mimc7 for big.Int hashing.
  147. func (k *PrivateKey) SignMimc7(msg *big.Int) *Signature {
  148. h1 := Blake512(k[:])
  149. msgBuf := BigIntLEBytes(msg)
  150. msgBuf32 := [32]byte{}
  151. copy(msgBuf32[:], msgBuf[:])
  152. rBuf := Blake512(append(h1[32:], msgBuf32[:]...))
  153. r := SetBigIntFromLEBytes(new(big.Int), rBuf) // r = H(H_{32..63}(k), msg)
  154. r.Mod(r, SubOrder)
  155. R8 := NewPoint().Mul(r, B8) // R8 = r * 8 * B
  156. A := k.Public().Point()
  157. hmInput, err := mimc7.BigIntsToRElems([]*big.Int{R8.X, R8.Y, A.X, A.Y, msg})
  158. if err != nil {
  159. panic(err)
  160. }
  161. hm := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
  162. S := new(big.Int).Lsh(k.Scalar().BigInt(), 3)
  163. S = S.Mul(hm, S)
  164. S.Add(r, S)
  165. S.Mod(S, SubOrder) // S = r + hm * 8 * s
  166. return &Signature{R8: R8, S: S}
  167. }
  168. // VerifyMimc7 verifies the signature of a message encoded as a big.Int in Zq
  169. // using blake-512 hash for buffer hashing and mimc7 for big.Int hashing.
  170. func (p *PublicKey) VerifyMimc7(msg *big.Int, sig *Signature) bool {
  171. hmInput, err := mimc7.BigIntsToRElems([]*big.Int{sig.R8.X, sig.R8.Y, p.X, p.Y, msg})
  172. if err != nil {
  173. panic(err)
  174. }
  175. hm := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
  176. left := NewPoint().Mul(sig.S, B8) // left = s * 8 * B
  177. r1 := big.NewInt(8)
  178. r1.Mul(r1, hm)
  179. right := NewPoint().Mul(r1, p.Point())
  180. right.Add(sig.R8, right) // right = 8 * R + 8 * hm * A
  181. return (left.X.Cmp(right.X) == 0) && (left.Y.Cmp(right.Y) == 0)
  182. }