Yola
Yola

Reputation: 19033

X509Certificate2 PrivateKey and GetRSAPrivateKey

Is it possible in .NET 8 and above that PrivateKey property returns null but GetRSAPrivateKey returns key? How can I write a unit test for such a scenario?

Upvotes: 0

Views: 191

Answers (2)

Malt
Malt

Reputation: 30285

I've seen this happen in practice in .Net Framework (4.8). The following snippet produces a certificate with a null PrivateKey property and non-null GetRSAPrivateKey:

var cert = new CertificateRequest(
        "CN=Foo",
        RSA.Create(2048),
        HashAlgorithmName.SHA256,
        RSASignaturePadding.Pkcs1)
    .CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(2));

Where CertificateRequest is System.Security.Cryptography.X509Certificates.CertificateRequest.

Upvotes: 1

bartonjs
bartonjs

Reputation: 33098

No, it's not possible, per https://github.com/dotnet/runtime/blob/05abb765e2740d7182c56e142fbe44d76fafedf4/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs#L268-L295:

if (!HasPrivateKey)
    return null;
 
_lazyPrivateKey ??= GetKeyAlgorithm() switch
{
    Oids.Rsa => Pal.GetRSAPrivateKey(),
    Oids.Dsa => Pal.GetDSAPrivateKey(),
 
    // This includes ECDSA, because an Oids.EcPublicKey key can be
    // many different algorithm kinds, not necessarily with mutual exclusion.
    // Plus, .NET Framework only supports RSA and DSA in this property.
    _ => throw new NotSupportedException(SR.NotSupported_KeyAlgorithm),
};
 
return _lazyPrivateKey;

And a little digging will show the same Pal.GetRSAPrivateKey() is used for cert.GetRSAPrivateKey().

If you're using .NET 8, you should never call the PrivateKey property, only ever use the Get*PrivateKey methods.

Upvotes: 1

Related Questions