我的“要解密的数据长度无效”错误

时间:2011-08-11 11:34:08

标签: c# .net cryptography

我有一个客户端/服务器应用程序。服务器和客户端通信已加密。服务器将加密的消息发送到客户端和客户端解密消息并获取它。与客户端消息相同。 “如果我向客户端发送大数据或客户端向服务器发送大数据,我将获得要解密的数据长度无效”错误。如果发送数据的长度很小,则没有问题。加密或解密数据长度是否有任何限制?

这是我的代码:

  static byte[] Encrypt(byte[] plaintext, byte[] key, byte[] IV)
    {
        RijndaelManaged myRijndael = new RijndaelManaged();
        myRijndael.Padding = PaddingMode.PKCS7;
        ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, IV);
        MemoryStream msEncrypt = new MemoryStream();
        CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
        csEncrypt.Write(plaintext, 0, plaintext.Length);
        csEncrypt.FlushFinalBlock();

        return msEncrypt.ToArray();

    }


    public static string Encrypt(string plainText, string password)
    {

        byte[] byteDizi = Encoding.Unicode.GetBytes(plaintext);


        PasswordDeriveBytes pdb = new PasswordDeriveBytes(password,
                                                          new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
                                                                      0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});


        byte[] sifreliV = Encrypt(byteDizi,
           pdb.GetBytes(32), pdb.GetBytes(16));
        return Convert.ToBase64String(sifreliV);

    }


    // Dekriptolama bir parola ve IV kullanarak

    static byte[] Decrypt(byte[] encryptedData,
                          byte[] Key, byte[] IV)
    {
        RijndaelManaged myRijndael = new RijndaelManaged();
        myRijndael.Padding = PaddingMode.PKCS7;
        ICryptoTransform decryptor = myRijndael.CreateDecryptor(Key, IV);
        MemoryStream msDecrypt = new MemoryStream(encryptedData);
        CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
        byte[] fromEncrypt = new byte[encryptedData.Length];
        csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);

        return fromEncrypt;

    }


    public static string Decrypt(string encryptedData, string password)
    {

        byte[] encryptedByte = Convert.FromBase64String(encryptedData);

        PasswordDeriveBytes pdb = new PasswordDeriveBytes(password,
                                                          new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 
                                                                      0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

        byte[] DecryptedData = Decrypt(encryptedByte,
            pdb.GetBytes(32), pdb.GetBytes(16));

        return Encoding.Unicode.GetString(DecryptedData);
    }
}

1 个答案:

答案 0 :(得分:0)

其他人提到了我认为会有所帮助的建议;我不会立即发现您发布的代码有任何问题会导致您描述的行为。

想要提及的是这个实现存在一些严重的安全问题:

  1. 密码salt不是特定于密码的。最好使用密码将salt存储在数据库中。每个密码都应该有一个独特的随机盐。这样,如果有人发现一个密码哈希的密码,他们就不会知道其他用户帐户是否有相同的密码。

  2. 初始化向量(“IV”)来自密码,就像密钥一样。这意味着用户使用相同密码完成的每次加密都将具有相同的IV。 IVs应该从不重复使用。 http://en.wikipedia.org/wiki/Initialization_vector#Properties指出IV必须是唯一且不可预测的。使用RNGCryptoServiceProvider生成随机IV。

    通常我喜欢在我的加密函数中生成随机IV。然后我将IV添加到加密消息中。解密函数从加密消息的开头剥离IV以初始化解密类,然后解密剩余的字节。

    这样做的原因是以相同明文开头的两条消息(例如,公共标题结构)和使用相同密钥加密的消息在开头会有相同的密文。攻击者可以使用它来发现密钥。

  3. 现代密码术只有完美地完成所有细节才能很好地运作。否则,即使很小的实施问题也可能导致它在严重的安全问题上迅速崩溃 - 并且在它被破坏之前没有人注意到。获取您的工作,然后实施这些更改。