pkcs8.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. package x509
  5. import (
  6. "crypto/ecdsa"
  7. "crypto/rsa"
  8. "errors"
  9. "fmt"
  10. "github.com/google/certificate-transparency-go/asn1"
  11. "github.com/google/certificate-transparency-go/x509/pkix"
  12. )
  13. // pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See
  14. // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn
  15. // and RFC 5208.
  16. type pkcs8 struct {
  17. Version int
  18. Algo pkix.AlgorithmIdentifier
  19. PrivateKey []byte
  20. // optional attributes omitted.
  21. }
  22. // ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key.
  23. // See RFC 5208.
  24. func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
  25. var privKey pkcs8
  26. if _, err := asn1.Unmarshal(der, &privKey); err != nil {
  27. return nil, err
  28. }
  29. switch {
  30. case privKey.Algo.Algorithm.Equal(OIDPublicKeyRSA):
  31. key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
  32. if err != nil {
  33. return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
  34. }
  35. return key, nil
  36. case privKey.Algo.Algorithm.Equal(OIDPublicKeyECDSA):
  37. bytes := privKey.Algo.Parameters.FullBytes
  38. namedCurveOID := new(asn1.ObjectIdentifier)
  39. if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
  40. namedCurveOID = nil
  41. }
  42. key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
  43. if err != nil {
  44. return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
  45. }
  46. return key, nil
  47. default:
  48. return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
  49. }
  50. }
  51. // MarshalPKCS8PrivateKey converts a private key to PKCS#8 encoded form.
  52. // The following key types are supported: *rsa.PrivateKey, *ecdsa.PublicKey.
  53. // Unsupported key types result in an error.
  54. //
  55. // See RFC 5208.
  56. func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) {
  57. var privKey pkcs8
  58. switch k := key.(type) {
  59. case *rsa.PrivateKey:
  60. privKey.Algo = pkix.AlgorithmIdentifier{
  61. Algorithm: OIDPublicKeyRSA,
  62. Parameters: asn1.NullRawValue,
  63. }
  64. privKey.PrivateKey = MarshalPKCS1PrivateKey(k)
  65. case *ecdsa.PrivateKey:
  66. oid, ok := OIDFromNamedCurve(k.Curve)
  67. if !ok {
  68. return nil, errors.New("x509: unknown curve while marshalling to PKCS#8")
  69. }
  70. oidBytes, err := asn1.Marshal(oid)
  71. if err != nil {
  72. return nil, errors.New("x509: failed to marshal curve OID: " + err.Error())
  73. }
  74. privKey.Algo = pkix.AlgorithmIdentifier{
  75. Algorithm: OIDPublicKeyECDSA,
  76. Parameters: asn1.RawValue{
  77. FullBytes: oidBytes,
  78. },
  79. }
  80. if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil {
  81. return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error())
  82. }
  83. default:
  84. return nil, fmt.Errorf("x509: unknown key type while marshalling PKCS#8: %T", key)
  85. }
  86. return asn1.Marshal(privKey)
  87. }