1
2
3
4
5 package ecdsa
6
7 import (
8 "bytes"
9 "crypto/internal/fips140"
10 "crypto/internal/fips140/bigmod"
11 "crypto/internal/fips140/drbg"
12 "crypto/internal/fips140/nistec"
13 "errors"
14 "io"
15 "sync"
16 )
17
18
19
20
21
22 type PrivateKey struct {
23 pub PublicKey
24 d []byte
25 }
26
27 func (priv *PrivateKey) Bytes() []byte {
28 return priv.d
29 }
30
31 func (priv *PrivateKey) PublicKey() *PublicKey {
32 return &priv.pub
33 }
34
35 type PublicKey struct {
36 curve curveID
37 q []byte
38 }
39
40 func (pub *PublicKey) Bytes() []byte {
41 return pub.q
42 }
43
44 type curveID string
45
46 const (
47 p224 curveID = "P-224"
48 p256 curveID = "P-256"
49 p384 curveID = "P-384"
50 p521 curveID = "P-521"
51 )
52
53 type Curve[P Point[P]] struct {
54 curve curveID
55 newPoint func() P
56 ordInverse func([]byte) ([]byte, error)
57 N *bigmod.Modulus
58 nMinus2 []byte
59 }
60
61
62 type Point[P any] interface {
63 *nistec.P224Point | *nistec.P256Point | *nistec.P384Point | *nistec.P521Point
64 Bytes() []byte
65 BytesX() ([]byte, error)
66 SetBytes([]byte) (P, error)
67 ScalarMult(P, []byte) (P, error)
68 ScalarBaseMult([]byte) (P, error)
69 Add(p1, p2 P) P
70 }
71
72 func precomputeParams[P Point[P]](c *Curve[P], order []byte) {
73 var err error
74 c.N, err = bigmod.NewModulus(order)
75 if err != nil {
76 panic(err)
77 }
78 two, _ := bigmod.NewNat().SetBytes([]byte{2}, c.N)
79 c.nMinus2 = bigmod.NewNat().ExpandFor(c.N).Sub(two, c.N).Bytes(c.N)
80 }
81
82 func P224() *Curve[*nistec.P224Point] { return _P224() }
83
84 var _P224 = sync.OnceValue(func() *Curve[*nistec.P224Point] {
85 c := &Curve[*nistec.P224Point]{
86 curve: p224,
87 newPoint: nistec.NewP224Point,
88 }
89 precomputeParams(c, p224Order)
90 return c
91 })
92
93 var p224Order = []byte{
94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
96 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
97 0x5c, 0x5c, 0x2a, 0x3d,
98 }
99
100 func P256() *Curve[*nistec.P256Point] { return _P256() }
101
102 var _P256 = sync.OnceValue(func() *Curve[*nistec.P256Point] {
103 c := &Curve[*nistec.P256Point]{
104 curve: p256,
105 newPoint: nistec.NewP256Point,
106 ordInverse: nistec.P256OrdInverse,
107 }
108 precomputeParams(c, p256Order)
109 return c
110 })
111
112 var p256Order = []byte{
113 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
114 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
115 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84,
116 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51}
117
118 func P384() *Curve[*nistec.P384Point] { return _P384() }
119
120 var _P384 = sync.OnceValue(func() *Curve[*nistec.P384Point] {
121 c := &Curve[*nistec.P384Point]{
122 curve: p384,
123 newPoint: nistec.NewP384Point,
124 }
125 precomputeParams(c, p384Order)
126 return c
127 })
128
129 var p384Order = []byte{
130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf,
134 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a,
135 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73}
136
137 func P521() *Curve[*nistec.P521Point] { return _P521() }
138
139 var _P521 = sync.OnceValue(func() *Curve[*nistec.P521Point] {
140 c := &Curve[*nistec.P521Point]{
141 curve: p521,
142 newPoint: nistec.NewP521Point,
143 }
144 precomputeParams(c, p521Order)
145 return c
146 })
147
148 var p521Order = []byte{0x01, 0xff,
149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
150 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
152 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
153 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b,
154 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0,
155 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
156 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09}
157
158 func NewPrivateKey[P Point[P]](c *Curve[P], D, Q []byte) (*PrivateKey, error) {
159 fips140.RecordApproved()
160 pub, err := NewPublicKey(c, Q)
161 if err != nil {
162 return nil, err
163 }
164 d, err := bigmod.NewNat().SetBytes(D, c.N)
165 if err != nil {
166 return nil, err
167 }
168 priv := &PrivateKey{pub: *pub, d: d.Bytes(c.N)}
169 return priv, nil
170 }
171
172 func NewPublicKey[P Point[P]](c *Curve[P], Q []byte) (*PublicKey, error) {
173
174
175
176 _, err := c.newPoint().SetBytes(Q)
177 if err != nil {
178 return nil, err
179 }
180 return &PublicKey{curve: c.curve, q: Q}, nil
181 }
182
183
184 func GenerateKey[P Point[P]](c *Curve[P], rand io.Reader) (*PrivateKey, error) {
185 fips140.RecordApproved()
186
187 k, Q, err := randomPoint(c, func(b []byte) error {
188 return drbg.ReadWithReader(rand, b)
189 })
190 if err != nil {
191 return nil, err
192 }
193
194 priv := &PrivateKey{
195 pub: PublicKey{
196 curve: c.curve,
197 q: Q.Bytes(),
198 },
199 d: k.Bytes(c.N),
200 }
201 fipsPCT(c, priv)
202 return priv, nil
203 }
204
205
206
207
208
209
210
211 func randomPoint[P Point[P]](c *Curve[P], generate func([]byte) error) (k *bigmod.Nat, p P, err error) {
212 for {
213 b := make([]byte, c.N.Size())
214 if err := generate(b); err != nil {
215 return nil, nil, err
216 }
217
218
219
220
221
222
223
224
225
226
227 if excess := len(b)*8 - c.N.BitLen(); excess > 0 {
228
229
230 if c.curve != p521 {
231 panic("ecdsa: internal error: unexpectedly masking off bits")
232 }
233 b = rightShift(b, excess)
234 }
235
236
237
238
239
240
241 if k, err := bigmod.NewNat().SetBytes(b, c.N); err == nil && k.IsZero() == 0 {
242 p, err := c.newPoint().ScalarBaseMult(k.Bytes(c.N))
243 return k, p, err
244 }
245
246 if testingOnlyRejectionSamplingLooped != nil {
247 testingOnlyRejectionSamplingLooped()
248 }
249 }
250 }
251
252
253
254 var testingOnlyRejectionSamplingLooped func()
255
256
257
258 type Signature struct {
259 R, S []byte
260 }
261
262
263
264
265
266 func Sign[P Point[P], H fips140.Hash](c *Curve[P], h func() H, priv *PrivateKey, rand io.Reader, hash []byte) (*Signature, error) {
267 if priv.pub.curve != c.curve {
268 return nil, errors.New("ecdsa: private key does not match curve")
269 }
270 fips140.RecordApproved()
271 fipsSelfTest()
272
273
274
275
276
277
278 Z := make([]byte, len(priv.d))
279 if err := drbg.ReadWithReader(rand, Z); err != nil {
280 return nil, err
281 }
282
283
284
285
286
287
288
289 drbg := newDRBG(h, Z, nil, blockAlignedPersonalizationString{priv.d, bits2octets(c, hash)})
290
291 return sign(c, priv, drbg, hash)
292 }
293
294
295
296
297
298
299 func SignDeterministic[P Point[P], H fips140.Hash](c *Curve[P], h func() H, priv *PrivateKey, hash []byte) (*Signature, error) {
300 if priv.pub.curve != c.curve {
301 return nil, errors.New("ecdsa: private key does not match curve")
302 }
303 fips140.RecordApproved()
304 fipsSelfTestDeterministic()
305 drbg := newDRBG(h, priv.d, bits2octets(c, hash), nil)
306 return sign(c, priv, drbg, hash)
307 }
308
309
310
311 func bits2octets[P Point[P]](c *Curve[P], hash []byte) []byte {
312 e := bigmod.NewNat()
313 hashToNat(c, e, hash)
314 return e.Bytes(c.N)
315 }
316
317 func signGeneric[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte) (*Signature, error) {
318
319
320 k, R, err := randomPoint(c, func(b []byte) error {
321 drbg.Generate(b)
322 return nil
323 })
324 if err != nil {
325 return nil, err
326 }
327
328
329 kInv := bigmod.NewNat()
330 inverse(c, kInv, k)
331
332 Rx, err := R.BytesX()
333 if err != nil {
334 return nil, err
335 }
336 r, err := bigmod.NewNat().SetOverflowingBytes(Rx, c.N)
337 if err != nil {
338 return nil, err
339 }
340
341
342
343
344 if r.IsZero() == 1 {
345 return nil, errors.New("ecdsa: internal error: r is zero")
346 }
347
348 e := bigmod.NewNat()
349 hashToNat(c, e, hash)
350
351 s, err := bigmod.NewNat().SetBytes(priv.d, c.N)
352 if err != nil {
353 return nil, err
354 }
355 s.Mul(r, c.N)
356 s.Add(e, c.N)
357 s.Mul(kInv, c.N)
358
359
360 if s.IsZero() == 1 {
361 return nil, errors.New("ecdsa: internal error: s is zero")
362 }
363
364 return &Signature{r.Bytes(c.N), s.Bytes(c.N)}, nil
365 }
366
367
368 func inverse[P Point[P]](c *Curve[P], kInv, k *bigmod.Nat) {
369 if c.ordInverse != nil {
370 kBytes, err := c.ordInverse(k.Bytes(c.N))
371
372 if err == nil {
373 _, err := kInv.SetBytes(kBytes, c.N)
374 if err != nil {
375 panic("ecdsa: internal error: ordInverse produced an invalid value")
376 }
377 return
378 }
379 }
380
381
382
383 kInv.Exp(k, c.nMinus2, c.N)
384 }
385
386
387
388 func hashToNat[P Point[P]](c *Curve[P], e *bigmod.Nat, hash []byte) {
389
390
391
392
393 if size := c.N.Size(); len(hash) >= size {
394 hash = hash[:size]
395 if excess := len(hash)*8 - c.N.BitLen(); excess > 0 {
396 hash = rightShift(hash, excess)
397 }
398 }
399 _, err := e.SetOverflowingBytes(hash, c.N)
400 if err != nil {
401 panic("ecdsa: internal error: truncated hash is too long")
402 }
403 }
404
405
406
407
408
409
410 func rightShift(b []byte, shift int) []byte {
411 if shift <= 0 || shift >= 8 {
412 panic("ecdsa: internal error: shift can only be by 1 to 7 bits")
413 }
414 b = bytes.Clone(b)
415 for i := len(b) - 1; i >= 0; i-- {
416 b[i] >>= shift
417 if i > 0 {
418 b[i] |= b[i-1] << (8 - shift)
419 }
420 }
421 return b
422 }
423
424
425
426
427
428
429
430
431 func Verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error {
432 if pub.curve != c.curve {
433 return errors.New("ecdsa: public key does not match curve")
434 }
435 fips140.RecordApproved()
436 fipsSelfTest()
437 return verify(c, pub, hash, sig)
438 }
439
440 func verifyGeneric[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error {
441
442
443 Q, err := c.newPoint().SetBytes(pub.q)
444 if err != nil {
445 return err
446 }
447
448 r, err := bigmod.NewNat().SetBytes(sig.R, c.N)
449 if err != nil {
450 return err
451 }
452 if r.IsZero() == 1 {
453 return errors.New("ecdsa: invalid signature: r is zero")
454 }
455 s, err := bigmod.NewNat().SetBytes(sig.S, c.N)
456 if err != nil {
457 return err
458 }
459 if s.IsZero() == 1 {
460 return errors.New("ecdsa: invalid signature: s is zero")
461 }
462
463 e := bigmod.NewNat()
464 hashToNat(c, e, hash)
465
466
467 w := bigmod.NewNat()
468 inverse(c, w, s)
469
470
471 p1, err := c.newPoint().ScalarBaseMult(e.Mul(w, c.N).Bytes(c.N))
472 if err != nil {
473 return err
474 }
475
476 p2, err := Q.ScalarMult(Q, w.Mul(r, c.N).Bytes(c.N))
477 if err != nil {
478 return err
479 }
480
481 Rx, err := p1.Add(p1, p2).BytesX()
482 if err != nil {
483 return err
484 }
485
486 v, err := bigmod.NewNat().SetOverflowingBytes(Rx, c.N)
487 if err != nil {
488 return err
489 }
490
491 if v.Equal(r) != 1 {
492 return errors.New("ecdsa: signature did not verify")
493 }
494 return nil
495 }
496
View as plain text