【问题标题】:Clickbank CBC-AES-256 decryption in c#C#中的Clickbank CBC-AES-256解密
【发布时间】:2016-05-11 02:15:41
【问题描述】:

我是这种加密和解密技术的新手。

我正在与 Clickbank Instant Notification system 合作完成一项任务。我从 Clickbank 获取加密值,我想解密通知。我的问题与this 线程非常相似,但它对我不起作用。它抛出以下错误:

指定的初始化向量 (IV) 与此算法的块大小不匹配。

下面是我的解密代码。

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);

            }
        }
    }
}

请告诉我哪里错了?

谢谢

【问题讨论】:

  • 1) 你使用文本为key/iv,这没有任何意义。表示为字符串的键通常是十六进制或 Base64 编码的。 2) IV 的长度必须是 16 字节,而密钥的长度必须是 32 字节。
  • 感谢您的回复。我检查了一下,我的密钥是 16 个字母长,IV 是从 Clickbank 返回的。
  • 快速浏览发现了一些关于JValuebyte[] 运算符的信息,但我的JToken 知识大约为0,所以我不能真正使用它作为答案。正如代码已经规定的那样,键和 IV 是字节,没有字符。
  • i.ToString() 的值是多少?
  • v 的值为 "NDVEM0M4ODZGMzE4OTVENA=="。 (不带引号)

标签: c# encryption cryptography clickbank


【解决方案1】:

我刚刚解决了这个完全相同的问题,所以这是我的解决方案。要记住的是密码/密钥由 sha1 散列,前 32 个十六进制字符用作密钥字节。让我失望的部分是字符是 c# 中的 UFT16 字符,实际上每个字符是 2 个字节,但不是源加密使用的字符。所以我所做的就是将字符串转换为具有正确字节数组的 ASCII 字符串。不是最干净的代码,但它的功能。

    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;
    }

【讨论】:

  • UTF-8 字符对于 ASCII 字符是单字节,对于其他字符是多字节。 UTF-16 是 ASCII 字符的两个字节字符,这种格式通常在计算机语言内部使用。
  • 对不起,你是对的,我的意思是 UTF-16 是内部字符串表示,但答案仍然成立。将答案从 UTF-8 更新为 UTF-16
【解决方案2】:

如果您的 v 有 16 个字母,而您 Encoding.UTF8.GetBytes(v); 则字节数可能在 16 到 64 之间。这可能会给您带来错误。

指定的初始化向量 (IV) 与块大小不匹配 对于这个算法。

验证 iv 是 16 个字节。

【讨论】:

  • IV 的值为 "NDVEM0M4ODZGMzE4OTVENA==" 长度为 24 个字母。我认为它在 Base64 中。 IV 必须为 16 个字节长。 var ivArray = System.Convert.FromBase64String("NDVEM0M4ODZGMzE4OTVENA==");我理解正确。而且,Key 必须是 32 字节长。我的密钥长度是 16 个字母。它是十六进制格式。当我将它转换为 UTF-8 时,它给了我 16 个字节。 (不工作)当我将它转换为 Unicode 时,它​​给了我 32 个字节。 (即使不工作)。在 java 代码 SHA-1 中,使用了 UTF-8 编码。所以,我认为这是我缺少的东西
  • 已检查。 iv 是 16 字节长
猜你喜欢
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-22
  • 1970-01-01
  • 2017-09-28
  • 1970-01-01
相关资源
最近更新 更多