Skip to content

Commit e65cf75

Browse files
committed
crypto/x509: support certificates with X25519 public keys
Even though X25519 can't be used for signing, it may be desirable to use a CA structure to sign X25519 keys that are used for ECDH purposes. This change adds the ability to properly extract X25519 public keys from certificates that contain such keys. It also makes it possible to create such certificates through CreateCertificate().
1 parent b68f8ca commit e65cf75

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

src/crypto/x509/x509.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -267,13 +267,15 @@ const (
267267
RSA
268268
DSA // Only supported for parsing.
269269
ECDSA
270+
X25519
270271
Ed25519
271272
)
272273

273274
var publicKeyAlgoName = [...]string{
274275
RSA: "RSA",
275276
DSA: "DSA",
276277
ECDSA: "ECDSA",
278+
X25519: "X25519",
277279
Ed25519: "Ed25519",
278280
}
279281

@@ -505,6 +507,8 @@ func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm
505507
return DSA
506508
case oid.Equal(oidPublicKeyECDSA):
507509
return ECDSA
510+
case oid.Equal(oidPublicKeyX25519):
511+
return X25519
508512
case oid.Equal(oidPublicKeyEd25519):
509513
return Ed25519
510514
}
@@ -1645,9 +1649,9 @@ var emptyASN1Subject = []byte{0x30, 0}
16451649
//
16461650
// The returned slice is the certificate in DER encoding.
16471651
//
1648-
// The currently supported key types are *rsa.PublicKey, *ecdsa.PublicKey and
1649-
// ed25519.PublicKey. pub must be a supported key type, and priv must be a
1650-
// crypto.Signer with a supported public key.
1652+
// The currently supported key types are *rsa.PublicKey, *ecdsa.PublicKey,
1653+
// ed25519.PublicKey and *ecdh.PublicKey (for X25519). pub must be a supported
1654+
// key type, and priv must be a crypto.Signer with a supported public key.
16511655
//
16521656
// The AuthorityKeyId will be taken from the SubjectKeyId of parent, if any,
16531657
// unless the resulting certificate is self-signed. Otherwise the value from

src/crypto/x509/x509_test.go

+61
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,67 @@ func TestRSAPSSSelfSigned(t *testing.T) {
11061106
}
11071107
}
11081108

1109+
const x25519Certificate = `
1110+
Certificate:
1111+
Data:
1112+
Version: 3 (0x2)
1113+
Serial Number: 6197312946105598768 (0x5601474a2a8dc330)
1114+
Signature Algorithm: ED25519
1115+
Issuer: CN=IETF Test Demo
1116+
Validity
1117+
Not Before: Aug 1 12:19:24 2016 GMT
1118+
Not After : Dec 31 23:59:59 2040 GMT
1119+
Subject: CN=IETF Test Demo
1120+
Subject Public Key Info:
1121+
Public Key Algorithm: X25519
1122+
X25519 Public-Key:
1123+
pub:
1124+
85:20:f0:09:89:30:a7:54:74:8b:7d:dc:b4:3e:f7:
1125+
5a:0d:bf:3a:0d:26:38:1a:f4:eb:a4:a9:8e:aa:9b:
1126+
4e:6a
1127+
X509v3 extensions:
1128+
X509v3 Basic Constraints: critical
1129+
CA:FALSE
1130+
X509v3 Key Usage:
1131+
Key Agreement
1132+
X509v3 Subject Key Identifier:
1133+
9B:1F:5E:ED:ED:04:33:85:E4:F7:BC:62:3C:59:75:B9:0B:C8:BB:3B
1134+
Signature Algorithm: ED25519
1135+
Signature Value:
1136+
af:23:01:fe:dd:c9:e6:ff:c1:cc:a7:3d:74:d6:48:a4:39:80:
1137+
82:cd:db:69:b1:4e:4d:06:ec:f8:1a:25:ce:50:d4:c2:c3:eb:
1138+
74:6c:4e:dd:83:46:85:6e:c8:6f:3d:ce:1a:18:65:c5:7a:c2:
1139+
7b:50:a0:c3:50:07:f5:e7:d9:07
1140+
-----BEGIN CERTIFICATE-----
1141+
MIIBLDCB36ADAgECAghWAUdKKo3DMDAFBgMrZXAwGTEXMBUGA1UEAwwOSUVURiBU
1142+
ZXN0IERlbW8wHhcNMTYwODAxMTIxOTI0WhcNNDAxMjMxMjM1OTU5WjAZMRcwFQYD
1143+
VQQDDA5JRVRGIFRlc3QgRGVtbzAqMAUGAytlbgMhAIUg8AmJMKdUdIt93LQ+91oN
1144+
vzoNJjga9OukqY6qm05qo0UwQzAPBgNVHRMBAf8EBTADAQEAMA4GA1UdDwEBAAQE
1145+
AwIDCDAgBgNVHQ4BAQAEFgQUmx9e7e0EM4Xk97xiPFl1uQvIuzswBQYDK2VwA0EA
1146+
ryMB/t3J5v/BzKc9dNZIpDmAgs3babFOTQbs+BolzlDUwsPrdGxO3YNGhW7Ibz3O
1147+
GhhlxXrCe1Cgw1AH9efZBw==
1148+
-----END CERTIFICATE-----`
1149+
1150+
func TestX25519(t *testing.T) {
1151+
der, _ := pem.Decode([]byte(x25519Certificate))
1152+
if der == nil {
1153+
t.Fatalf("Failed to find PEM block")
1154+
}
1155+
1156+
cert, err := ParseCertificate(der.Bytes)
1157+
if err != nil {
1158+
t.Fatalf("Failed to parse: %s", err)
1159+
}
1160+
1161+
if cert.PublicKeyAlgorithm != X25519 {
1162+
t.Fatalf("Parsed key algorithm was not X25519")
1163+
}
1164+
_, ok := cert.PublicKey.(*ecdh.PublicKey)
1165+
if !ok {
1166+
t.Fatalf("Parsed key was not an X25519 key: %s", err)
1167+
}
1168+
}
1169+
11091170
const ed25519Certificate = `
11101171
Certificate:
11111172
Data:

0 commit comments

Comments
 (0)