github.com/consensys/gnark-crypto@v0.14.0/internal/generator/ecdsa/template/ecdsa.go.tmpl (about)

     1  import (
     2  	"crypto/aes"
     3  	"crypto/cipher"
     4  	"crypto/rand"
     5  	"crypto/sha512"
     6  	"crypto/subtle"
     7  	{{- if or (eq .Name "secp256k1") (eq .Name "bn254") (eq .Name "stark-curve") }}
     8  	"errors"
     9  	{{- end }}
    10  	"hash"
    11  	"io"
    12  	"math/big"
    13  
    14  	"github.com/consensys/gnark-crypto/ecc/{{ .Name }}"
    15  	"github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr"
    16  	"github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fp"
    17  	"github.com/consensys/gnark-crypto/signature"
    18  )
    19  
    20  const (
    21  	sizeFr         = fr.Bytes
    22  	sizeFrBits     = fr.Bits
    23  	sizeFp         = fp.Bytes
    24  {{- if eq .Name "secp256k1"}}
    25  	sizePublicKey  = 2 * sizeFp
    26  {{- else}}
    27  	sizePublicKey  = sizeFp
    28  {{- end}}
    29  	sizePrivateKey = sizeFr + sizePublicKey
    30  	sizeSignature  = 2 * sizeFr
    31  )
    32  
    33  {{- if or (eq .Name "secp256k1") (eq .Name "bn254") (eq .Name "stark-curve") }}
    34  var (
    35  	// ErrNoSqrtR is returned when x^3+ax+b is not a square in the field. This
    36  	// is used for public key recovery and allows to detect if the signature is
    37  	// valid or not.
    38  	ErrNoSqrtR = errors.New("x^3+ax+b is not a square in the field")
    39  )
    40  {{- end }}
    41  
    42  var order = fr.Modulus()
    43  
    44  // PublicKey represents an ECDSA public key
    45  type PublicKey struct {
    46  	A {{ .CurvePackage }}.G1Affine
    47  }
    48  
    49  // PrivateKey represents an ECDSA private key
    50  type PrivateKey struct {
    51  	PublicKey PublicKey
    52  	scalar    [sizeFr]byte // secret scalar, in big Endian
    53  }
    54  
    55  // Signature represents an ECDSA signature
    56  type Signature struct {
    57  	R, S [sizeFr]byte
    58  }
    59  
    60  var one = new(big.Int).SetInt64(1)
    61  
    62  // randFieldElement returns a random element of the order of the given
    63  // curve using the procedure given in FIPS 186-4, Appendix B.5.1.
    64  func randFieldElement(rand io.Reader) (k *big.Int, err error) {
    65  	b := make([]byte, fr.Bits/8+8)
    66  	_, err = io.ReadFull(rand, b)
    67  	if err != nil {
    68  		return
    69  	}
    70  
    71  	k = new(big.Int).SetBytes(b)
    72  	n := new(big.Int).Sub(order, one)
    73  	k.Mod(k, n)
    74  	k.Add(k, one)
    75  	return
    76  }
    77  
    78  // GenerateKey generates a public and private key pair.
    79  func GenerateKey(rand io.Reader) (*PrivateKey, error) {
    80  
    81  	k, err := randFieldElement(rand)
    82  	if err != nil {
    83  		return nil, err
    84  
    85  	}
    86  
    87      {{- if or (eq .Name "secp256k1") (eq .Name "stark-curve")}}
    88          _, g := {{ .CurvePackage }}.Generators()
    89      {{- else}}
    90          _, _, g, _ := {{ .CurvePackage }}.Generators()
    91      {{- end}}
    92  
    93  	privateKey := new(PrivateKey)
    94  	k.FillBytes(privateKey.scalar[:sizeFr])
    95  	privateKey.PublicKey.A.ScalarMultiplication(&g, k)
    96  	return privateKey, nil
    97  }
    98  
    99  // HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4,
   100  // we use the left-most bits of the hash to match the bit-length of the order of
   101  // the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3.
   102  func HashToInt(hash []byte) *big.Int {
   103  	if len(hash) > sizeFr {
   104  		hash = hash[:sizeFr]
   105      }
   106  	ret := new(big.Int).SetBytes(hash)
   107  	excess := ret.BitLen() - sizeFrBits
   108  	if excess > 0 {
   109  		ret.Rsh(ret, uint(excess))
   110  	}
   111  	return ret
   112  }
   113  
   114  {{- if or (eq .Name "secp256k1") (eq .Name "bn254") (eq .Name "stark-curve") }}
   115  // recoverP recovers the value P (prover commitment) when creating a signature.
   116  // It uses the recovery information v and part of the decomposed signature r. It
   117  // is used internally for recovering the public key.
   118  func recoverP(v uint, r *big.Int) (*{{ .CurvePackage }}.G1Affine, error) {
   119  	if r.Cmp(fr.Modulus()) >= 0 {
   120  		return nil, errors.New("r is larger than modulus")
   121  	}
   122  	if r.Cmp(big.NewInt(0)) <= 0 {
   123  	    return nil, errors.New("r is negative")
   124  	}
   125  	x := new(big.Int).Set(r)
   126  	{{- /* actually we want use a mask which corresponds to maximum cofactor of the curve. But this is when
   127  	we generalize the implementation over arbitrary curve.*/}}
   128  	// if x is r or r+N
   129  	xChoice := (v & 2) >> 1
   130  	// if y is y or -y
   131  	yChoice := v & 1
   132  	// decompose limbs into big.Int value
   133  	// conditional +n based on xChoice
   134  	kn := big.NewInt(int64(xChoice))
   135  	kn.Mul(kn, fr.Modulus())
   136  	x.Add(x, kn)
   137  	// y^2 = x^3+ax+b
   138  	a, b := {{ .CurvePackage }}.CurveCoefficients()
   139  	y := new(big.Int).Exp(x, big.NewInt(3), fp.Modulus())
   140  	if !a.IsZero() {
   141  		y.Add(y, new(big.Int).Mul(a.BigInt(new(big.Int)), x))
   142  	}
   143  	y.Add(y, b.BigInt(new(big.Int)))
   144  	y.Mod(y, fp.Modulus())
   145  	// y = sqrt(y^2)
   146  	if y.ModSqrt(y, fp.Modulus()) == nil {
   147  		// there is no square root, return error constant
   148  		return nil, ErrNoSqrtR
   149  	}
   150  	// check that y has same oddity as defined by v
   151  	if y.Bit(0) != yChoice {
   152  		y = y.Sub(fp.Modulus(), y)
   153  	}
   154  	return &{{ .CurvePackage }}.G1Affine{
   155  		X: *new(fp.Element).SetBigInt(x),
   156  		Y: *new(fp.Element).SetBigInt(y),
   157  	}, nil
   158  }
   159  {{- end}}
   160  
   161  type zr struct{}
   162  
   163  // Read replaces the contents of dst with zeros. It is safe for concurrent use.
   164  func (zr) Read(dst []byte) (n int, err error) {
   165  	for i := range dst {
   166  		dst[i] = 0
   167  	}
   168  	return len(dst), nil
   169  }
   170  
   171  var zeroReader = zr{}
   172  
   173  const (
   174  	aesIV = "gnark-crypto IV." // must be 16 chars (equal block size)
   175  )
   176  
   177  func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) {
   178  	// This implementation derives the nonce from an AES-CTR CSPRNG keyed by:
   179  	//
   180  	//    SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32]
   181  	//
   182  	// The CSPRNG key is indifferentiable from a random oracle as shown in
   183  	// [Coron], the AES-CTR stream is indifferentiable from a random oracle
   184  	// under standard cryptographic assumptions (see [Larsson] for examples).
   185  	//
   186  	// [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf
   187  	// [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf
   188  
   189  	// Get 256 bits of entropy from rand.
   190  	entropy := make([]byte, 32)
   191  	_, err = io.ReadFull(rand.Reader, entropy)
   192  	if err != nil {
   193  		return
   194  
   195  	}
   196  
   197  	// Initialize an SHA-512 hash context; digest...
   198  	md := sha512.New()
   199  	md.Write(privateKey.scalar[:sizeFr]) // the private key,
   200  	md.Write(entropy)                   // the entropy,
   201  	md.Write(hash)                      // and the input hash;
   202  	key := md.Sum(nil)[:32]             // and compute ChopMD-256(SHA-512),
   203  	// which is an indifferentiable MAC.
   204  
   205  	// Create an AES-CTR instance to use as a CSPRNG.
   206  	block, _ := aes.NewCipher(key)
   207  
   208  	// Create a CSPRNG that xors a stream of zeros with
   209  	// the output of the AES-CTR instance.
   210  	csprng = &cipher.StreamReader{
   211  		R: zeroReader,
   212  		S: cipher.NewCTR(block, []byte(aesIV)),
   213  	}
   214  
   215  	return csprng, err
   216  }
   217  
   218  // Equal compares 2 public keys
   219  func (pub *PublicKey) Equal(x signature.PublicKey) bool {
   220  	xx, ok := x.(*PublicKey)
   221  	if !ok {
   222  		return false
   223  	}
   224  	bpk := pub.Bytes()
   225  	bxx := xx.Bytes()
   226  	return subtle.ConstantTimeCompare(bpk, bxx) == 1
   227  }
   228  
   229  // Public returns the public key associated to the private key.
   230  func (privKey *PrivateKey) Public() signature.PublicKey {
   231  	var pub PublicKey
   232  	pub.A.Set(&privKey.PublicKey.A)
   233  	return &pub
   234  }
   235  
   236  {{- if or (eq .Name "secp256k1") (eq .Name "bn254") (eq .Name "stark-curve") }}
   237  // SignForRecover performs the ECDSA signature and returns public key recovery information
   238  //
   239  // k ← 𝔽r (random)
   240  // P = k ⋅ g1Gen
   241  // r = x_P (mod order)
   242  // s = k⁻¹ . (m + sk ⋅ r)
   243  // v = (div(x_P, order)<<1) || y_P[-1]
   244  //
   245  // SEC 1, Version 2.0, Section 4.1.3
   246  func (privKey *PrivateKey) SignForRecover(message []byte, hFunc hash.Hash) (v uint, r, s *big.Int, err error) {
   247  	r, s = new(big.Int), new(big.Int)
   248  
   249  	scalar, kInv := new(big.Int), new(big.Int)
   250  	scalar.SetBytes(privKey.scalar[:sizeFr])
   251  	for {
   252  		for {
   253  			csprng, err := nonce(privKey, message)
   254  			if err != nil {
   255  				return 0, nil, nil, err
   256  			}
   257  			k, err := randFieldElement(csprng)
   258  			if err != nil {
   259  				return 0, nil, nil, err
   260  			}
   261  
   262  			var P {{ .CurvePackage }}.G1Affine
   263  			P.ScalarMultiplicationBase(k)
   264  			kInv.ModInverse(k, order)
   265  
   266  			P.X.BigInt(r)
   267  			// set how many times we overflow the scalar field
   268  			v |= (uint(new(big.Int).Div(r, order).Uint64())) << 1
   269  			// set if y is even or odd
   270  			v |= P.Y.BigInt(new(big.Int)).Bit(0)
   271  
   272  			r.Mod(r, order)
   273  			if r.Sign() != 0 {
   274  				break
   275  			}
   276  		}
   277  		s.Mul(r, scalar)
   278  
   279  		var m *big.Int
   280  		if hFunc != nil {
   281  			// compute the hash of the message as an integer
   282  			dataToHash := make([]byte, len(message))
   283  			copy(dataToHash[:], message[:])
   284  			hFunc.Reset()
   285  			_, err := hFunc.Write(dataToHash[:])
   286  			if err != nil {
   287  				return 0, nil, nil, err
   288  			}
   289  			hramBin := hFunc.Sum(nil)
   290  			m = HashToInt(hramBin)
   291  		} else {
   292  			m = HashToInt(message)
   293  		}
   294  
   295  		s.Add(m, s).
   296  			Mul(kInv, s).
   297  			Mod(s, order) // order != 0
   298  		if s.Sign() != 0 {
   299  			break
   300  		}
   301  	}
   302  
   303  	return v, r, s, nil
   304  }
   305  
   306  // Sign performs the ECDSA signature
   307  //
   308  // k ← 𝔽r (random)
   309  // P = k ⋅ g1Gen
   310  // r = x_P (mod order)
   311  // s = k⁻¹ . (m + sk ⋅ r)
   312  // signature = {r, s}
   313  //
   314  // SEC 1, Version 2.0, Section 4.1.3
   315  func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) {
   316  	_, r, s, err := privKey.SignForRecover(message, hFunc)
   317  	if err != nil {
   318  		return nil, err
   319  	}
   320  	var sig Signature
   321  	r.FillBytes(sig.R[:sizeFr])
   322  	s.FillBytes(sig.S[:sizeFr])
   323  
   324  	return sig.Bytes(), nil
   325  }
   326  {{- else }}
   327  // Sign performs the ECDSA signature
   328  //
   329  // k ← 𝔽r (random)
   330  // P = k ⋅ g1Gen
   331  // r = x_P (mod order)
   332  // s = k⁻¹ . (m + sk ⋅ r)
   333  // signature = {r, s}
   334  //
   335  // SEC 1, Version 2.0, Section 4.1.3
   336  func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) {
   337  	scalar, r, s, kInv := new(big.Int), new(big.Int), new(big.Int), new(big.Int)
   338  	scalar.SetBytes(privKey.scalar[:sizeFr])
   339  	for {
   340  		for {
   341  			csprng, err := nonce(privKey, message)
   342  			if err != nil {
   343  				return nil, err
   344  			}
   345  			k, err := randFieldElement(csprng)
   346  			if err != nil {
   347  				return nil, err
   348  			}
   349  
   350  			var P {{ .CurvePackage }}.G1Affine
   351  			P.ScalarMultiplicationBase(k)
   352  			kInv.ModInverse(k, order)
   353  
   354  			P.X.BigInt(r)
   355  
   356  			r.Mod(r, order)
   357  			if r.Sign() != 0 {
   358  				break
   359  			}
   360  		}
   361  		s.Mul(r, scalar)
   362  
   363  		var m *big.Int
   364  		if hFunc != nil {
   365  			// compute the hash of the message as an integer
   366  			dataToHash := make([]byte, len(message))
   367  			copy(dataToHash[:], message[:])
   368  			hFunc.Reset()
   369  			_, err := hFunc.Write(dataToHash[:])
   370  			if err != nil {
   371  				return nil, err
   372  			}
   373  			hramBin := hFunc.Sum(nil)
   374  			m = HashToInt(hramBin)
   375  		} else {
   376  			m = HashToInt(message)
   377  		}
   378  
   379  		s.Add(m, s).
   380  			Mul(kInv, s).
   381  			Mod(s, order) // order != 0
   382  		if s.Sign() != 0 {
   383  			break
   384  		}
   385  	}
   386  
   387  	var sig Signature
   388  	r.FillBytes(sig.R[:sizeFr])
   389  	s.FillBytes(sig.S[:sizeFr])
   390  
   391  	return sig.Bytes(), nil
   392  }
   393  {{- end }}
   394  
   395  // Verify validates the ECDSA signature
   396  //
   397  // R ?= (s⁻¹ ⋅ m ⋅ Base + s⁻¹ ⋅ R ⋅ publiKey)_x
   398  //
   399  // SEC 1, Version 2.0, Section 4.1.4
   400  func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) {
   401  
   402  	// Deserialize the signature
   403  	var sig Signature
   404  	if _, err := sig.SetBytes(sigBin); err != nil {
   405  		return false, err
   406   	}
   407  
   408  	r, s := new(big.Int), new(big.Int)
   409  	r.SetBytes(sig.R[:sizeFr])
   410  	s.SetBytes(sig.S[:sizeFr])
   411  
   412  	sInv := new(big.Int).ModInverse(s, order)
   413  
   414      var m *big.Int
   415  	if hFunc != nil {
   416  		// compute the hash of the message as an integer
   417  		dataToHash := make([]byte, len(message))
   418  		copy(dataToHash[:], message[:])
   419  		hFunc.Reset()
   420  		_, err := hFunc.Write(dataToHash[:])
   421  		if err != nil {
   422  			return false, err
   423  		}
   424  		hramBin := hFunc.Sum(nil)
   425  		m = HashToInt(hramBin)
   426  	} else {
   427  		m = HashToInt(message)
   428   	}
   429  
   430  	u1 := new(big.Int).Mul(m, sInv)
   431  	u1.Mod(u1, order)
   432  	u2 := new(big.Int).Mul(r, sInv)
   433  	u2.Mod(u2, order)
   434       var U {{ .CurvePackage }}.G1Jac
   435  	U.JointScalarMultiplicationBase(&publicKey.A, u1, u2)
   436  
   437  	var z big.Int
   438   	U.Z.Square(&U.Z).
   439  		Inverse(&U.Z).
   440  		Mul(&U.Z, &U.X).
   441  		BigInt(&z)
   442  
   443  	z.Mod(&z, order)
   444  
   445  	return z.Cmp(r) == 0, nil
   446  
   447  }