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