I'm attempting to generate an X509 ECDSA certificate using BouncyCastle to use for a WebRTC DTLS handshake.
The method below generates a valid certificate that is understood by openssl but it's seemingly not accepted by Chrome and FireFox, which use non-openssl implmentations. The only difference in the ECDSA certificates produced by Chrome is the lack of named EC parameters.
My question is how can I get Bouncy Castle to skip the EC named parameters and use the ASN notation?
public static (Org.BouncyCastle.X509.X509Certificate certificate, AsymmetricKeyParameter privateKey) CreateSelfSignedEcdsaCert(string subjectName, string issuerName)
{
var randomGenerator = new CryptoApiRandomGenerator();
var random = new SecureRandom(randomGenerator);
var ecSpec = ECNamedCurveTable.GetByName("secp256r1");
var keyPairGenerator = new ECKeyPairGenerator("EC");
ECKeyGenerationParameters keyGenerationParameters = new ECKeyGenerationParameters(new ECDomainParameters(ecSpec), random);
keyPairGenerator.Init(keyGenerationParameters);
var subjectKeyPair = keyPairGenerator.GenerateKeyPair();
// Generate ECDSA signature factory
ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHECDSA", subjectKeyPair.Private, random);
// The Certificate Generator
var certificateGenerator = GetV3CertificateGenerator(subjectName, issuerName, random);
// Create the SubjectPublicKeyInfo with the OID for the named curve secp256r1 (prime256v1)
ECPublicKeyParameters ecPublicKeyParameters = (ECPublicKeyParameters)subjectKeyPair.Public;
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(ecPublicKeyParameters);
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
var certificate = certificateGenerator.Generate(signatureFactory);
return (certificate, subjectKeyPair.Private);
}
Bouncy Castle certificate exmaple:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 2541552027757896468 (0x2345681a80aee314)
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN = WebRTC
Validity
Not Before: Oct 19 00:00:00 2024 GMT
Not After : Nov 18 00:00:00 2024 GMT
Subject: CN = WebRTC
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:5c:1b:cc:e6:f9:e1:a7:14:e3:c5:a7:11:a7:b2:
92:14:d0:ab:a1:99:5f:a7:bf:7a:c1:c1:a8:23:ea:
86:2e:86:ab:36:61:a6:2a:02:59:e4:2c:7b:4f:ce:
2a:35:ae:50:33:12:b9:b3:3f:6a:e1:78:c5:49:37:
7d:89:4c:1f:cc
Field Type: prime-field
Prime:
00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
ff:ff:ff
A:
00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
ff:ff:fc
B:
5a:c6:35:d8:aa:3a:93:e7:b3:eb:bd:55:76:98:86:
bc:65:1d:06:b0:cc:53:b0:f6:3b:ce:3c:3e:27:d2:
60:4b
Generator (uncompressed):
04:6b:17:d1:f2:e1:2c:42:47:f8:bc:e6:e5:63:a4:
40:f2:77:03:7d:81:2d:eb:33:a0:f4:a1:39:45:d8:
98:c2:96:4f:e3:42:e2:fe:1a:7f:9b:8e:e7:eb:4a:
7c:0f:9e:16:2b:ce:33:57:6b:31:5e:ce:cb:b6:40:
68:37:bf:51:f5
Order:
00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff:
ff:ff:bc:e6:fa:ad:a7:17:9e:84:f3:b9:ca:c2:fc:
63:25:51
Cofactor: 1 (0x1)
Seed:
c4:9d:36:08:86:e7:04:93:6a:66:78:e1:13:9d:26:
b7:81:9f:7e:90
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:46:02:21:00:95:21:34:16:a4:ea:5f:b5:e2:b8:72:29:03:
c7:e7:3d:0e:a0:60:47:56:af:10:85:95:03:64:2d:01:8b:fb:
1c:02:21:00:94:22:16:56:be:c9:e3:99:eb:17:65:df:1f:44:
d3:1d:bf:ab:ec:7d:38:8a:b1:c8:ec:5c:da:51:3c:a9:d1:ab
Chrome Certificate:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 8979986769746990694 (0x7c9f52639a7a1666)
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN = WebRTC
Validity
Not Before: Oct 19 19:37:33 2024 GMT
Not After : Nov 19 19:37:33 2024 GMT
Subject: CN = WebRTC
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:d2:3c:a2:d9:4f:3d:c1:4d:d5:87:b2:88:57:39:
7d:3e:1d:ef:eb:78:aa:99:7f:51:6a:99:60:26:9e:
ad:21:10:33:15:b1:7c:c8:03:a4:a7:0d:e4:03:1e:
60:94:98:c2:e5:2e:b5:16:a7:44:48:55:2f:10:c9:
e1:55:f7:de:17
ASN1 OID: prime256v1
NIST CURVE: P-256
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:45:02:21:00:88:53:7f:2b:56:9e:b4:46:04:d5:b1:65:05:
49:7e:8b:8e:94:97:f0:f6:2f:46:eb:49:a3:6c:2e:b3:d4:83:
b5:02:20:7e:5e:30:f4:70:73:ff:0f:f9:30:af:09:44:f5:e3:
62:4e:61:c0:d1:d0:49:d7:f9:23:59:c6:d7:35:43:f2:08
To apply the OID instead of the parameters, you must take the ECKeyGenerationParameters
-ctor, which requires the DerObjectIdentifier
instead of the ECDomainParameters
, i.e.:
ECKeyGenerationParameters keyGenerationParameters = new ECKeyGenerationParameters(X9ObjectIdentifiers.Prime256v1, random);
This creates a certificate that contains the sequence with the OID instead of the sequence with the parameters. Accordingly, the OpenSSL dump (openssl x509 -in certificate.pem -text -noout
) only displays:
ASN1 OID: prime256v1
NIST CURVE: P-256
instead of the parameters.