github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/crypto/x509/pkcs8.go (about) 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 x509 6 7 import ( 8 "crypto/ecdh" 9 "crypto/ecdsa" 10 "crypto/ed25519" 11 "crypto/rsa" 12 "crypto/x509/pkix" 13 "encoding/asn1" 14 "errors" 15 "fmt" 16 ) 17 18 // pkcs8 reflects an ASN.1, PKCS #8 PrivateKey. See 19 // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn 20 // and RFC 5208. 21 type pkcs8 struct { 22 Version int 23 Algo pkix.AlgorithmIdentifier 24 PrivateKey []byte 25 // optional attributes omitted. 26 } 27 28 // ParsePKCS8PrivateKey parses an unencrypted private key in PKCS #8, ASN.1 DER form. 29 // 30 // It returns a *rsa.PrivateKey, an *ecdsa.PrivateKey, an ed25519.PrivateKey (not 31 // a pointer), or an *ecdh.PrivateKey (for X25519). More types might be supported 32 // in the future. 33 // 34 // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". 35 func ParsePKCS8PrivateKey(der []byte) (key any, err error) { 36 var privKey pkcs8 37 if _, err := asn1.Unmarshal(der, &privKey); err != nil { 38 if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil { 39 return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)") 40 } 41 if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil { 42 return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)") 43 } 44 return nil, err 45 } 46 switch { 47 case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA): 48 key, err = ParsePKCS1PrivateKey(privKey.PrivateKey) 49 if err != nil { 50 return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error()) 51 } 52 return key, nil 53 54 case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA): 55 bytes := privKey.Algo.Parameters.FullBytes 56 namedCurveOID := new(asn1.ObjectIdentifier) 57 if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { 58 namedCurveOID = nil 59 } 60 key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey) 61 if err != nil { 62 return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error()) 63 } 64 return key, nil 65 66 case privKey.Algo.Algorithm.Equal(oidPublicKeyEd25519): 67 if l := len(privKey.Algo.Parameters.FullBytes); l != 0 { 68 return nil, errors.New("x509: invalid Ed25519 private key parameters") 69 } 70 var curvePrivateKey []byte 71 if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil { 72 return nil, fmt.Errorf("x509: invalid Ed25519 private key: %v", err) 73 } 74 if l := len(curvePrivateKey); l != ed25519.SeedSize { 75 return nil, fmt.Errorf("x509: invalid Ed25519 private key length: %d", l) 76 } 77 return ed25519.NewKeyFromSeed(curvePrivateKey), nil 78 79 case privKey.Algo.Algorithm.Equal(oidPublicKeyX25519): 80 if l := len(privKey.Algo.Parameters.FullBytes); l != 0 { 81 return nil, errors.New("x509: invalid X25519 private key parameters") 82 } 83 var curvePrivateKey []byte 84 if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil { 85 return nil, fmt.Errorf("x509: invalid X25519 private key: %v", err) 86 } 87 return ecdh.X25519().NewPrivateKey(curvePrivateKey) 88 89 default: 90 return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm) 91 } 92 } 93 94 // MarshalPKCS8PrivateKey converts a private key to PKCS #8, ASN.1 DER form. 95 // 96 // The following key types are currently supported: *rsa.PrivateKey, 97 // *ecdsa.PrivateKey, ed25519.PrivateKey (not a pointer), and *ecdh.PrivateKey. 98 // Unsupported key types result in an error. 99 // 100 // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". 101 func MarshalPKCS8PrivateKey(key any) ([]byte, error) { 102 var privKey pkcs8 103 104 switch k := key.(type) { 105 case *rsa.PrivateKey: 106 privKey.Algo = pkix.AlgorithmIdentifier{ 107 Algorithm: oidPublicKeyRSA, 108 Parameters: asn1.NullRawValue, 109 } 110 privKey.PrivateKey = MarshalPKCS1PrivateKey(k) 111 112 case *ecdsa.PrivateKey: 113 oid, ok := oidFromNamedCurve(k.Curve) 114 if !ok { 115 return nil, errors.New("x509: unknown curve while marshaling to PKCS#8") 116 } 117 oidBytes, err := asn1.Marshal(oid) 118 if err != nil { 119 return nil, errors.New("x509: failed to marshal curve OID: " + err.Error()) 120 } 121 privKey.Algo = pkix.AlgorithmIdentifier{ 122 Algorithm: oidPublicKeyECDSA, 123 Parameters: asn1.RawValue{ 124 FullBytes: oidBytes, 125 }, 126 } 127 if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil { 128 return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error()) 129 } 130 131 case ed25519.PrivateKey: 132 privKey.Algo = pkix.AlgorithmIdentifier{ 133 Algorithm: oidPublicKeyEd25519, 134 } 135 curvePrivateKey, err := asn1.Marshal(k.Seed()) 136 if err != nil { 137 return nil, fmt.Errorf("x509: failed to marshal private key: %v", err) 138 } 139 privKey.PrivateKey = curvePrivateKey 140 141 case *ecdh.PrivateKey: 142 if k.Curve() == ecdh.X25519() { 143 privKey.Algo = pkix.AlgorithmIdentifier{ 144 Algorithm: oidPublicKeyX25519, 145 } 146 var err error 147 if privKey.PrivateKey, err = asn1.Marshal(k.Bytes()); err != nil { 148 return nil, fmt.Errorf("x509: failed to marshal private key: %v", err) 149 } 150 } else { 151 oid, ok := oidFromECDHCurve(k.Curve()) 152 if !ok { 153 return nil, errors.New("x509: unknown curve while marshaling to PKCS#8") 154 } 155 oidBytes, err := asn1.Marshal(oid) 156 if err != nil { 157 return nil, errors.New("x509: failed to marshal curve OID: " + err.Error()) 158 } 159 privKey.Algo = pkix.AlgorithmIdentifier{ 160 Algorithm: oidPublicKeyECDSA, 161 Parameters: asn1.RawValue{ 162 FullBytes: oidBytes, 163 }, 164 } 165 if privKey.PrivateKey, err = marshalECDHPrivateKey(k); err != nil { 166 return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error()) 167 } 168 } 169 170 default: 171 return nil, fmt.Errorf("x509: unknown key type while marshaling PKCS#8: %T", key) 172 } 173 174 return asn1.Marshal(privKey) 175 }