@@ -23,6 +23,7 @@ package x509
23
23
import (
24
24
"bytes"
25
25
"crypto"
26
+ "crypto/ecdh"
26
27
"crypto/ecdsa"
27
28
"crypto/ed25519"
28
29
"crypto/elliptic"
@@ -59,12 +60,12 @@ type pkixPublicKey struct {
59
60
BitString asn1.BitString
60
61
}
61
62
62
- // ParsePKIXPublicKey parses a public key in PKIX, ASN.1 DER form.
63
- // The encoded public key is a SubjectPublicKeyInfo structure
64
- // (see RFC 5280, Section 4.1).
63
+ // ParsePKIXPublicKey parses a public key in PKIX, ASN.1 DER form. The encoded
64
+ // public key is a SubjectPublicKeyInfo structure (see RFC 5280, Section 4.1).
65
65
//
66
- // It returns a *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, or
67
- // ed25519.PublicKey. More types might be supported in the future.
66
+ // It returns a *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
67
+ // ed25519.PublicKey (not a pointer), or *ecdh.PublicKey (for X25519).
68
+ // More types might be supported in the future.
68
69
//
69
70
// This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY".
70
71
func ParsePKIXPublicKey (derBytes []byte ) (pub any , err error ) {
@@ -77,11 +78,7 @@ func ParsePKIXPublicKey(derBytes []byte) (pub any, err error) {
77
78
} else if len (rest ) != 0 {
78
79
return nil , errors .New ("x509: trailing data after ASN.1 of public-key" )
79
80
}
80
- algo := getPublicKeyAlgorithmFromOID (pki .Algorithm .Algorithm )
81
- if algo == UnknownPublicKeyAlgorithm {
82
- return nil , errors .New ("x509: unknown public key algorithm" )
83
- }
84
- return parsePublicKey (algo , & pki )
81
+ return parsePublicKey (& pki )
85
82
}
86
83
87
84
func marshalPublicKey (pub any ) (publicKeyBytes []byte , publicKeyAlgorithm pkix.AlgorithmIdentifier , err error ) {
@@ -117,6 +114,12 @@ func marshalPublicKey(pub any) (publicKeyBytes []byte, publicKeyAlgorithm pkix.A
117
114
case ed25519.PublicKey :
118
115
publicKeyBytes = pub
119
116
publicKeyAlgorithm .Algorithm = oidPublicKeyEd25519
117
+ case * ecdh.PublicKey :
118
+ if pub .Curve () != ecdh .X25519 () {
119
+ return nil , pkix.AlgorithmIdentifier {}, errors .New ("x509: unsupported ECDH curve" )
120
+ }
121
+ publicKeyBytes = pub .Bytes ()
122
+ publicKeyAlgorithm .Algorithm = oidPublicKeyX25519
120
123
default :
121
124
return nil , pkix.AlgorithmIdentifier {}, fmt .Errorf ("x509: unsupported public key type: %T" , pub )
122
125
}
@@ -128,8 +131,9 @@ func marshalPublicKey(pub any) (publicKeyBytes []byte, publicKeyAlgorithm pkix.A
128
131
// The encoded public key is a SubjectPublicKeyInfo structure
129
132
// (see RFC 5280, Section 4.1).
130
133
//
131
- // The following key types are currently supported: *rsa.PublicKey, *ecdsa.PublicKey
132
- // and ed25519.PublicKey. Unsupported key types result in an error.
134
+ // The following key types are currently supported: *rsa.PublicKey,
135
+ // *ecdsa.PublicKey, ed25519.PublicKey (not a pointer), and *ecdh.PublicKey
136
+ // (X25519 only). Unsupported key types result in an error.
133
137
//
134
138
// This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY".
135
139
func MarshalPKIXPublicKey (pub any ) ([]byte , error ) {
@@ -240,7 +244,7 @@ type PublicKeyAlgorithm int
240
244
const (
241
245
UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota
242
246
RSA
243
- DSA // Unsupported .
247
+ DSA // Only supported for parsing .
244
248
ECDSA
245
249
Ed25519
246
250
)
@@ -444,27 +448,34 @@ func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm
444
448
return UnknownSignatureAlgorithm
445
449
}
446
450
447
- // RFC 3279, 2.3 Public Key Algorithms
448
- //
449
- // pkcs-1 OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
450
- // rsadsi(113549) pkcs(1) 1 }
451
- //
452
- // rsaEncryption OBJECT IDENTIFIER ::== { pkcs1-1 1 }
453
- //
454
- // id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
455
- // x9-57(10040) x9cm(4) 1 }
456
- //
457
- // RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
458
- //
459
- // id-ecPublicKey OBJECT IDENTIFIER ::= {
460
- // iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
461
451
var (
462
- oidPublicKeyRSA = asn1.ObjectIdentifier {1 , 2 , 840 , 113549 , 1 , 1 , 1 }
463
- oidPublicKeyDSA = asn1.ObjectIdentifier {1 , 2 , 840 , 10040 , 4 , 1 }
464
- oidPublicKeyECDSA = asn1.ObjectIdentifier {1 , 2 , 840 , 10045 , 2 , 1 }
465
- oidPublicKeyEd25519 = oidSignatureEd25519
452
+ // RFC 3279, 2.3 Public Key Algorithms
453
+ //
454
+ // pkcs-1 OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
455
+ // rsadsi(113549) pkcs(1) 1 }
456
+ //
457
+ // rsaEncryption OBJECT IDENTIFIER ::== { pkcs1-1 1 }
458
+ //
459
+ // id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
460
+ // x9-57(10040) x9cm(4) 1 }
461
+ oidPublicKeyRSA = asn1.ObjectIdentifier {1 , 2 , 840 , 113549 , 1 , 1 , 1 }
462
+ oidPublicKeyDSA = asn1.ObjectIdentifier {1 , 2 , 840 , 10040 , 4 , 1 }
463
+ // RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
464
+ //
465
+ // id-ecPublicKey OBJECT IDENTIFIER ::= {
466
+ // iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
467
+ oidPublicKeyECDSA = asn1.ObjectIdentifier {1 , 2 , 840 , 10045 , 2 , 1 }
468
+ // RFC 8410, Section 3
469
+ //
470
+ // id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 }
471
+ // id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 }
472
+ oidPublicKeyX25519 = asn1.ObjectIdentifier {1 , 3 , 101 , 110 }
473
+ oidPublicKeyEd25519 = asn1.ObjectIdentifier {1 , 3 , 101 , 112 }
466
474
)
467
475
476
+ // getPublicKeyAlgorithmFromOID returns the exposed PublicKeyAlgorithm
477
+ // identifier for public key types supported in certificates and CSRs. Marshal
478
+ // and Parse functions may support a different set of public key types.
468
479
func getPublicKeyAlgorithmFromOID (oid asn1.ObjectIdentifier ) PublicKeyAlgorithm {
469
480
switch {
470
481
case oid .Equal (oidPublicKeyRSA ):
@@ -1521,6 +1532,9 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
1521
1532
if err != nil {
1522
1533
return nil , err
1523
1534
}
1535
+ if getPublicKeyAlgorithmFromOID (publicKeyAlgorithm .Algorithm ) == UnknownPublicKeyAlgorithm {
1536
+ return nil , fmt .Errorf ("x509: unsupported public key type: %T" , pub )
1537
+ }
1524
1538
1525
1539
asn1Issuer , err := subjectBytes (parent )
1526
1540
if err != nil {
@@ -2068,9 +2082,11 @@ func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error
2068
2082
}
2069
2083
2070
2084
var err error
2071
- out .PublicKey , err = parsePublicKey (out .PublicKeyAlgorithm , & in .TBSCSR .PublicKey )
2072
- if err != nil {
2073
- return nil , err
2085
+ if out .PublicKeyAlgorithm != UnknownPublicKeyAlgorithm {
2086
+ out .PublicKey , err = parsePublicKey (& in .TBSCSR .PublicKey )
2087
+ if err != nil {
2088
+ return nil , err
2089
+ }
2074
2090
}
2075
2091
2076
2092
var subject pkix.RDNSequence
0 commit comments