Skip to content

Fix NullReferenceException when signing with an RSA JWK containing both private key and x5c#3533

Open
chris-peterson wants to merge 1 commit into
AzureAD:devfrom
chris-peterson:fix-null-reference
Open

Fix NullReferenceException when signing with an RSA JWK containing both private key and x5c#3533
chris-peterson wants to merge 1 commit into
AzureAD:devfrom
chris-peterson:fix-null-reference

Conversation

@chris-peterson

Copy link
Copy Markdown

Fixes #3260

Problem

JsonWebKeyConverter.TryConvertToSecurityKey tries TryConvertToX509SecurityKey before TryCreateToRsaSecurityKey for kty=RSA. A JWK that carries both private RSA parameters (d/p/q/…) and x5c is therefore converted to an X509SecurityKey built from x5c[0] — a public-only certificate — and the private RSA parameters are discarded.

When that key is used to sign:

  • AsymmetricAdapter.InitializeUsingX509SecurityKey calls InitializeUsingRsa(x509SecurityKey.PrivateKey as RSA, …) with requirePrivateKey: true.
  • X509SecurityKey.PrivateKey returns null (Certificate.GetRSAPrivateKey() on a public-only cert), so the adapter stores a null RSA.
  • The first sign operation dereferences it → NullReferenceException in AsymmetricAdapter.SignUsingSpanRsa.

Removing x5c from the same key (forcing the RsaSecurityKey conversion) signs successfully, which confirms the precedence is the cause. This is the signing-correctness angle of #3260, in addition to the memory consideration the issue was originally filed for.

Fix

Reorder the two attempts in the kty=RSA branch so RSA key material is used when present:

if (TryCreateToRsaSecurityKey(webKey, out key))
    return true;
if (TryConvertToX509SecurityKey(webKey, out key))
    return true;

An x5c-only JWK still converts to an X509SecurityKey, because TryCreateToRsaSecurityKey returns false unless both n and e are present.

Behavior change

A JWK that carries both n/e and x5c now converts to an RsaSecurityKey instead of an X509SecurityKey. Cryptographic operations are unaffected; the difference is the concrete SecurityKey type a caller observes (and the avoided X509Certificate2 load). This is the prioritization requested in #3260.

Tests

  • JsonWebKeyConverterTest.TryConvertToSecurityKey_RsaJsonWebKeyWithPrivateKeyAndX5c_ConvertsToRsaSecurityKey — asserts a JWK with private RSA parameters and x5c converts to an RsaSecurityKey.
  • JsonWebTokenHandlerTests.CreateToken_RsaJsonWebKeyWithPrivateKeyAndX5c_Signs — end-to-end signing test that reproduced the NullReferenceException before this change.

Both tests fail on the prior ordering (the converter yields X509SecurityKey, and signing throws the NRE at AsymmetricAdapter.SignUsingSpanRsa) and pass with the reorder.

JsonWebKeyConverter.TryConvertToSecurityKey tried TryConvertToX509SecurityKey
before TryCreateToRsaSecurityKey for kty=RSA. A JWK carrying both private RSA
parameters and x5c was converted to an X509SecurityKey built from x5c[0] (a
public-only certificate), discarding the private key. Signing then dereferenced
the null private key and threw a NullReferenceException in
AsymmetricAdapter.SignUsingSpanRsa.

Reorder the two attempts so RSA key material is used when present. An x5c-only
JWK still converts to an X509SecurityKey, because TryCreateToRsaSecurityKey
returns false unless both n and e are present.

Add a converter unit test (RSA JWK with private parameters + x5c converts to an
RsaSecurityKey) and an end-to-end signing test that reproduced the NRE.

Refs: AzureAD#3260
@chris-peterson
chris-peterson requested a review from a team as a code owner June 30, 2026 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prioritize converting RSA keys to RsaSecurityKeys over X509SecurityKey

1 participant