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
SignatureProvideractually creates (or, back then, created) anRsaCryptoServiceProviderProxyto manage the signing and verification of RSA keys, which failed on mono. So I first wrote aCustomRsaCryptoServiceProviderProxywhich would be instantiated by aCustomAsymmetricSignatureProviderinstead, but in the end just skipped that part altogether by having that class’ constructor callThe
CustomAsymmetricSignatureProviderwould be implictly used in theJwtSecurityTokenHandler’sCreateJwtSecurityTokenmethod asand in the
StartupasNote that
CryptoProviderFactory.Defaultcurrently 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
RSACryptoServiceProviderwithCspParameters.ProviderType = 24to 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 😄