解密 TripleDES:指定的密钥是已知的弱密钥,不能使用

Decrypting TripleDES: Specified key is a known weak key and cannot be used

为什么这段代码return 弱键错误?

static public byte[] TDESDecrypt(byte[] toDecrypt, byte[] key, CipherMode mode = CipherMode.ECB, PaddingMode padding = PaddingMode.None)
{
    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    tdes.Key = key;
    tdes.Mode = mode;
    tdes.Padding = padding;
    ICryptoTransform cTransform = tdes.CreateDecryptor();
    byte[] resultArray = cTransform.TransformFinalBlock(toDecrypt, 0, toDecrypt.Length);
    tdes.Clear();
    return resultArray;
}

当我尝试执行行 "tdes.Key = key" 时,出现错误

deriveSessionKeyIS System.Security.Cryptography.CryptographicException: Specified key is a known weak key for TripleDES and cannot be used

为什么?我正在尝试的密钥是随机的,但是测试的密钥之一是 FB13347FE570DC4FFB13347FE570DC4F。问题出在哪里?

您可以阅读 wikipedia for example about what is the weak key in cryptography. For triple DES there is a method (TripleDES.IsWeakKey),它检查三重 DES 密钥是否存在弱点。在您的情况下,密钥 FB13347FE570DC4FFB13347FE570DC4F 在某种意义上是对称的,即它的前 8 个字节与后 8 个字节完全相等。这意味着如果你用那个密钥加密一些东西,然后再 encrypt 那个加密的信息 - 你将恢复原始文本(因为这个具体的加密算法是如何工作的),这显然是危险的.

所以简而言之,.NET 可以保护您免于做导致密码漏洞的危险事情。如果您将使用标准 GenerateKey() 函数生成密钥(或者只是不明确设置 Key)- 将不会生成弱密钥。

关于为什么该密钥对于三重 DES 来说很弱的更多信息。 3DES 之所以这样命名,是因为它本质上使用 3 个密钥,并对这些密钥应用纯 DES encryption\decryption 3 次。每个密钥的长度为 8 个字节,因此 3DES 密钥大小为 8*3 = 24 个字节。但是,算法还允许第一个和第三个密钥相同,因此允许使用 16 字节密钥(如您的示例)。在那种情况下,这 16 个字节的前半部分用作第三个密钥。此选项提供的安全性较低,但仍然可行。

现在,如果您的 16 字节密钥的前半部分和后半部分相同,那么 3DES 将使用的所有 三个 密钥都是相同的。假设 3DES 是这样工作的:

DES encrypt with 3rd(DES Decrypt with 2nd(DES Encrypt with 1st(plaintext)))

您会看到,在您的情况下,您退回到使用简单的 DES,这首先违背了使用 3DES 的全部目的。

这是一个弱 3DES 密钥,因为附加的 8 字节将再次作为最后 8 位重复。因此 3DES 加密已恢复为 DES 并且很弱。

3DES 执行三个操作,最常见的形式是 ede 数据首先用密钥的前 8 字节加密,然后用第二个 8 字节解密,最后用最后的密钥加密8 字节(在本例中是前 8 字节)。请注意,在前两个操作之后,数据恢复为原始数据,因此实际执行的唯一加密是最后一次加密,即 8 字节,即 56 位密钥。那是一个弱 3DES 密钥。

我在 MSDN 论坛上找到了 this 解决方案。此解决方案与弱密钥完美配合。

我用论坛的代码做了这个:

using System.Security.Cryptography;
using System.IO;
using System.Reflection;

static class MyDES
{
    public static byte[] Encrypt(byte[] data, byte[] key, byte[] IV)
    {
        MemoryStream mStream = new MemoryStream();
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
        des.Mode = CipherMode.ECB;
        des.Padding = PaddingMode.None;
        CryptoStream cStream = new CryptoStream(mStream,
            des.CreateWeakEncryptor(key, IV),
            CryptoStreamMode.Write);
        cStream.Write(data, 0, data.Length);
        cStream.FlushFinalBlock();
        byte[] ret = mStream.ToArray();
        cStream.Close();
        mStream.Close();
        return ret;
    }

    public static byte[] Decrypt(byte[] data, byte[] key, byte[] IV)
    {
        MemoryStream msDecrypt = new MemoryStream(data);
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
        des.Mode = CipherMode.ECB;
        des.Padding = PaddingMode.None;
        CryptoStream csDecrypt = new CryptoStream(msDecrypt,
            des.CreateWeakDecryptor(key, IV),
            CryptoStreamMode.Read);
        byte[] fromEncrypt = new byte[data.Length];
        csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
        return fromEncrypt;
    }


    #region DESCryptoExtensions
    public static ICryptoTransform CreateWeakEncryptor(this DESCryptoServiceProvider cryptoProvider, byte[] key, byte[] iv)
    {
        MethodInfo mi = cryptoProvider.GetType().GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance);
        object[] Par = { key, cryptoProvider.Mode, iv, cryptoProvider.FeedbackSize, 0 };
        ICryptoTransform trans = mi.Invoke(cryptoProvider, Par) as ICryptoTransform;
        return trans;
    }
    public static ICryptoTransform CreateWeakEncryptor(this DESCryptoServiceProvider cryptoProvider)
    {
        return CreateWeakEncryptor(cryptoProvider, cryptoProvider.Key, cryptoProvider.IV);
    }
    public static ICryptoTransform CreateWeakDecryptor(this DESCryptoServiceProvider cryptoProvider, byte[] key, byte[] iv)
    {
        return CreateWeakEncryptor(cryptoProvider, key, iv);
    }
    public static ICryptoTransform CreateWeakDecryptor(this DESCryptoServiceProvider cryptoProvider)
    {
        return CreateWeakDecryptor(cryptoProvider, cryptoProvider.Key, cryptoProvider.IV);
    }
    #endregion
}