1
2
3
4
5 package x509
6
7 import (
8 "crypto/ecdh"
9 "crypto/ecdsa"
10 "crypto/ed25519"
11 "crypto/mldsa"
12 "crypto/rsa"
13 "crypto/x509/pkix"
14 "encoding/asn1"
15 "errors"
16 "fmt"
17 )
18
19
20
21
22 type pkcs8 struct {
23 Version int
24 Algo pkix.AlgorithmIdentifier
25 PrivateKey []byte
26
27 }
28
29
30
31
32
33
34
35
36
37
38
39 func ParsePKCS8PrivateKey(der []byte) (key any, err error) {
40 var privKey pkcs8
41 if _, err := asn1.Unmarshal(der, &privKey); err != nil {
42 if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil {
43 return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)")
44 }
45 if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil {
46 return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)")
47 }
48 return nil, err
49 }
50 switch {
51 case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA):
52 key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
53 if err != nil {
54 return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
55 }
56 return key, nil
57
58 case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA):
59 bytes := privKey.Algo.Parameters.FullBytes
60 namedCurveOID := new(asn1.ObjectIdentifier)
61 if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
62 namedCurveOID = nil
63 }
64 key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
65 if err != nil {
66 return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
67 }
68 return key, nil
69
70 case privKey.Algo.Algorithm.Equal(oidPublicKeyEd25519):
71 if l := len(privKey.Algo.Parameters.FullBytes); l != 0 {
72 return nil, errors.New("x509: invalid Ed25519 private key parameters")
73 }
74 var curvePrivateKey []byte
75 if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil {
76 return nil, fmt.Errorf("x509: invalid Ed25519 private key: %v", err)
77 }
78 if l := len(curvePrivateKey); l != ed25519.SeedSize {
79 return nil, fmt.Errorf("x509: invalid Ed25519 private key length: %d", l)
80 }
81 return ed25519.NewKeyFromSeed(curvePrivateKey), nil
82
83 case privKey.Algo.Algorithm.Equal(oidPublicKeyMLDSA44),
84 privKey.Algo.Algorithm.Equal(oidPublicKeyMLDSA65),
85 privKey.Algo.Algorithm.Equal(oidPublicKeyMLDSA87):
86 if l := len(privKey.Algo.Parameters.FullBytes); l != 0 {
87 return nil, errors.New("x509: invalid ML-DSA private key parameters")
88 }
89 if l := len(privKey.PrivateKey); l == 0 {
90 return nil, fmt.Errorf("x509: invalid ML-DSA private key length: %d", l)
91 }
92 switch privKey.PrivateKey[0] {
93 case 0x80:
94 case 0x04:
95 return nil, errors.New("x509: semi-expanded ML-DSA private keys without seed are not supported")
96 case 0x30:
97 return nil, errors.New(`x509: ML-DSA private keys with both seed and expanded key are not supported, use e.g. "openssl pkey -provparam ml-dsa.output_formats=seed-only" to convert to a seed-only key`)
98 default:
99 return nil, fmt.Errorf("x509: invalid ML-DSA private key: invalid ASN.1 tag %02x", privKey.PrivateKey[0])
100 }
101 if l := len(privKey.PrivateKey); l != 2+mldsa.PrivateKeySize {
102 return nil, fmt.Errorf("x509: invalid ML-DSA private key length: %d", l)
103 }
104 if privKey.PrivateKey[1] != mldsa.PrivateKeySize {
105 return nil, fmt.Errorf("x509: invalid ML-DSA private key ASN.1 encoding")
106 }
107 params, ok := mldsaParametersFromOID(privKey.Algo.Algorithm)
108 if !ok {
109 return nil, errors.New("x509: unknown ML-DSA parameters")
110 }
111 return mldsa.NewPrivateKey(params, privKey.PrivateKey[2:])
112
113 case privKey.Algo.Algorithm.Equal(oidPublicKeyX25519):
114 if l := len(privKey.Algo.Parameters.FullBytes); l != 0 {
115 return nil, errors.New("x509: invalid X25519 private key parameters")
116 }
117 var curvePrivateKey []byte
118 if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil {
119 return nil, fmt.Errorf("x509: invalid X25519 private key: %v", err)
120 }
121 return ecdh.X25519().NewPrivateKey(curvePrivateKey)
122
123 default:
124 return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
125 }
126 }
127
128
129
130
131
132
133
134
135
136
137 func MarshalPKCS8PrivateKey(key any) ([]byte, error) {
138 var privKey pkcs8
139
140 switch k := key.(type) {
141 case *rsa.PrivateKey:
142 privKey.Algo = pkix.AlgorithmIdentifier{
143 Algorithm: oidPublicKeyRSA,
144 Parameters: asn1.NullRawValue,
145 }
146 k.Precompute()
147 if err := k.Validate(); err != nil {
148 return nil, err
149 }
150 privKey.PrivateKey = MarshalPKCS1PrivateKey(k)
151
152 case *ecdsa.PrivateKey:
153 oid, ok := oidFromNamedCurve(k.Curve)
154 if !ok {
155 return nil, errors.New("x509: unknown curve while marshaling to PKCS#8")
156 }
157 oidBytes, err := asn1.Marshal(oid)
158 if err != nil {
159 return nil, errors.New("x509: failed to marshal curve OID: " + err.Error())
160 }
161 privKey.Algo = pkix.AlgorithmIdentifier{
162 Algorithm: oidPublicKeyECDSA,
163 Parameters: asn1.RawValue{
164 FullBytes: oidBytes,
165 },
166 }
167 if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil {
168 return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error())
169 }
170
171 case ed25519.PrivateKey:
172 privKey.Algo = pkix.AlgorithmIdentifier{
173 Algorithm: oidPublicKeyEd25519,
174 }
175 curvePrivateKey, err := asn1.Marshal(k.Seed())
176 if err != nil {
177 return nil, fmt.Errorf("x509: failed to marshal private key: %v", err)
178 }
179 privKey.PrivateKey = curvePrivateKey
180
181 case *mldsa.PrivateKey:
182 oid, ok := oidFromMLDSAParameters(k.PublicKey().Parameters())
183 if !ok {
184 return nil, errors.New("x509: unknown ML-DSA parameters while marshaling to PKCS#8")
185 }
186 privKey.Algo = pkix.AlgorithmIdentifier{
187 Algorithm: oid,
188 }
189 privKey.PrivateKey = append([]byte{0x80, mldsa.PrivateKeySize}, k.Bytes()...)
190
191 case *ecdh.PrivateKey:
192 if k.Curve() == ecdh.X25519() {
193 privKey.Algo = pkix.AlgorithmIdentifier{
194 Algorithm: oidPublicKeyX25519,
195 }
196 var err error
197 if privKey.PrivateKey, err = asn1.Marshal(k.Bytes()); err != nil {
198 return nil, fmt.Errorf("x509: failed to marshal private key: %v", err)
199 }
200 } else {
201 oid, ok := oidFromECDHCurve(k.Curve())
202 if !ok {
203 return nil, errors.New("x509: unknown curve while marshaling to PKCS#8")
204 }
205 oidBytes, err := asn1.Marshal(oid)
206 if err != nil {
207 return nil, errors.New("x509: failed to marshal curve OID: " + err.Error())
208 }
209 privKey.Algo = pkix.AlgorithmIdentifier{
210 Algorithm: oidPublicKeyECDSA,
211 Parameters: asn1.RawValue{
212 FullBytes: oidBytes,
213 },
214 }
215 if privKey.PrivateKey, err = marshalECDHPrivateKey(k); err != nil {
216 return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error())
217 }
218 }
219
220 default:
221 return nil, fmt.Errorf("x509: unknown key type while marshaling PKCS#8: %T", key)
222 }
223
224 return asn1.Marshal(privKey)
225 }
226
View as plain text