【问题标题】:Specified key is not a valid size for this algorithm指定的密钥不是此算法的有效大小
【发布时间】:2011-02-24 13:01:11
【问题描述】:

我有这个代码:

RijndaelManaged rijndaelCipher = new RijndaelManaged();

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

我得到了投掷:

Specified key is not a valid size for this algorithm.

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

这个字符串有什么问题?我可以数一下你的一些示例字符串吗?

【问题讨论】:

    标签: c# encryption rijndaelmanaged


    【解决方案1】:

    base64 解码后的字符串“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678912”产生 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 相同的字节数组将起作用。

    【讨论】:

    • 有趣的巧合...这是我用于所有加密算法的相同密钥...
    • 其实它似乎支持a few more keysizes 但那是因为一个bug。只是不要忘记在单元测试期间解决该错误。
    【解决方案2】:

    使用随机数生成器类(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;
    

    请注意,可以使用相同的过程来派生密钥。希望这会有所帮助。

    【讨论】:

    • 如果你使用随机数生成密钥来加密密码,你以后怎么能回来(生成不同的随机密钥)并确认密码正确?
    • @jp2code 只要您将 ivBytes 存储在某处,这实际上是一个出色且安全的解决方案,这是我认为此答案打算让您执行的操作(但未明确显示)
    【解决方案3】:

    RijndaelManaged 算法支持 128、192 或 256 位的密钥长度。您的钥匙是这些尺寸之一吗?

    【讨论】:

    • 我不明白:/我要编码的字符串长度为 40 - 200
    【解决方案4】:

    这是我创建的类

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

    【讨论】:

      【解决方案5】:

      我不知道 rijndaelCipher.Key 的长度 如果是24,那么rijndaelCipher.Key = s.SubString(0, 24);

      这么简单。

      【讨论】:

        猜你喜欢
        • 2020-09-25
        • 1970-01-01
        • 2010-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-24
        相关资源
        最近更新 更多