指定的密钥大小不适用于此算法。

67

我有这段代码:

RijndaelManaged rijndaelCipher = new RijndaelManaged();
              
// Set key and IV
rijndaelCipher.Key = Convert.FromBase64String("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678912");
rijndaelCipher.IV = Convert.FromBase64String("1234567890123456789012345678901234567890123456789012345678901234");

我遇到了这个异常:

指定的密钥不是此算法的有效大小。

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

这些字符串有什么问题?你能给我一些例子吗?

5个回答

107

字符串"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678912"进行base64解码后可以得到48个字节(384位)。RijndaelManaged支持128、192和256位的密钥。

一个有效的128位密钥是new byte[]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },如果你需要从base64中获取,则为Convert.FromBase64String("AAECAwQFBgcICQoLDA0ODw==")

默认的块大小是128位,因此同样的字节数组可以作为IV。


84
有趣的巧合...那正是我用于所有加密算法的秘钥... - Narnian
2
实际上,它似乎支持更多的密钥大小,但那是因为有一个错误。在单元测试期间不要忘记解决这个错误。 - Maarten Bodewes

6
使用随机数生成器类(RNGCryptoServiceProvider)按如下方式将指定缓冲区填充为随机字节:
var numberOfBits = 256; // or 192 or 128, however using a larger bit size renders the encrypted data harder to decipher

var ivBytes = new byte[numberOfBits / 8]; // 8 bits per byte

new RNGCryptoServiceProvider().GetBytes(ivBytes);

var rijndaelManagedCipher = new RijndaelManaged();

//Don't forget to set the explicitly set the block size for the IV if you're not using the default of 128

rijndaelManagedCipher.BlockSize = 256;

rijndaelManagedCipher.IV = ivBytes;

注意,相同的过程可以用来生成一个密钥。希望这有所帮助。

11
如果您使用随机数生成密钥来加密密码,那么如何在以后返回(生成不同的随机密钥)并确认该密码是正确的? - user153923
@jp2code 这实际上是一个很棒且安全的解决方案,只要你将ivBytes存储在某个地方,这也是我认为这个答案打算让你去做的(但没有明确展示)。 - AlgoRythm

2

RijndaelManaged算法支持128位、192位或256位的密钥长度。你的密钥是否是这些长度之一?


1
我不明白 :/ 我要编码的字符串长度为40-200。 - user278618
我将字符串转换为字节数组后,它的长度确实是16个字节,但仍然无法接受。 - Kemsikov

0
这里是我创建的类。
public class ByteCipher
{
    // This constant is used to determine the keysize of the encryption algorithm in bits.
    // We divide this by 8 within the code below to get the equivalent number of bytes.
    private int _Keysize = (int)GlobalConfiguration.DataEncode_Key_Size;

    private byte[] saltStringBytes;

    private byte[] ivStringBytes;
    // This constant determines the number of iterations for the password bytes generation function.
    private const int DerivationIterations = 1000;
    private string _passPhrase = GlobalConfiguration.DataEncode_Key;

    private const string salt128 = "kljsdkkdlo4454GG";
    private const string salt256 = "kljsdkkdlo4454GG00155sajuklmbkdl";

    public ByteCipher(string passPhrase = null, DataCipherKeySize keySize = DataCipherKeySize.Key_128)
    {
        if (!string.IsNullOrEmpty(passPhrase?.Trim()))
            _passPhrase = passPhrase;
        _Keysize = keySize == DataCipherKeySize.Key_256 ? 256 : 128;
        saltStringBytes = _Keysize == 256 ? Encoding.UTF8.GetBytes(salt256) : Encoding.UTF8.GetBytes(salt128);
        ivStringBytes = _Keysize == 256 ? Encoding.UTF8.GetBytes("SSljsdkkdlo4454Maakikjhsd55GaRTP") : Encoding.UTF8.GetBytes("SSljsdkkdlo4454M");
    }

    public byte[] Encrypt(byte[] plainTextBytes)
    {
        if (plainTextBytes.Length <= 0)
            return plainTextBytes;

        using (var password = new Rfc2898DeriveBytes(_passPhrase, saltStringBytes, DerivationIterations))
        {
            var keyBytes = password.GetBytes(_Keysize / 8);
            using (var symmetricKey = new RijndaelManaged())
            {
                symmetricKey.BlockSize = _Keysize;
                symmetricKey.Mode = CipherMode.CBC;
                symmetricKey.Padding = PaddingMode.PKCS7;
                using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
                {
                    using (var memoryStream = new MemoryStream())
                    {
                        using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                        {
                            cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                            cryptoStream.FlushFinalBlock();
                            // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
                            var cipherTextBytes = saltStringBytes;
                            cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
                            cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
                            memoryStream.Close();
                            cryptoStream.Close();
                            return cipherTextBytes;
                        }
                    }
                }
            }
        }
    }

    public byte[] Decrypt(byte[] cipherTextBytesWithSaltAndIv)
    {
        if (cipherTextBytesWithSaltAndIv.Length <= 0)
            return cipherTextBytesWithSaltAndIv;
        var v = Encoding.UTF8.GetString(cipherTextBytesWithSaltAndIv.Take(_Keysize / 8).ToArray());
        if (v != salt256 && v != salt128)
            return cipherTextBytesWithSaltAndIv;

        var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((_Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((_Keysize / 8) * 2)).ToArray();

        using (var password = new Rfc2898DeriveBytes(_passPhrase, saltStringBytes, DerivationIterations))
        {
            var keyBytes = password.GetBytes(_Keysize / 8);
            using (var symmetricKey = new RijndaelManaged())
            {
                symmetricKey.Mode = CipherMode.CBC;
                symmetricKey.Padding = PaddingMode.PKCS7;
                symmetricKey.BlockSize = _Keysize;

                using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
                {
                    using (var memoryStream = new MemoryStream(cipherTextBytes))
                    {
                        using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                        {
                            var plainTextBytes = new byte[cipherTextBytes.Length];
                            var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                            memoryStream.Close();
                            cryptoStream.Close();
                            return plainTextBytes;
                        }
                    }
                }
            }
        }
    }
}

-6

我不知道rijndaelCipher.Key的长度。

如果是24,则rijndaelCipher.Key = s.SubString(0, 24);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接