1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 // Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as
6 // defined in [FIPS 186-5].
7 //
8 // Signatures generated by this package are not deterministic, but entropy is
9 // mixed with the private key and the message, achieving the same level of
10 // security in case of randomness source failure.
11 //
12 // Operations involving private keys are implemented using constant-time
13 // algorithms, as long as an [elliptic.Curve] returned by [elliptic.P224],
14 // [elliptic.P256], [elliptic.P384], or [elliptic.P521] is used.
15 //
16 // [FIPS 186-5]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
17 package ecdsa
18 19 import (
20 "crypto"
21 "crypto/ecdh"
22 "crypto/elliptic"
23 "crypto/internal/boring"
24 "crypto/internal/boring/bbig"
25 "crypto/internal/fips140/ecdsa"
26 "crypto/internal/fips140/nistec"
27 "crypto/internal/fips140cache"
28 "crypto/internal/fips140hash"
29 "crypto/internal/fips140only"
30 "crypto/internal/randutil"
31 "crypto/sha512"
32 "crypto/subtle"
33 "errors"
34 "io"
35 "math/big"
36 37 "golang.org/x/crypto/cryptobyte"
38 "golang.org/x/crypto/cryptobyte/asn1"
39 )
40 41 // PublicKey represents an ECDSA public key.
42 type PublicKey struct {
43 elliptic.Curve
44 45 // X, Y are the coordinates of the public key point.
46 //
47 // Modifying the raw coordinates can produce invalid keys, and may
48 // invalidate internal optimizations; moreover, [big.Int] methods are not
49 // suitable for operating on cryptographic values. To encode and decode
50 // PublicKey values, use [PublicKey.Bytes] and [ParseUncompressedPublicKey]
51 // or [crypto/x509.MarshalPKIXPublicKey] and [crypto/x509.ParsePKIXPublicKey].
52 // For ECDH, use [crypto/ecdh]. For lower-level elliptic curve operations,
53 // use a third-party module like filippo.io/nistec.
54 //
55 // These fields will be deprecated in Go 1.26.
56 X, Y *big.Int
57 }
58 59 // Any methods implemented on PublicKey might need to also be implemented on
60 // PrivateKey, as the latter embeds the former and will expose its methods.
61 62 // ECDH returns k as a [ecdh.PublicKey]. It returns an error if the key is
63 // invalid according to the definition of [ecdh.Curve.NewPublicKey], or if the
64 // Curve is not supported by crypto/ecdh.
65 func (k *PublicKey) ECDH() (*ecdh.PublicKey, error) {
66 c := curveToECDH(k.Curve)
67 if c == nil {
68 return nil, errors.New("ecdsa: unsupported curve by crypto/ecdh")
69 }
70 if !k.Curve.IsOnCurve(k.X, k.Y) {
71 return nil, errors.New("ecdsa: invalid public key")
72 }
73 return c.NewPublicKey(elliptic.Marshal(k.Curve, k.X, k.Y))
74 }
75 76 // Equal reports whether pub and x have the same value.
77 //
78 // Two keys are only considered to have the same value if they have the same Curve value.
79 // Note that for example [elliptic.P256] and elliptic.P256().Params() are different
80 // values, as the latter is a generic not constant time implementation.
81 func (pub *PublicKey) Equal(x crypto.PublicKey) bool {
82 xx, ok := x.(*PublicKey)
83 if !ok {
84 return false
85 }
86 return bigIntEqual(pub.X, xx.X) && bigIntEqual(pub.Y, xx.Y) &&
87 // Standard library Curve implementations are singletons, so this check
88 // will work for those. Other Curves might be equivalent even if not
89 // singletons, but there is no definitive way to check for that, and
90 // better to err on the side of safety.
91 pub.Curve == xx.Curve
92 }
93 94 // ParseUncompressedPublicKey parses a public key encoded as an uncompressed
95 // point according to SEC 1, Version 2.0, Section 2.3.3 (also known as the X9.62
96 // uncompressed format). It returns an error if the point is not in uncompressed
97 // form, is not on the curve, or is the point at infinity.
98 //
99 // curve must be one of [elliptic.P224], [elliptic.P256], [elliptic.P384], or
100 // [elliptic.P521], or ParseUncompressedPublicKey returns an error.
101 //
102 // ParseUncompressedPublicKey accepts the same format as
103 // [ecdh.Curve.NewPublicKey] does for NIST curves, but returns a [PublicKey]
104 // instead of an [ecdh.PublicKey].
105 //
106 // Note that public keys are more commonly encoded in DER (or PEM) format, which
107 // can be parsed with [crypto/x509.ParsePKIXPublicKey] (and [encoding/pem]).
108 func ParseUncompressedPublicKey(curve elliptic.Curve, data []byte) (*PublicKey, error) {
109 if len(data) < 1 || data[0] != 4 {
110 return nil, errors.New("ecdsa: invalid uncompressed public key")
111 }
112 switch curve {
113 case elliptic.P224():
114 return parseUncompressedPublicKey(ecdsa.P224(), curve, data)
115 case elliptic.P256():
116 return parseUncompressedPublicKey(ecdsa.P256(), curve, data)
117 case elliptic.P384():
118 return parseUncompressedPublicKey(ecdsa.P384(), curve, data)
119 case elliptic.P521():
120 return parseUncompressedPublicKey(ecdsa.P521(), curve, data)
121 default:
122 return nil, errors.New("ecdsa: curve not supported by ParseUncompressedPublicKey")
123 }
124 }
125 126 func parseUncompressedPublicKey[P ecdsa.Point[P]](c *ecdsa.Curve[P], curve elliptic.Curve, data []byte) (*PublicKey, error) {
127 k, err := ecdsa.NewPublicKey(c, data)
128 if err != nil {
129 return nil, err
130 }
131 return publicKeyFromFIPS(curve, k)
132 }
133 134 // Bytes encodes the public key as an uncompressed point according to SEC 1,
135 // Version 2.0, Section 2.3.3 (also known as the X9.62 uncompressed format).
136 // It returns an error if the public key is invalid.
137 //
138 // PublicKey.Curve must be one of [elliptic.P224], [elliptic.P256],
139 // [elliptic.P384], or [elliptic.P521], or Bytes returns an error.
140 //
141 // Bytes returns the same format as [ecdh.PublicKey.Bytes] does for NIST curves.
142 //
143 // Note that public keys are more commonly encoded in DER (or PEM) format, which
144 // can be generated with [crypto/x509.MarshalPKIXPublicKey] (and [encoding/pem]).
145 func (pub *PublicKey) Bytes() ([]byte, error) {
146 switch pub.Curve {
147 case elliptic.P224():
148 return publicKeyBytes(ecdsa.P224(), pub)
149 case elliptic.P256():
150 return publicKeyBytes(ecdsa.P256(), pub)
151 case elliptic.P384():
152 return publicKeyBytes(ecdsa.P384(), pub)
153 case elliptic.P521():
154 return publicKeyBytes(ecdsa.P521(), pub)
155 default:
156 return nil, errors.New("ecdsa: curve not supported by PublicKey.Bytes")
157 }
158 }
159 160 func publicKeyBytes[P ecdsa.Point[P]](c *ecdsa.Curve[P], pub *PublicKey) ([]byte, error) {
161 k, err := publicKeyToFIPS(c, pub)
162 if err != nil {
163 return nil, err
164 }
165 return k.Bytes(), nil
166 }
167 168 // PrivateKey represents an ECDSA private key.
169 type PrivateKey struct {
170 PublicKey
171 172 // D is the private scalar value.
173 //
174 // Modifying the raw value can produce invalid keys, and may
175 // invalidate internal optimizations; moreover, [big.Int] methods are not
176 // suitable for operating on cryptographic values. To encode and decode
177 // PrivateKey values, use [PrivateKey.Bytes] and [ParseRawPrivateKey] or
178 // [crypto/x509.MarshalPKCS8PrivateKey] and [crypto/x509.ParsePKCS8PrivateKey].
179 // For ECDH, use [crypto/ecdh].
180 //
181 // This field will be deprecated in Go 1.26.
182 D *big.Int
183 }
184 185 // ECDH returns k as a [ecdh.PrivateKey]. It returns an error if the key is
186 // invalid according to the definition of [ecdh.Curve.NewPrivateKey], or if the
187 // Curve is not supported by [crypto/ecdh].
188 func (k *PrivateKey) ECDH() (*ecdh.PrivateKey, error) {
189 c := curveToECDH(k.Curve)
190 if c == nil {
191 return nil, errors.New("ecdsa: unsupported curve by crypto/ecdh")
192 }
193 size := (k.Curve.Params().N.BitLen() + 7) / 8
194 if k.D.BitLen() > size*8 {
195 return nil, errors.New("ecdsa: invalid private key")
196 }
197 return c.NewPrivateKey(k.D.FillBytes([]byte{:size}))
198 }
199 200 func curveToECDH(c elliptic.Curve) ecdh.Curve {
201 switch c {
202 case elliptic.P256():
203 return ecdh.P256()
204 case elliptic.P384():
205 return ecdh.P384()
206 case elliptic.P521():
207 return ecdh.P521()
208 default:
209 return nil
210 }
211 }
212 213 // Public returns the public key corresponding to priv.
214 func (priv *PrivateKey) Public() crypto.PublicKey {
215 return &priv.PublicKey
216 }
217 218 // Equal reports whether priv and x have the same value.
219 //
220 // See [PublicKey.Equal] for details on how Curve is compared.
221 func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool {
222 xx, ok := x.(*PrivateKey)
223 if !ok {
224 return false
225 }
226 return priv.PublicKey.Equal(&xx.PublicKey) && bigIntEqual(priv.D, xx.D)
227 }
228 229 // bigIntEqual reports whether a and b are equal leaking only their bit length
230 // through timing side-channels.
231 func bigIntEqual(a, b *big.Int) bool {
232 return subtle.ConstantTimeCompare(a.Bytes(), b.Bytes()) == 1
233 }
234 235 // ParseRawPrivateKey parses a private key encoded as a fixed-length big-endian
236 // integer, according to SEC 1, Version 2.0, Section 2.3.6 (sometimes referred
237 // to as the raw format). It returns an error if the value is not reduced modulo
238 // the curve's order, or if it's zero.
239 //
240 // curve must be one of [elliptic.P224], [elliptic.P256], [elliptic.P384], or
241 // [elliptic.P521], or ParseRawPrivateKey returns an error.
242 //
243 // ParseRawPrivateKey accepts the same format as [ecdh.Curve.NewPrivateKey] does
244 // for NIST curves, but returns a [PrivateKey] instead of an [ecdh.PrivateKey].
245 //
246 // Note that private keys are more commonly encoded in ASN.1 or PKCS#8 format,
247 // which can be parsed with [crypto/x509.ParseECPrivateKey] or
248 // [crypto/x509.ParsePKCS8PrivateKey] (and [encoding/pem]).
249 func ParseRawPrivateKey(curve elliptic.Curve, data []byte) (*PrivateKey, error) {
250 switch curve {
251 case elliptic.P224():
252 return parseRawPrivateKey(ecdsa.P224(), nistec.NewP224Point, curve, data)
253 case elliptic.P256():
254 return parseRawPrivateKey(ecdsa.P256(), nistec.NewP256Point, curve, data)
255 case elliptic.P384():
256 return parseRawPrivateKey(ecdsa.P384(), nistec.NewP384Point, curve, data)
257 case elliptic.P521():
258 return parseRawPrivateKey(ecdsa.P521(), nistec.NewP521Point, curve, data)
259 default:
260 return nil, errors.New("ecdsa: curve not supported by ParseRawPrivateKey")
261 }
262 }
263 264 func parseRawPrivateKey[P ecdsa.Point[P]](c *ecdsa.Curve[P], newPoint func() P, curve elliptic.Curve, data []byte) (*PrivateKey, error) {
265 q, err := newPoint().ScalarBaseMult(data)
266 if err != nil {
267 return nil, err
268 }
269 k, err := ecdsa.NewPrivateKey(c, data, q.Bytes())
270 if err != nil {
271 return nil, err
272 }
273 return privateKeyFromFIPS(curve, k)
274 }
275 276 // Bytes encodes the private key as a fixed-length big-endian integer according
277 // to SEC 1, Version 2.0, Section 2.3.6 (sometimes referred to as the raw
278 // format). It returns an error if the private key is invalid.
279 //
280 // PrivateKey.Curve must be one of [elliptic.P224], [elliptic.P256],
281 // [elliptic.P384], or [elliptic.P521], or Bytes returns an error.
282 //
283 // Bytes returns the same format as [ecdh.PrivateKey.Bytes] does for NIST curves.
284 //
285 // Note that private keys are more commonly encoded in ASN.1 or PKCS#8 format,
286 // which can be generated with [crypto/x509.MarshalECPrivateKey] or
287 // [crypto/x509.MarshalPKCS8PrivateKey] (and [encoding/pem]).
288 func (priv *PrivateKey) Bytes() ([]byte, error) {
289 switch priv.Curve {
290 case elliptic.P224():
291 return privateKeyBytes(ecdsa.P224(), priv)
292 case elliptic.P256():
293 return privateKeyBytes(ecdsa.P256(), priv)
294 case elliptic.P384():
295 return privateKeyBytes(ecdsa.P384(), priv)
296 case elliptic.P521():
297 return privateKeyBytes(ecdsa.P521(), priv)
298 default:
299 return nil, errors.New("ecdsa: curve not supported by PrivateKey.Bytes")
300 }
301 }
302 303 func privateKeyBytes[P ecdsa.Point[P]](c *ecdsa.Curve[P], priv *PrivateKey) ([]byte, error) {
304 k, err := privateKeyToFIPS(c, priv)
305 if err != nil {
306 return nil, err
307 }
308 return k.Bytes(), nil
309 }
310 311 // Sign signs a hash (which should be the result of hashing a larger message
312 // with opts.HashFunc()) using the private key, priv. If the hash is longer than
313 // the bit-length of the private key's curve order, the hash will be truncated
314 // to that length. It returns the ASN.1 encoded signature, like [SignASN1].
315 //
316 // If rand is not nil, the signature is randomized. Most applications should use
317 // [crypto/rand.Reader] as rand. Note that the returned signature does not
318 // depend deterministically on the bytes read from rand, and may change between
319 // calls and/or between versions.
320 //
321 // If rand is nil, Sign will produce a deterministic signature according to RFC
322 // 6979. When producing a deterministic signature, opts.HashFunc() must be the
323 // function used to produce digest and priv.Curve must be one of
324 // [elliptic.P224], [elliptic.P256], [elliptic.P384], or [elliptic.P521].
325 func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
326 if rand == nil {
327 return signRFC6979(priv, digest, opts)
328 }
329 return SignASN1(rand, priv, digest)
330 }
331 332 // GenerateKey generates a new ECDSA private key for the specified curve.
333 //
334 // Most applications should use [crypto/rand.Reader] as rand. Note that the
335 // returned key does not depend deterministically on the bytes read from rand,
336 // and may change between calls and/or between versions.
337 func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
338 randutil.MaybeReadByte(rand)
339 340 if boring.Enabled && rand == boring.RandReader {
341 x, y, d, err := boring.GenerateKeyECDSA(c.Params().Name)
342 if err != nil {
343 return nil, err
344 }
345 return &PrivateKey{PublicKey: PublicKey{Curve: c, X: bbig.Dec(x), Y: bbig.Dec(y)}, D: bbig.Dec(d)}, nil
346 }
347 boring.UnreachableExceptTests()
348 349 switch c.Params() {
350 case elliptic.P224().Params():
351 return generateFIPS(c, ecdsa.P224(), rand)
352 case elliptic.P256().Params():
353 return generateFIPS(c, ecdsa.P256(), rand)
354 case elliptic.P384().Params():
355 return generateFIPS(c, ecdsa.P384(), rand)
356 case elliptic.P521().Params():
357 return generateFIPS(c, ecdsa.P521(), rand)
358 default:
359 return generateLegacy(c, rand)
360 }
361 }
362 363 func generateFIPS[P ecdsa.Point[P]](curve elliptic.Curve, c *ecdsa.Curve[P], rand io.Reader) (*PrivateKey, error) {
364 if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) {
365 return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode")
366 }
367 privateKey, err := ecdsa.GenerateKey(c, rand)
368 if err != nil {
369 return nil, err
370 }
371 return privateKeyFromFIPS(curve, privateKey)
372 }
373 374 // errNoAsm is returned by signAsm and verifyAsm when the assembly
375 // implementation is not available.
376 var errNoAsm = errors.New("no assembly implementation available")
377 378 // SignASN1 signs a hash (which should be the result of hashing a larger message)
379 // using the private key, priv. If the hash is longer than the bit-length of the
380 // private key's curve order, the hash will be truncated to that length. It
381 // returns the ASN.1 encoded signature.
382 //
383 // The signature is randomized. Most applications should use [crypto/rand.Reader]
384 // as rand. Note that the returned signature does not depend deterministically on
385 // the bytes read from rand, and may change between calls and/or between versions.
386 func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) {
387 randutil.MaybeReadByte(rand)
388 389 if boring.Enabled && rand == boring.RandReader {
390 b, err := boringPrivateKey(priv)
391 if err != nil {
392 return nil, err
393 }
394 return boring.SignMarshalECDSA(b, hash)
395 }
396 boring.UnreachableExceptTests()
397 398 switch priv.Curve.Params() {
399 case elliptic.P224().Params():
400 return signFIPS(ecdsa.P224(), priv, rand, hash)
401 case elliptic.P256().Params():
402 return signFIPS(ecdsa.P256(), priv, rand, hash)
403 case elliptic.P384().Params():
404 return signFIPS(ecdsa.P384(), priv, rand, hash)
405 case elliptic.P521().Params():
406 return signFIPS(ecdsa.P521(), priv, rand, hash)
407 default:
408 return signLegacy(priv, rand, hash)
409 }
410 }
411 412 func signFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], priv *PrivateKey, rand io.Reader, hash []byte) ([]byte, error) {
413 if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) {
414 return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode")
415 }
416 k, err := privateKeyToFIPS(c, priv)
417 if err != nil {
418 return nil, err
419 }
420 // Always using SHA-512 instead of the hash that computed hash is
421 // technically a violation of draft-irtf-cfrg-det-sigs-with-noise-04 but in
422 // our API we don't get to know what it was, and this has no security impact.
423 sig, err := ecdsa.Sign(c, sha512.New, k, rand, hash)
424 if err != nil {
425 return nil, err
426 }
427 return encodeSignature(sig.R, sig.S)
428 }
429 430 func signRFC6979(priv *PrivateKey, hash []byte, opts crypto.SignerOpts) ([]byte, error) {
431 if opts == nil {
432 return nil, errors.New("ecdsa: Sign called with nil opts")
433 }
434 h := opts.HashFunc()
435 if h.Size() != len(hash) {
436 return nil, errors.New("ecdsa: hash length does not match hash function")
437 }
438 switch priv.Curve.Params() {
439 case elliptic.P224().Params():
440 return signFIPSDeterministic(ecdsa.P224(), h, priv, hash)
441 case elliptic.P256().Params():
442 return signFIPSDeterministic(ecdsa.P256(), h, priv, hash)
443 case elliptic.P384().Params():
444 return signFIPSDeterministic(ecdsa.P384(), h, priv, hash)
445 case elliptic.P521().Params():
446 return signFIPSDeterministic(ecdsa.P521(), h, priv, hash)
447 default:
448 return nil, errors.New("ecdsa: curve not supported by deterministic signatures")
449 }
450 }
451 452 func signFIPSDeterministic[P ecdsa.Point[P]](c *ecdsa.Curve[P], hashFunc crypto.Hash, priv *PrivateKey, hash []byte) ([]byte, error) {
453 k, err := privateKeyToFIPS(c, priv)
454 if err != nil {
455 return nil, err
456 }
457 h := fips140hash.UnwrapNew(hashFunc.New)
458 if fips140only.Enabled && !fips140only.ApprovedHash(h()) {
459 return nil, errors.New("crypto/ecdsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
460 }
461 sig, err := ecdsa.SignDeterministic(c, h, k, hash)
462 if err != nil {
463 return nil, err
464 }
465 return encodeSignature(sig.R, sig.S)
466 }
467 468 func encodeSignature(r, s []byte) ([]byte, error) {
469 var b cryptobyte.Builder
470 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
471 addASN1IntBytes(b, r)
472 addASN1IntBytes(b, s)
473 })
474 return b.Bytes()
475 }
476 477 // addASN1IntBytes encodes in ASN.1 a positive integer represented as
478 // a big-endian byte slice with zero or more leading zeroes.
479 func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) {
480 for len(bytes) > 0 && bytes[0] == 0 {
481 bytes = bytes[1:]
482 }
483 if len(bytes) == 0 {
484 b.SetError(errors.New("invalid integer"))
485 return
486 }
487 b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) {
488 if bytes[0]&0x80 != 0 {
489 c.AddUint8(0)
490 }
491 c.AddBytes(bytes)
492 })
493 }
494 495 // VerifyASN1 verifies the ASN.1 encoded signature, sig, of hash using the
496 // public key, pub. Its return value records whether the signature is valid.
497 //
498 // The inputs are not considered confidential, and may leak through timing side
499 // channels, or if an attacker has control of part of the inputs.
500 func VerifyASN1(pub *PublicKey, hash, sig []byte) bool {
501 if boring.Enabled {
502 key, err := boringPublicKey(pub)
503 if err != nil {
504 return false
505 }
506 return boring.VerifyECDSA(key, hash, sig)
507 }
508 boring.UnreachableExceptTests()
509 510 switch pub.Curve.Params() {
511 case elliptic.P224().Params():
512 return verifyFIPS(ecdsa.P224(), pub, hash, sig)
513 case elliptic.P256().Params():
514 return verifyFIPS(ecdsa.P256(), pub, hash, sig)
515 case elliptic.P384().Params():
516 return verifyFIPS(ecdsa.P384(), pub, hash, sig)
517 case elliptic.P521().Params():
518 return verifyFIPS(ecdsa.P521(), pub, hash, sig)
519 default:
520 return verifyLegacy(pub, hash, sig)
521 }
522 }
523 524 func verifyFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], pub *PublicKey, hash, sig []byte) bool {
525 r, s, err := parseSignature(sig)
526 if err != nil {
527 return false
528 }
529 k, err := publicKeyToFIPS(c, pub)
530 if err != nil {
531 return false
532 }
533 if err := ecdsa.Verify(c, k, hash, &ecdsa.Signature{R: r, S: s}); err != nil {
534 return false
535 }
536 return true
537 }
538 539 func parseSignature(sig []byte) (r, s []byte, err error) {
540 var inner cryptobyte.String
541 input := cryptobyte.String(sig)
542 if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
543 !input.Empty() ||
544 !inner.ReadASN1Integer(&r) ||
545 !inner.ReadASN1Integer(&s) ||
546 !inner.Empty() {
547 return nil, nil, errors.New("invalid ASN.1")
548 }
549 return r, s, nil
550 }
551 552 func publicKeyFromFIPS(curve elliptic.Curve, pub *ecdsa.PublicKey) (*PublicKey, error) {
553 x, y, err := pointToAffine(curve, pub.Bytes())
554 if err != nil {
555 return nil, err
556 }
557 return &PublicKey{Curve: curve, X: x, Y: y}, nil
558 }
559 560 func privateKeyFromFIPS(curve elliptic.Curve, priv *ecdsa.PrivateKey) (*PrivateKey, error) {
561 pub, err := publicKeyFromFIPS(curve, priv.PublicKey())
562 if err != nil {
563 return nil, err
564 }
565 return &PrivateKey{PublicKey: *pub, D: (&big.Int{}).SetBytes(priv.Bytes())}, nil
566 }
567 568 func publicKeyToFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], pub *PublicKey) (*ecdsa.PublicKey, error) {
569 Q, err := pointFromAffine(pub.Curve, pub.X, pub.Y)
570 if err != nil {
571 return nil, err
572 }
573 return ecdsa.NewPublicKey(c, Q)
574 }
575 576 var privateKeyCache fips140cache.Cache[PrivateKey, ecdsa.PrivateKey]
577 578 func privateKeyToFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], priv *PrivateKey) (*ecdsa.PrivateKey, error) {
579 Q, err := pointFromAffine(priv.Curve, priv.X, priv.Y)
580 if err != nil {
581 return nil, err
582 }
583 return privateKeyCache.Get(priv, func() (*ecdsa.PrivateKey, error) {
584 return ecdsa.NewPrivateKey(c, priv.D.Bytes(), Q)
585 }, func(k *ecdsa.PrivateKey) bool {
586 return subtle.ConstantTimeCompare(k.PublicKey().Bytes(), Q) == 1 &&
587 leftPadBytesEqual(k.Bytes(), priv.D.Bytes())
588 })
589 }
590 591 func leftPadBytesEqual(a, b []byte) bool {
592 if len(a) < len(b) {
593 a, b = b, a
594 }
595 if len(a) > len(b) {
596 x := []byte{:0:66 /* enough for a P-521 private key */}
597 x = append(x, []byte{:len(a)-len(b)}...)
598 x = append(x, b...)
599 b = x
600 }
601 return subtle.ConstantTimeCompare(a, b) == 1
602 }
603 604 // pointFromAffine is used to convert the PublicKey to a nistec SetBytes input.
605 func pointFromAffine(curve elliptic.Curve, x, y *big.Int) ([]byte, error) {
606 bitSize := curve.Params().BitSize
607 // Reject values that would not get correctly encoded.
608 if x.Sign() < 0 || y.Sign() < 0 {
609 return nil, errors.New("negative coordinate")
610 }
611 if x.BitLen() > bitSize || y.BitLen() > bitSize {
612 return nil, errors.New("overflowing coordinate")
613 }
614 // Encode the coordinates and let SetBytes reject invalid points.
615 byteLen := (bitSize + 7) / 8
616 buf := []byte{:1+2*byteLen}
617 buf[0] = 4 // uncompressed point
618 x.FillBytes(buf[1 : 1+byteLen])
619 y.FillBytes(buf[1+byteLen : 1+2*byteLen])
620 return buf, nil
621 }
622 623 // pointToAffine is used to convert a nistec Bytes encoding to a PublicKey.
624 func pointToAffine(curve elliptic.Curve, p []byte) (x, y *big.Int, err error) {
625 if len(p) == 1 && p[0] == 0 {
626 // This is the encoding of the point at infinity.
627 return nil, nil, errors.New("ecdsa: public key point is the infinity")
628 }
629 byteLen := (curve.Params().BitSize + 7) / 8
630 x = (&big.Int{}).SetBytes(p[1 : 1+byteLen])
631 y = (&big.Int{}).SetBytes(p[1+byteLen:])
632 return x, y, nil
633 }
634