-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Closed
Description
Description
When certificate is both ECDSA and ECDH in terms of:
Lines 1285 to 1299 in 27604b5
| private static bool IsECDsa(X509Certificate2 certificate) | |
| { | |
| using (ECDsa? ecdsa = certificate.GetECDsaPublicKey()) | |
| { | |
| return ecdsa is not null; | |
| } | |
| } | |
| private static bool IsECDiffieHellman(X509Certificate2 certificate) | |
| { | |
| using (ECDiffieHellman? ecdh = certificate.GetECDiffieHellmanPublicKey()) | |
| { | |
| return ecdh is not null; | |
| } | |
| } |
Then private key loaded with
X509Certificate2.CreateFromPem is not usable for ECDH on Windows.
Reproduction Steps
using System;
using System.Security.Cryptography.X509Certificates;
var pem = """
-----BEGIN CERTIFICATE-----
MIIBFDCBu6ADAgECAgkAvDLCg4b2/VwwCgYIKoZIzj0EAwIwDzENMAsGA1UEAwwE
VGVzdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowDzENMAsGA1UE
AwwEVGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFxeYPoaE/s7F4GQqTE/
eGfWmhQIgxkVNYKZk7z4mfAylUmbZ6Axbt04eatl9RMOFjHFH20hOg51/300otK6
x1IwCgYIKoZIzj0EAwIDSAAwRQIhAJ8PLaxaX/mtYSaQ+Ar/xkesnkc69R6B59+Z
4GGcpS7FAiBe3mEFY/bmB3qJYSYRMGjytQ/98v5LYSZHAaDx87uZMQ==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgT0q0yhmyYKLP9yPB
SKubBJFheOfrvBquIkhIm+br38uhRANCAARcXmD6GhP7OxeBkKkxP3hn1poUCIMZ
FTWCmZO8+JnwMpVJm2egMW7dOHmrZfUTDhYxxR9tIToOdf99NKLSusdS
-----END PRIVATE KEY-----
""";
var certificate = X509Certificate2.CreateFromPem(pem, pem);
Console.WriteLine(certificate.GetECDsaPrivateKey() is null);
Console.WriteLine(certificate.GetECDiffieHellmanPrivateKey() is null);Expected behavior
False
False
Actual behavior
False
True
Regression?
No response
Known Workarounds
Explicitly load private key with ECDiffieHellman:
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
var pem = """
-----BEGIN CERTIFICATE-----
MIIBFDCBu6ADAgECAgkAvDLCg4b2/VwwCgYIKoZIzj0EAwIwDzENMAsGA1UEAwwE
VGVzdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowDzENMAsGA1UE
AwwEVGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFxeYPoaE/s7F4GQqTE/
eGfWmhQIgxkVNYKZk7z4mfAylUmbZ6Axbt04eatl9RMOFjHFH20hOg51/300otK6
x1IwCgYIKoZIzj0EAwIDSAAwRQIhAJ8PLaxaX/mtYSaQ+Ar/xkesnkc69R6B59+Z
4GGcpS7FAiBe3mEFY/bmB3qJYSYRMGjytQ/98v5LYSZHAaDx87uZMQ==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgT0q0yhmyYKLP9yPB
SKubBJFheOfrvBquIkhIm+br38uhRANCAARcXmD6GhP7OxeBkKkxP3hn1poUCIMZ
FTWCmZO8+JnwMpVJm2egMW7dOHmrZfUTDhYxxR9tIToOdf99NKLSusdS
-----END PRIVATE KEY-----
""";
var certificate = X509Certificate2.CreateFromPem(pem);
var key = ECDiffieHellman.Create();
key.ImportFromPem(pem);
certificate = certificate.CopyWithPrivateKey(key);
Console.WriteLine(certificate.GetECDsaPrivateKey() is null);
Console.WriteLine(certificate.GetECDiffieHellmanPrivateKey() is null);Configuration
.NET SDK:
Version: 9.0.203
Commit: dc7acfa194
Workload version: 9.0.200-manifests.9df47798
MSBuild version: 17.13.20+a4ef1e90f
Runtime Environment:
OS Name: Windows
OS Version: 10.0.26100
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.203\
Host:
Version: 9.0.4
Architecture: x64
Commit: f57e6dc747
.NET SDKs installed:
9.0.203 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 9.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 9.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 9.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
As far as I understand, issue is specific for Windows.
Other information
On Windows CngKey for EC key marked with AlgorithmGroup ECDSA or ECDH. ECDH keys can be used in both algorithms, while ECDSA keys can be used only with ECDSA. As such when key should be usable in both algorithms, then it should be loaded as ECDH. Following code fragment load them as ECDSA:
Lines 1175 to 1186 in 27604b5
| Oids.EcPublicKey when IsECDsa(certificate) => | |
| ExtractKeyFromPem<ECDsa>( | |
| keyPem, | |
| s_EcPublicKeyPrivateKeyLabels, | |
| static keyPem => CreateAndImport(keyPem, ECDsa.Create), | |
| certificate.CopyWithPrivateKey), | |
| Oids.EcPublicKey when IsECDiffieHellman(certificate) => | |
| ExtractKeyFromPem<ECDiffieHellman>( | |
| keyPem, | |
| s_EcPublicKeyPrivateKeyLabels, | |
| static keyPem => CreateAndImport(keyPem, ECDiffieHellman.Create), | |
| certificate.CopyWithPrivateKey), |
Switch cases
Oids.EcPublicKey when IsECDsa(certificate) and Oids.EcPublicKey when IsECDiffieHellman(certificate) should be reordered to load them as ECDH.