sec1.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Copyright 2012 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. package x509
  5. import (
  6. "crypto/ecdsa"
  7. "crypto/elliptic"
  8. // START CT CHANGES
  9. "github.com/google/certificate-transparency/go/asn1"
  10. // START CT CHANGES
  11. "errors"
  12. "fmt"
  13. "math/big"
  14. )
  15. const ecPrivKeyVersion = 1
  16. // ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure.
  17. // References:
  18. // RFC5915
  19. // SEC1 - http://www.secg.org/download/aid-780/sec1-v2.pdf
  20. // Per RFC5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in
  21. // most cases it is not.
  22. type ecPrivateKey struct {
  23. Version int
  24. PrivateKey []byte
  25. NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
  26. PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
  27. }
  28. // ParseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
  29. func ParseECPrivateKey(der []byte) (key *ecdsa.PrivateKey, err error) {
  30. return parseECPrivateKey(nil, der)
  31. }
  32. // MarshalECPrivateKey marshals an EC private key into ASN.1, DER format.
  33. func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
  34. oid, ok := oidFromNamedCurve(key.Curve)
  35. if !ok {
  36. return nil, errors.New("x509: unknown elliptic curve")
  37. }
  38. return asn1.Marshal(ecPrivateKey{
  39. Version: 1,
  40. PrivateKey: key.D.Bytes(),
  41. NamedCurveOID: oid,
  42. PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
  43. })
  44. }
  45. // parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
  46. // The OID for the named curve may be provided from another source (such as
  47. // the PKCS8 container) - if it is provided then use this instead of the OID
  48. // that may exist in the EC private key structure.
  49. func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
  50. var privKey ecPrivateKey
  51. if _, err := asn1.Unmarshal(der, &privKey); err != nil {
  52. return nil, errors.New("x509: failed to parse EC private key: " + err.Error())
  53. }
  54. if privKey.Version != ecPrivKeyVersion {
  55. return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version)
  56. }
  57. var curve elliptic.Curve
  58. if namedCurveOID != nil {
  59. curve = namedCurveFromOID(*namedCurveOID)
  60. } else {
  61. curve = namedCurveFromOID(privKey.NamedCurveOID)
  62. }
  63. if curve == nil {
  64. return nil, errors.New("x509: unknown elliptic curve")
  65. }
  66. k := new(big.Int).SetBytes(privKey.PrivateKey)
  67. if k.Cmp(curve.Params().N) >= 0 {
  68. return nil, errors.New("x509: invalid elliptic curve private key value")
  69. }
  70. priv := new(ecdsa.PrivateKey)
  71. priv.Curve = curve
  72. priv.D = k
  73. priv.X, priv.Y = curve.ScalarBaseMult(privKey.PrivateKey)
  74. return priv, nil
  75. }