Unexpected behavior when disposing RSACryptoServiceProvider.
When you create a token using the following the instructions in RSACryptoServiceProvider https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rsacryptoserviceprovider?view=net-5.0, the token creation fails every other time.
So, the first call succeeds but the call immediately after that fails with exception:
System.ObjectDisposedException: Safe handle has been closed.
Object name: 'SafeHandle'.
at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)
at Interop.Advapi32.CryptCreateHash(SafeProvHandle hProv, Int32 Algid, SafeKeyHandle hKey, CryptCreateHashFlags dwFlags, SafeHashHandle& phHash)
at Internal.NativeCrypto.CapiHelper.CreateHashHandle(SafeProvHandle hProv, Byte[] hash, Int32 calgHash)
at Internal.NativeCrypto.CapiHelper.SignValue(SafeProvHandle hProv, SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash)
at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash)
at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
at Microsoft.IdentityModel.Tokens.AsymmetricAdapter.SignWithRsa(Byte[] bytes)
at Microsoft.IdentityModel.Tokens.AsymmetricAdapter.Sign(Byte[] bytes)
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider.Sign(Byte[] input)
at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateJwtSecurityTokenPrivate(String issuer, String audience, ClaimsIdentity subject, Nullable1 notBefore, Nullable1 expires, Nullable1 issuedAt, SigningCredentials signingCredentials, EncryptingCredentials encryptingCredentials, IDictionary2 claimCollection, String tokenType)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateJwtSecurityToken(SecurityTokenDescriptor tokenDescriptor)
+ the codeline pointing to tokenHandler.CreateJwtSecurityToken
See the mini-project in here: https://github.com/Ozzian/InterestingBehaviour/blob/19df369549a21907880c2f8d4cb77b6cb37db45e/InterestingBehaviour/JWT.cs#L20
Is the intent not to dispose the RSACryptoServiceProvider during your service lifetime? What is up with this?
@Ozzian we will investigate this. Since the RsaSecurityKey ctor is passed a RSA instance, we should not be disposing that instance. Internally we cache an AsymmetricSignatureProvider associated with the RSA instance, that provider reuses the RSA instance after it was disposed.
We also get this error when we upgraded System.IdentityModel.Tokens.Jwt from previously working version 5.6 which we currently run in our production. Upgrading to a newer version of System.IdentityModel.Tokens.Jwt will not be possible for us until either this bug is solved or a viable workaround exists.
I have provided a C# project that reproduces the bug scenario as simple as possible. You may reach it here: https://github.com/Tobias841/Bug_SafeHandleHasBeenClosed
I have also the same problem as described by @Tobias841. An existing project was updated to the latest release (6.11.1). After much testing, I found the most recent version without this problem was 5.6.0.
@Tobias841 what is stopping you from upgrading to 6.x?
@Tobias841 what is stopping you from upgrading to 6.x?
If I read the original post correctly, and this is true in my case, this problem only exists in 6.x. We are waiting for 6.x to be fixed.
@Tobias841 what is stopping you from upgrading to 6.x?
andybakerbrfc is correct. All the information is there in the original post I think by Ozzian: "The token creation fails every other time". This is stopping us to upgrade to v 6.x. You seem to have a state dependency in the dispose method in between calls that causes the bug judging from the call stack and error message. But I'm on vacation now so I might remember this wrong...
I also added a link to a test project with minimal code that reveals the problem. I would suggest downloading that code. It should make it simple for you guys to find the problem I think using that test code. We can't upgrade to v 6.x until this has been fixed.
Most helpful comment
@Ozzian we will investigate this. Since the RsaSecurityKey ctor is passed a RSA instance, we should not be disposing that instance. Internally we cache an AsymmetricSignatureProvider associated with the RSA instance, that provider reuses the RSA instance after it was disposed.