arnaucube
arnaucube/go-iden3-cryptoPublic Self-hosted repository
go-iden3-crypto/babyjub/eddsa.go
babyjub/eddsa.goRaw
  1// Package babyjub eddsa implements the EdDSA over the BabyJubJub curve
  2//nolint:gomnd
  3package babyjub
  4
  5import (
  6	"crypto/rand"
  7	"database/sql/driver"
  8	"fmt"
  9	"math/big"
 10
 11	"github.com/iden3/go-iden3-crypto/mimc7"
 12	"github.com/iden3/go-iden3-crypto/poseidon"
 13	"github.com/iden3/go-iden3-crypto/utils"
 14)
 15
 16// pruneBuffer prunes the buffer during key generation according to RFC 8032.
 17// https://tools.ietf.org/html/rfc8032#page-13
 18func pruneBuffer(buf *[32]byte) *[32]byte {
 19	buf[0] = buf[0] & 0xF8
 20	buf[31] = buf[31] & 0x7F
 21	buf[31] = buf[31] | 0x40
 22	return buf
 23}
 24
 25// PrivateKey is an EdDSA private key, which is a 32byte buffer.
 26type PrivateKey [32]byte
 27
 28// NewRandPrivKey generates a new random private key (using cryptographically
 29// secure randomness).
 30func NewRandPrivKey() PrivateKey {
 31	var k PrivateKey
 32	_, err := rand.Read(k[:])
 33	if err != nil {
 34		panic(err)
 35	}
 36	return k
 37}
 38
 39// Scalar converts a private key into the scalar value s following the EdDSA
 40// standard, and using blake-512 hash.
 41func (k *PrivateKey) Scalar() *PrivKeyScalar {
 42	s := SkToBigInt(k)
 43	return NewPrivKeyScalar(s)
 44}
 45
 46// SkToBigInt converts a private key into the *big.Int value following the
 47// EdDSA standard, and using blake-512 hash
 48func SkToBigInt(k *PrivateKey) *big.Int {
 49	sBuf := Blake512(k[:])
 50	sBuf32 := [32]byte{}
 51	copy(sBuf32[:], sBuf[:32])
 52	pruneBuffer(&sBuf32)
 53	s := new(big.Int)
 54	utils.SetBigIntFromLEBytes(s, sBuf32[:])
 55	s.Rsh(s, 3)
 56	return s
 57}
 58
 59// Public returns the public key corresponding to a private key.
 60func (k *PrivateKey) Public() *PublicKey {
 61	return k.Scalar().Public()
 62}
 63
 64// PrivKeyScalar represents the scalar s output of a private key
 65type PrivKeyScalar big.Int
 66
 67// NewPrivKeyScalar creates a new PrivKeyScalar from a big.Int
 68func NewPrivKeyScalar(s *big.Int) *PrivKeyScalar {
 69	sk := PrivKeyScalar(*s)
 70	return &sk
 71}
 72
 73// Public returns the public key corresponding to the scalar value s of a
 74// private key.
 75func (s *PrivKeyScalar) Public() *PublicKey {
 76	p := NewPoint().Mul((*big.Int)(s), B8)
 77	pk := PublicKey(*p)
 78	return &pk
 79}
 80
 81// BigInt returns the big.Int corresponding to a PrivKeyScalar.
 82func (s *PrivKeyScalar) BigInt() *big.Int {
 83	return (*big.Int)(s)
 84}
 85
 86// PublicKey represents an EdDSA public key, which is a curve point.
 87type PublicKey Point
 88
 89// MarshalText implements the marshaler for PublicKey
 90func (pk PublicKey) MarshalText() ([]byte, error) {
 91	pkc := pk.Compress()
 92	return utils.Hex(pkc[:]).MarshalText()
 93}
 94
 95// String returns the string representation of the PublicKey
 96func (pk PublicKey) String() string {
 97	pkc := pk.Compress()
 98	return utils.Hex(pkc[:]).String()
 99}
100
101// UnmarshalText implements the unmarshaler for the PublicKey
102func (pk *PublicKey) UnmarshalText(h []byte) error {
103	var pkc PublicKeyComp
104	if err := utils.HexDecodeInto(pkc[:], h); err != nil {
105		return err
106	}
107	pkd, err := pkc.Decompress()
108	if err != nil {
109		return err
110	}
111	*pk = *pkd
112	return nil
113}
114
115// Point returns the Point corresponding to a PublicKey.
116func (pk *PublicKey) Point() *Point {
117	return (*Point)(pk)
118}
119
120// PublicKeyComp represents a compressed EdDSA Public key; it's a compressed curve
121// point.
122type PublicKeyComp [32]byte
123
124// MarshalText implements the marshaler for the PublicKeyComp
125func (pkComp PublicKeyComp) MarshalText() ([]byte, error) {
126	return utils.Hex(pkComp[:]).MarshalText()
127}
128
129// String returns the string representation of the PublicKeyComp
130func (pkComp PublicKeyComp) String() string { return utils.Hex(pkComp[:]).String() }
131
132// UnmarshalText implements the unmarshaler for the PublicKeyComp
133func (pkComp *PublicKeyComp) UnmarshalText(h []byte) error {
134	return utils.HexDecodeInto(pkComp[:], h)
135}
136
137// Compress returns the PublicKeyCompr for the given PublicKey
138func (pk *PublicKey) Compress() PublicKeyComp {
139	return PublicKeyComp((*Point)(pk).Compress())
140}
141
142// Decompress returns the PublicKey for the given PublicKeyComp
143func (pkComp *PublicKeyComp) Decompress() (*PublicKey, error) {
144	point, err := NewPoint().Decompress(*pkComp)
145	if err != nil {
146		return nil, err
147	}
148	pk := PublicKey(*point)
149	return &pk, nil
150}
151
152// Signature represents an EdDSA uncompressed signature.
153type Signature struct {
154	R8 *Point
155	S  *big.Int
156}
157
158// SignatureComp represents a compressed EdDSA signature.
159type SignatureComp [64]byte
160
161// MarshalText implements the marshaler for the SignatureComp
162func (sComp SignatureComp) MarshalText() ([]byte, error) {
163	return utils.Hex(sComp[:]).MarshalText()
164}
165
166// String returns the string representation of the SignatureComp
167func (sComp SignatureComp) String() string { return utils.Hex(sComp[:]).String() }
168
169// UnmarshalText implements the unmarshaler for the SignatureComp
170func (sComp *SignatureComp) UnmarshalText(h []byte) error {
171	return utils.HexDecodeInto(sComp[:], h)
172}
173
174// Compress an EdDSA signature by concatenating the compression of
175// the point R8 and the Little-Endian encoding of S.
176func (s *Signature) Compress() SignatureComp {
177	R8p := s.R8.Compress()
178	Sp := utils.BigIntLEBytes(s.S)
179	buf := [64]byte{}
180	copy(buf[:32], R8p[:])
181	copy(buf[32:], Sp[:])
182	return SignatureComp(buf)
183}
184
185// Decompress a compressed signature into s, and also returns the decompressed
186// signature.  Returns error if the Point decompression fails.
187func (s *Signature) Decompress(buf [64]byte) (*Signature, error) {
188	R8p := [32]byte{}
189	copy(R8p[:], buf[:32])
190	var err error
191	if s.R8, err = NewPoint().Decompress(R8p); err != nil {
192		return nil, err
193	}
194	s.S = utils.SetBigIntFromLEBytes(new(big.Int), buf[32:])
195	return s, nil
196}
197
198// Decompress a compressed signature.  Returns error if the Point decompression
199// fails.
200func (sComp *SignatureComp) Decompress() (*Signature, error) {
201	return new(Signature).Decompress(*sComp)
202}
203
204// Scan implements Scanner for database/sql.
205func (sComp *SignatureComp) Scan(src interface{}) error {
206	srcB, ok := src.([]byte)
207	if !ok {
208		return fmt.Errorf("can't scan %T into Signature", src)
209	}
210	if len(srcB) != 64 {
211		return fmt.Errorf("can't scan []byte of len %d into Signature, want %d", len(srcB), 64)
212	}
213	copy(sComp[:], srcB[:])
214	return nil
215}
216
217// Value implements valuer for database/sql.
218func (sComp SignatureComp) Value() (driver.Value, error) {
219	return sComp[:], nil
220}
221
222// Scan implements Scanner for database/sql.
223func (s *Signature) Scan(src interface{}) error {
224	srcB, ok := src.([]byte)
225	if !ok {
226		return fmt.Errorf("can't scan %T into Signature", src)
227	}
228	if len(srcB) != 64 {
229		return fmt.Errorf("can't scan []byte of len %d into Signature, want %d", len(srcB), 64)
230	}
231	buf := [64]byte{}
232	copy(buf[:], srcB[:])
233	_, err := s.Decompress(buf)
234	return err
235}
236
237// Value implements valuer for database/sql.
238func (s Signature) Value() (driver.Value, error) {
239	comp := s.Compress()
240	return comp[:], nil
241}
242
243// SignMimc7 signs a message encoded as a big.Int in Zq using blake-512 hash
244// for buffer hashing and mimc7 for big.Int hashing.
245func (k *PrivateKey) SignMimc7(msg *big.Int) *Signature {
246	h1 := Blake512(k[:])
247	msgBuf := utils.BigIntLEBytes(msg)
248	msgBuf32 := [32]byte{}
249	copy(msgBuf32[:], msgBuf[:])
250	rBuf := Blake512(append(h1[32:], msgBuf32[:]...))
251	r := utils.SetBigIntFromLEBytes(new(big.Int), rBuf) // r = H(H_{32..63}(k), msg)
252	r.Mod(r, SubOrder)
253	R8 := NewPoint().Mul(r, B8) // R8 = r * 8 * B
254	A := k.Public().Point()
255	hmInput := []*big.Int{R8.X, R8.Y, A.X, A.Y, msg}
256	hm, err := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
257	if err != nil {
258		panic(err)
259	}
260	S := new(big.Int).Lsh(k.Scalar().BigInt(), 3)
261	S = S.Mul(hm, S)
262	S.Add(r, S)
263	S.Mod(S, SubOrder) // S = r + hm * 8 * s
264
265	return &Signature{R8: R8, S: S}
266}
267
268// VerifyMimc7 verifies the signature of a message encoded as a big.Int in Zq
269// using blake-512 hash for buffer hashing and mimc7 for big.Int hashing.
270func (pk *PublicKey) VerifyMimc7(msg *big.Int, sig *Signature) bool {
271	hmInput := []*big.Int{sig.R8.X, sig.R8.Y, pk.X, pk.Y, msg}
272	hm, err := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
273	if err != nil {
274		return false
275	}
276
277	left := NewPoint().Mul(sig.S, B8) // left = s * 8 * B
278	r1 := big.NewInt(8)
279	r1.Mul(r1, hm)
280	right := NewPoint().Mul(r1, pk.Point())
281	rightProj := right.Projective()
282	rightProj.Add(sig.R8.Projective(), rightProj) // right = 8 * R + 8 * hm * A
283	right = rightProj.Affine()
284	return (left.X.Cmp(right.X) == 0) && (left.Y.Cmp(right.Y) == 0)
285}
286
287// SignPoseidon signs a message encoded as a big.Int in Zq using blake-512 hash
288// for buffer hashing and Poseidon for big.Int hashing.
289func (k *PrivateKey) SignPoseidon(msg *big.Int) *Signature {
290	h1 := Blake512(k[:])
291	msgBuf := utils.BigIntLEBytes(msg)
292	msgBuf32 := [32]byte{}
293	copy(msgBuf32[:], msgBuf[:])
294	rBuf := Blake512(append(h1[32:], msgBuf32[:]...))
295	r := utils.SetBigIntFromLEBytes(new(big.Int), rBuf) // r = H(H_{32..63}(k), msg)
296	r.Mod(r, SubOrder)
297	R8 := NewPoint().Mul(r, B8) // R8 = r * 8 * B
298	A := k.Public().Point()
299
300	hmInput := []*big.Int{R8.X, R8.Y, A.X, A.Y, msg}
301	hm, err := poseidon.Hash(hmInput) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
302	if err != nil {
303		panic(err)
304	}
305
306	S := new(big.Int).Lsh(k.Scalar().BigInt(), 3)
307	S = S.Mul(hm, S)
308	S.Add(r, S)
309	S.Mod(S, SubOrder) // S = r + hm * 8 * s
310
311	return &Signature{R8: R8, S: S}
312}
313
314// VerifyPoseidon verifies the signature of a message encoded as a big.Int in Zq
315// using blake-512 hash for buffer hashing and Poseidon for big.Int hashing.
316func (pk *PublicKey) VerifyPoseidon(msg *big.Int, sig *Signature) bool {
317	hmInput := []*big.Int{sig.R8.X, sig.R8.Y, pk.X, pk.Y, msg}
318	hm, err := poseidon.Hash(hmInput) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
319	if err != nil {
320		return false
321	}
322
323	left := NewPoint().Mul(sig.S, B8) // left = s * 8 * B
324	r1 := big.NewInt(8)
325	r1.Mul(r1, hm)
326	right := NewPoint().Mul(r1, pk.Point())
327	rightProj := right.Projective()
328	rightProj.Add(sig.R8.Projective(), rightProj) // right = 8 * R + 8 * hm * A
329	right = rightProj.Affine()
330	return (left.X.Cmp(right.X) == 0) && (left.Y.Cmp(right.Y) == 0)
331}
332
333// Scan implements Scanner for database/sql.
334func (pk *PublicKey) Scan(src interface{}) error {
335	srcB, ok := src.([]byte)
336	if !ok {
337		return fmt.Errorf("can't scan %T into PublicKey", src)
338	}
339	if len(srcB) != 32 {
340		return fmt.Errorf("can't scan []byte of len %d into PublicKey, want %d", len(srcB), 32)
341	}
342	var comp PublicKeyComp
343	copy(comp[:], srcB)
344	decomp, err := comp.Decompress()
345	if err != nil {
346		return err
347	}
348	*pk = *decomp
349	return nil
350}
351
352// Value implements valuer for database/sql.
353func (pk PublicKey) Value() (driver.Value, error) {
354	comp := pk.Compress()
355	return comp[:], nil
356}
357
358// Scan implements Scanner for database/sql.
359func (pkComp *PublicKeyComp) Scan(src interface{}) error {
360	srcB, ok := src.([]byte)
361	if !ok {
362		return fmt.Errorf("can't scan %T into PublicKeyComp", src)
363	}
364	if len(srcB) != 32 {
365		return fmt.Errorf("can't scan []byte of len %d into PublicKeyComp, want %d", len(srcB), 32)
366	}
367	copy(pkComp[:], srcB)
368	return nil
369}
370
371// Value implements valuer for database/sql.
372func (pkComp PublicKeyComp) Value() (driver.Value, error) {
373	return pkComp[:], nil
374}