Decrypt and verify hash for SHA256 - c#

3.6k views Asked by At

I am trying to decrypt and validate the hash but at times of decrypting, it throws me the error 'Key does not exist' and at the time of validating the hash return False

https://payvyne.readme.io/docs/webhooks

Signature:

HEjoCsghC9X0slrE2DprptDLYdoA7jaw4Jl7vpJVxzx9GNJEiO3pYGLDPhLmVqk98QJJ/FuiS5J+fvp+msr3Y8aFzKqjRQXj5TBELT38N+A7I8y3Vc0mgeR0aDMx7I83yhfkcoyhdiGJibzqQ5SYFZ0nnEVHYXheLUlga45yg/McDICtMm6lhnrPWEuHzoZTQkhsrLN/1W1PtLjJ2DickWB78PmhpeflL2Cpe6qS3qCclqFGZ7HIl9OoxU4WXpTYgxw7eixAKB7apFdFqea4BnGravfENNl97pOBuU6fRof4KtMczVagQw3QnxFD3BBtpTepRaT+jHY8wStXUG1bxllH32WiA9CVcpY4mxKhpxzQ8YD0b+3OgkpzZYS+BVVAdVazMJeEAw7v/zaxpjbR+Zo5l9vOLdyatwM75qpwMoKnMeKJHeRytEOK54al49OHiaE+v1OkOhJA0zh5nLzEIZanIdf+hXHDz3Euecs/p0cABiFNmhzYY5fl8qEytK6j2CjXQOYgljG5dqPm7M9CW36ntZTDaIEVWql3jdi9frxc4/82w1jhROFL0pBG1zz8nimAEesB1AaxmNqW7BIxULweX7eaReeo/dIqDSbmFuT+TikPQo4XRtmpDqO37Y9P6q7ZXtHOFopSaykHUHs+NgrKlBJMM5ADg5bHWm2Qows=

Public key:

pA6ULfXWrIMq-qvxn_0CykoStq0ZMYm63lHsuXTsE4q4tgekLJDW2Lnf35ilbFU_vybBdyeJAphpsYc4P0eJBt_z2T62HAV3gnwp_GU6hWIo8faK31TSXIrLmGjZlAVynAxjFYZoNxMeZuwEXpxG4bRGs58P7XSx1fAzedX6oGIlcSLljKH4I1BHt6gJhPIHYNXQzq_a0hX54C1m1VDVP_kot8ui1YKZil_riROK_Xk4ktnOTAqXo9z4uNBqzzH2k0J2YNiCb8VOdbp7kjmH9sPLI-jb-ociy0wSkGZc1e8saGIkkSm4eUASvX_M_TTDD99OrgoIS2Vx07Tw4lK5yd28EMVBUzy2OypuPVf9PyoDGv_4241x5PpJsA9IKocD7AgwxJ3E7FBFhvuSP8c5wspkbQxBwv5nnk2zAxuZsiJeK0o3JSxjkZJEkeVY4mA3VV9SvSXEKAFg2h9J3CR9PTwrZoVBruycVtWJ4it5jroXff-aGlLoRAO0g3gtfjkJb3tw6SJTFOA49iJci76Mj8Adz3eeEEGxTxfDzh_lq0jXxTk7cQSaR2_ChYLHaoorrrFmAvWgDH_lSvlISIgey-SzUoJM9RAy4gVFdmg-XCQQlpMh_d1-IACO3EfBvYKWE-6uGIqx1nZhn9WIDdSqMp6940xRxl0vQy8vYCQ5q8U

Data for Sign in string:

{"type":"PAYMENT_STATUS_CHANGE","paymentId":"1c6e834f074ec941","status":"FAILED","timestamp":1652688286662,"amount":"164.69","currency":"GBP","description":"This is test payment","paymentType":"ONE_OFF","bankName":"Diamond bank","destinationAccount":"GBP2","createdAt":"2022-05-16T08:04:32.994","updatedAt":"2022-05-16T08:04:46.662","customerReference":"1199","refundedAmount":"0.00"}

Expo (exponent):

AQAB

Below is the code to Decrypt the signature using public key.

public static void DecryptUsingPublicKey(string publicKey, string expo, string signature)
{
    var modulus = ConvertToBase64(publicKey);
    var exponent = Convert.FromBase64String(expo);

    RSACryptoServiceProvider csp = new RSACryptoServiceProvider(2048);
    var _publicKey = csp.ExportParameters(false);

    _publicKey.Modulus = modulus;
    _publicKey.Exponent = exponent;
    csp.ImportParameters(_publicKey);

    var dataBytes = ConvertToBase64(signature);
    var plainText = csp.Decrypt(dataBytes, false);
    var returnData = Encoding.Unicode.GetString(plainText);
    Console.WriteLine($"value: {returnData}");
}

Below is the code for Verify signature using public key

public static void VerifySignature(string signature, string pKey, string dataForSign)
{
    string pKeyNew = pKey;
    pKeyNew = pKeyNew.Replace("_", "/").Replace("-", "+");
    string publicKey = $"<RSAKeyValue><Modulus>{pKeyNew}==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

    var encoder = new UTF8Encoding();
    byte[] dataForSignAsBytes = encoder.GetBytes(dataForSign);

    byte[] signatureAsBytes = ConvertToBase64(signature);

    RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
    rsaCryptoServiceProvider.FromXmlString(publicKey);

    var hashData = SHA256.Create().ComputeHash(dataForSignAsBytes);

    var result1 = rsaCryptoServiceProvider.VerifyData(dataForSignAsBytes, CryptoConfig.MapNameToOID("SHA256"), signatureAsBytes);
    var result2 = rsaCryptoServiceProvider.VerifyHash(hashData, CryptoConfig.MapNameToOID("SHA256"), signatureAsBytes);
    var result3 = rsaCryptoServiceProvider.VerifyHash(hashData, signatureAsBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    var result4 = rsaCryptoServiceProvider.VerifyData(dataForSignAsBytes, signatureAsBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    Console.WriteLine(result1);
    Console.WriteLine(result2);
    Console.WriteLine(result3);
    Console.WriteLine(result4);
}

ConvertToBase64 function

public static byte[] ConvertToBase64(string data)
{
    byte[] cyperBuffer;
    string dataNew = data;
    dataNew = dataNew.Replace("_", "/").Replace("-", "+");
    try
    {
        if (dataNew.Substring(dataNew.Length - 1) != "=")
        {
            dataNew += "=";
        }
        cyperBuffer = Convert.FromBase64String(dataNew);
    }
    catch
    {
        dataNew += "=";

        try
        {
            cyperBuffer = Convert.FromBase64String(dataNew);
        }
        catch
        {
            //If any error occured while convert to base64 then append '=' at the end.
            dataNew += "=";
            cyperBuffer = Convert.FromBase64String(dataNew);
        }
    }

    return cyperBuffer;
}
1

There are 1 answers

2
Maarten Bodewes On

This is a conversion mistake; you need to decode the base 64 signature, not encode the signature, so the following line is wrong:

byte[] signatureAsBytes = ConvertToBase64(signature);

it should be something like:

byte[] signatureAsBytes = ConvertFromBase64(signature);

Decryption is modular exponentiation with a private key. Furthermore, encryption normally uses a different padding scheme than signature generation, so you'd expect that the unpadding would fail if you try and decrypt. Only verification is possible.