azure-activedirectory-identitymodel-extensions-for-dotnet: RSACryptoServiceProviderProxy crashes on Mono
System.Security.Cryptography.CryptographicException: Keyset does not exist
at System.Security.Cryptography.RSACryptoServiceProvider.Common (System.Security.Cryptography.CspParameters p) [0x00000] in <filename unknown>:0
at System.Security.Cryptography.RSACryptoServiceProvider..ctor (Int32 dwKeySize, System.Security.Cryptography.CspParameters parameters) [0x00000] in <filename unknown>:0
at System.Security.Cryptography.RSACryptoServiceProvider..ctor (System.Security.Cryptography.CspParameters parameters) [0x00000] in <filename unknown>:0
at System.IdentityModel.Tokens.RSACryptoServiceProviderProxy..ctor (System.Security.Cryptography.RSACryptoServiceProvider rsa) [0x00000] in <filename unknown>:0
at System.IdentityModel.Tokens.AsymmetricSignatureProvider..ctor (System.IdentityModel.Tokens.AsymmetricSecurityKey key, System.String algorithm, Boolean willCreateSignatures) [0x00000] in <filename unknown>:0
at System.IdentityModel.Tokens.SignatureProviderFactory.CreateProvider (System.IdentityModel.Tokens.SecurityKey key, System.String algorithm, Boolean willCreateSignatures) [0x00000] in <filename unknown>:0
at System.IdentityModel.Tokens.SignatureProviderFactory.CreateForSigning (System.IdentityModel.Tokens.SecurityKey key, System.String algorithm) [0x00000] in <filename unknown>:0
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.CreateSignature (System.String inputString, System.IdentityModel.Tokens.SecurityKey key, System.String algorithm, System.IdentityModel.Tokens.SignatureProvider signatureProvider) [0x00000] in <filename unknown>:0
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.CreateToken (System.String issuer, System.String audience, System.Security.Claims.ClaimsIdentity subject, Nullable`1 notBefore, Nullable`1 expires, System.IdentityModel.Tokens.SigningCredentials signingCredentials, System.IdentityModel.Tokens.SignatureProvider signatureProvider) [0x00000] in <filename unknown>:0
at AspNet.Security.OpenIdConnect.Server.OpenIdConnectServerHandler+<CreateIdentityTokenAsync>d__21.MoveNext () [0x00000] in <filename unknown>:0
Mono doesn’t use CryptoAPI - which is Windows-specific - and always initializes CspKeyContainerInfo.ProviderType
to 1
, which causes RSACryptoServiceProviderProxy
to create a proxy around the existing RSA provider. Sadly, it crashes on Mono.
The bug disappears when you remove csp.Flags |= CspProviderFlags.UseExistingKey;
from RSACryptoServiceProviderProxy
’s constructor.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 45 (28 by maintainers)
Commits related to this issue
- Work around the RSACryptoServiceProviderProxy crash on mono While I understand that #179 was closed as wontfix because mono is not officially supported, this is a really trivial workaround that great... — committed to main--/azure-activedirectory-identitymodel-extensions-for-dotnet by main-- 5 years ago
@andycmaj that’s another bug: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/477
@in10se Sorry it took so long. My solution is actually pretty wildly stitched together. The idea is that the
SignatureProvider
actually creates (or, back then, created) anRsaCryptoServiceProviderProxy
to manage the signing and verification of RSA keys, which failed on mono. So I first wrote aCustomRsaCryptoServiceProviderProxy
which would be instantiated by aCustomAsymmetricSignatureProvider
instead, but in the end just skipped that part altogether by having that class’ constructor callThe
CustomAsymmetricSignatureProvider
would be implictly used in theJwtSecurityTokenHandler
’sCreateJwtSecurityToken
method asand in the
Startup
asNote that
CryptoProviderFactory.Default
currently doesn’t seem to have any effect.No particular concern for me, as it wouldn’t work even if you fixed this issue (since the ECDsa types are missing on Mono… we’d need a Mono TFM to fix that /cc @davidfowl)
FWIW, I opted for another temporary workaround: manually instantiating
RSACryptoServiceProvider
withCspParameters.ProviderType = 24
to bypassRSACryptoServiceProviderProxy
.Of course, it’s terribly insecure, as you have to load the private key from an unprotected embedded resource (note that I used the same trick to “mimic” .pfx support on CoreCLR).
The more I add temporary (and ugly) workarounds for security bugs, the more I realize we’re definitely on the bleeding edge with ASP.NET 5 on Core CLR and Mono: https://github.com/PinpointTownes/AspNet.Security.OpenIdConnect.Server/commit/e405908e9ed10f6eb5b10e5d3c6cf75cd0bf4926#diff-dc37cbfe3a6d682094d1bc6bb6a22117R191 😄