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.

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