1
votes

I've been signing JWT tokens for a couple of years with no problems. I recently upgraded to Windows 10 and when I try to sign a JWT token I get a CryptographicException of "Invalid algorithm specified".

I'm passing an X509Certificate2 into this method and I'm not doing anything else really.

System.IdentityModel.Tokens.JwtSecurityTokenHandler.CreateToken()

The signing certificate was previously created using SHA-1, so I even created a new signing certificate using SHA-256 RSA, but still no joy.

I read several SO questions that suggested I needed to enable the "Microsoft Enhanced RSA and AES Cryptographic Provider" or at least create my signing certificate using it. Many SO Qu's suggested adding this line, but still no luck.

CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");

I also checked that this algorithm is in registry and found it in the Provider list and Provider type list. Unfortunately I don't have control of what algorithm the Jwt signing code uses as its all hidden within the System.Identity libraries.

Strangely, when I stepped into the code and looked at the Signature it mentioned it had an RSA Provider of "Microsoft Strong Cryptographic Provider", rather than the "Enhanced" one mentioned earlier, although from the MSDN documentation they appear to be pretty much the same.

I presume its complaining it can't find the Algorithm used to sign the actual token, rather than the algorithm to read or intepret the signing certificate?

What other checks can I do with the limited flexibility of the JwtSecurityTokenHandler code?

The full stack trace is:

at      System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature)
   at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash)
   at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash)
   at System.IdentityModel.Tokens.AsymmetricSignatureProvider.Sign(Byte[] input)
   at System.IdentityModel.Tokens.JwtSecurityTokenHandler.CreateSignature(String inputString, SecurityKey key, String algorithm, SignatureProvider signatureProvider)
   at System.IdentityModel.Tokens.JwtSecurityTokenHandler.CreateToken(String issuer, String audience, ClaimsIdentity subject, Lifetime lifetime, SigningCredentials signingCredentials, SignatureProvider signatureProvider)
   at System.IdentityModel.Tokens.JwtSecurityTokenHandler.CreateToken(SecurityTokenDescriptor tokenDescriptor)
1
Not a duplicate, but appears to be the same underlying issue as this: stackoverflow.com/questions/7444586/…explunit

1 Answers

2
votes

I recently had to tackle the exact same issue.

TL;DR; You need to use "Microsoft Enhanced RSA and AES Cryptographic Provider", as opposed to what I suspect you are using which is "Microsoft Enhanced Cryptographic Provider v1.0".

You can find a full explanatory [ReadME][2], and source code at Karama.Jwt.Public. I happen to be using a different library for generating my JWT, namely JOSE, but I think that this is incidental.

Please let me know how you get on.