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 }