简体   繁体   中英

CryptographicException Bad Key when trying to load public key into RSACryptoServiceProvider

I'm not sure how this issue is happening, the key that I'm attempting to pass to the CSP was originally a Base64Encoded string which I've tried passing in using ImportSubjectInfoKey() as well. Each time when debugging I have exported the parameters and I am able to get my public key back as a Base64 string so as far as I know it's a valid key. However once it hits the VerifyData method it breaks with a Bad Key exception. While debugging, I did notice that rsa1.CspKeyContainerInfo was mentioning an error "Exportable: {key does not exist}". Is this where my issue is coming from? I've included the public key below as an XML string if anyone can see an issue.

    private static bool VerifyData(string paymentToken, string signature)
    {

        var rsa1 = new RSACryptoServiceProvider(2048);
        string publicKey = @"
            <RSAKeyValue><Modulus>zIU140G9rFe6ouNFuhCxIj3Ps3ELUV9w4XTnDsti8kcSTXMf0z6LMNVIqXaZYFbSYXAZRmuM3XNmoSWmMZzPBMl2/C7uC0wyNdrYdPw0uzU2wfr8MQbnvW0yQgQ/cSHNDUZR+n/s2ipXTdNmbRd4z+k+qXxw00xMDmiJu5iMHyYo24x284lTZ3+4dgL4xFlrtjgcb/NGHBpVPQTCbBfEQcmylCwzbTUdBJlAo5ezpziOJ6CNf9FDS1hvRKRvNl7Hx8To6vQZJTwdCT5RWDC2JYL0oSdPV+SZmlfHQQe33p81MiRl4cjp5AwMVKyAosDihGT810WFYhK431EIB/NR/w==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
        
        rsa1.FromXmlString(publicKey);

        // Converts back to my original Base64 encoded public key so it seems valid.
        var x = rsa1.ExportSubjectPublicKeyInfo();
        var a = Convert.ToBase64String(x);

        RSAPKCS1SignatureDeformatter rsaDeformatter = new(rsa1);
        rsaDeformatter.SetHashAlgorithm("SHA256");

        var paymentTokenAsBytes = Encoding.UTF8.GetBytes(paymentToken);
        var signatureAsBytes = Convert.FromBase64String(signature);

        bool verified = false;
        try
        {
            if (rsaDeformatter.VerifySignature(paymentTokenAsBytes, signatureAsBytes))
            {
                Console.WriteLine("The signature is valid.");
                verified = true;
            }
            else
            {
                Console.WriteLine("The signature is not valid.");
                verified = false;
            }
        } catch(CryptographicException ex)
        {
            Debug.WriteLine($"What is going on!! {ex} ");
        }
        return verified;

Error:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Bad Key.
at Internal.NativeCrypto.CapiHelper.CreateHashHandle(SafeProvHandle hProv, Byte[] hash, Int32 
calgHash)
at Internal.NativeCrypto.CapiHelper.VerifySign(SafeProvHandle hProv, SafeKeyHandle hKey, Int32 
calgKey, Int32 calgHash, Byte[] hash, Byte[] signature)
at System.Security.Cryptography.RSACryptoServiceProvider.VerifyHash(Byte[] hash, Byte[] signature, 
HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
at System.Security.Cryptography.RSAPKCS1SignatureDeformatter.VerifySignature(Byte[] rgbHash, Byte[] 
rgbSignature)
at Go.Server.Controllers.CitizenWebhook.VerifyData(String paymentToken, String signature) in 
C:\Users\Dylan\source\repos\GO5050PLATFORM\Go\Server\Controllers\Webhooks\CitizenWebhook.cs:line 108 

The posted code fails because VerifySignature() doesn't expect the raw data but the hashed data, see also this example from the documentation.

With the following change:

var paymentTokenAsBytes = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(paymentToken));

the verification is successful.


If the key is available in X.509/SPKI format (DER encoded), it can alternatively be imported with ImportSubjectPublicKeyInfo() . For verification, the methods VerifyData() (hashes the data implicitly) and VerifyHash() (expects the already hashed data) can be used alternatively.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM