Clickbank CBC-AES-256 decryption in c#

落花浮王杯 提交于 2020-01-17 08:10:10

问题


I'm new with this encryption and decryption techniques.

I'm working on a task with Clickbank Instant Notification system. I'm getting the encrypted values from Clickbank and I want to decrypt the notification. My problem is very similar to this thread but it is not working for me. It is throwing following error:

Specified initialization vector (IV) does not match the block size for this algorithm.

Below is my code for decryption.

protected void Page_Load(object sender, EventArgs e)
{
    //Sample response
    string sContent = "{\"notification\":\"18XR9s5fwkbhvfriqYS6jDJERf++jshcTDQX4NuUoUHtS+YzfMCNiEvmIVNxkbT5My2xWLFPB9mb\nEjwpHd3A6b9WJDYiXc0nufTxhXDAL1JzyYryEZAq7Bogj7mHjxUfFhc419wDmQteoSEz4H0IsKha\nIoxSfA5znd6WZKCSY9Dxx0wbZ8jLNL8SOYxi7pbFdKgMgKULKEh4EPKaWAvhE5UjWtzuHvMX37NI\nOvApkBoYEDE2mrde/SjLigE38X2wsGB4M6pYVkfzEE6rbYfVNxadkNHmri1xlaa+Grudy6vt6wzq\nPUfroEb6uRlxj2e6dmKZE4kynJFmRosMJ4ZRC+sYW+DyvkbdSY2dl1ZMNPhP+yhcMkbU8HQKUipw\nd7FUpb6utfiDB8YL5z7pJMnjHP01PsIvG+eSj0Lfj1gmbtVJt6TOJ4BCZxZdfdPRlJtPdOUiMRRk\nQ3Wn5g9VuvzNYg2ostZ+/HE778M6lZ264KbpMZSqEj4cTPCGFFNt7VCz9fXVoDLa7oI7KGY6rgxb\nBLWXdX058RSd0gSzC8otkCx9b6p8FZ5XxAX4qbU814batcbxw3V3GGVf97VLSVysdrHc+PEFdocl\nqaRarCHG5e2ZpEgQLoCtRhA99qkuS9Uc9+Hm1KT4kD2HIrPSclJWzUMoKuAG4n95EG0Q5ca0WZQx\naLNhdPyJmSLNwjV/SNPxYdyy81ENZtLbwJOYENCnpd41z73HF91/R1hrxQ0rCZsb6BBRGUeowEzE\nSKPSbWjDCQ6hLZTjObsOt6eTAmn8TrzjyqdwUfxHhLEtIQIOr4gPXxXqwGHYcNkRFezkwMScl2Hr\nmJ+Zm1xCqs9+fOOiO6TtZYKS+9Dl/JevMfGdbcPw8/5F7+ZVAkCcDS8OGaVv\",\"iv\":\"NDVEM0M4ODZGMzE4OTVENA==\"}";


    using (var reader = new StreamReader(Request.InputStream))
    {
        //Using below two lines for live testing
        //JavaScriptSerializer js = new JavaScriptSerializer();
        //sContent = reader.ReadToEnd();

        JObject jObject = JObject.Parse(sContent);

        JToken notification = jObject["notification"];
        JToken i = jObject["iv"];


        using (StreamWriter _testData = new StreamWriter(Server.MapPath("~/data.txt"), true))
        {
            _testData.WriteLine("=======================Notification"); // Write the file. 
            _testData.WriteLine(notification.ToString());
            _testData.WriteLine("=======================IV"); // Write the file. 
            _testData.WriteLine(i.ToString());

            string n = notification.ToString();
            string v = i.ToString();

            string sk = "MY SECRET KEY";


            byte[] key = Encoding.UTF8.GetBytes(sk);
            byte[] iv = Encoding.UTF8.GetBytes(v);

            try
            {
                using (var rijndaelManaged =
                       new RijndaelManaged { Key = key, IV = iv, Mode = CipherMode.CBC })
                using (var memoryStream =
                       new MemoryStream(Convert.FromBase64String(n)))
                using (var cryptoStream =
                       new CryptoStream(memoryStream,
                           rijndaelManaged.CreateDecryptor(key, iv),
                           CryptoStreamMode.Read))
                {
                    var dString = new StreamReader(cryptoStream).ReadToEnd();
                }
            }
            catch (CryptographicException ex)
            {
                Console.WriteLine("A Cryptographic error occurred: {0}", ex.Message);

            }
        }
    }
}

Please let me know where I'm wrong?

Thanks


回答1:


I just finished banging my head on this exact same problem, so here is my solution. The thing to keep in mind is the passphrase/secretkey gets hashed by sha1 and the first 32 hex characters are used as the key bytes. The part that was throwing me off was the characters are UFT16 characters in c# and were actually 2 bytes each but not what the source encryption used. So what I did was convert the string to a ASCII string which had the correct byte array. Not the cleanest code but it's functional.

    public static string DecryptClickBankNotification(string cipherText, string passPhrase, string initVector)
    {
        string decryptedString = null;

        byte[] inputBytes = Encoding.UTF8.GetBytes(passPhrase);

        SHA1 sha1 = SHA1.Create();
        byte[] key = sha1.ComputeHash(inputBytes);

        StringBuilder hex = new StringBuilder(key.Length * 2);
        foreach (byte b in key)
            hex.AppendFormat("{0:x2}", b);

        string secondPhaseKey = hex.ToString().Substring(0,32);

        ASCIIEncoding asciiEncoding = new ASCIIEncoding();

        byte[] keyBytes = asciiEncoding.GetBytes(secondPhaseKey);
        byte[] iv = Convert.FromBase64String(initVector);

        try
        {
            using (RijndaelManaged rijndaelManaged = new RijndaelManaged
            { 
                Key = keyBytes,
                IV = iv,
                Mode = CipherMode.CBC, 
                Padding = PaddingMode.PKCS7})
                using (Stream memoryStream = new MemoryStream(Convert.FromBase64String(cipherText)))
                using (CryptoStream cryptoStream =
                   new CryptoStream(memoryStream,
                       rijndaelManaged.CreateDecryptor(keyBytes, iv),
                       CryptoStreamMode.Read))
            {
                decryptedString = new StreamReader(cryptoStream).ReadToEnd();
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine(new TraceData(TraceCategoryEnum.Errors, "Error decrypting message: " + ex.Message));
        }

        return decryptedString;
    }



回答2:


If your v has 16 letters and you Encoding.UTF8.GetBytes(v); the number of bytes could be between 16 and 64. This could be giving you the error.

Specified initialization vector (IV) does not match the block size for this algorithm.

Verify that iv is 16 bytes.



来源:https://stackoverflow.com/questions/29208552/clickbank-cbc-aes-256-decryption-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!