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