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.

255 lines
7.6 KiB

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