【问题标题】:.NET AES-128 decryption returns a blank string.NET AES-128 解密返回一个空白字符串
【发布时间】:2014-04-21 16:19:26
【问题描述】:

我在解密示例应用程序中的简单值时遇到问题。该值是使用相同的示例应用程序加密的。我已经列出了下面的代码。

当代码块完成时,结果是plain 是一个空字符串。不会引发异常。

string plain = null;

using (AesManaged alg = new AesManaged())
{
    // Extract the initialization vector from the entire ciphertext
    byte[] IV = new byte[alg.IV.Length];
    Buffer.BlockCopy(cipherText, 0, IV, 0, alg.IV.Length);

    alg.IV = IV;
    alg.Key = GetKey();

    ICryptoTransform transform = alg.CreateDecryptor();

    // Extract the encrypted value from the entire ciphertext
    byte[] encrypted = new byte[cipherText.Length - alg.IV.Length];
    Buffer.BlockCopy(cipherText, alg.IV.Length, encrypted, 0, cipherText.Length - alg.IV.Length);

    using (MemoryStream ms = new MemoryStream(encrypted))
    {
        using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read))
        {
            using (StreamReader r = new StreamReader(cs))
            {
                cs.Flush();
                plain = r.ReadToEnd();
            }
        }
    }
}

我已验证cipherText(作为参数传递的 32 字节字节 [])具有与加密产生的值相同的字节。 IV 和 Key 也是逐字节相同的。注意:IV 由加密逻辑添加到加密值之前。这就是第一行从代码块中提取它的原因。

我还验证了encrypted byte[] 的内容与加密例程中的内容相同。内容只有 16 个字节。

我已经验证了MemoryStreamms中的Position是0,经过例程后是16。所以看起来MemoryStream被读取了。我的怀疑是我错误地使用了StreamReader,但我看不出我在哪里犯了错误。

我尝试修改加密字节[] 中的一个字节,然后如预期的那样得到CryptographicException(填充无效)。因此,从密码学的角度来看,我的 IV、密钥和加密值似乎都是有序的。出于某种原因,它可能没有一直得到处理?

感谢您的任何见解。

为完整起见,加密例程如下: byte[] 加密 = null;

using (AesManaged alg = new AesManaged())
{
    System.Diagnostics.Debug.WriteLine("Key size: {0}", alg.KeySize);

    alg.GenerateIV();
    alg.Key = GetKey();

    ICryptoTransform transform = alg.CreateEncryptor(alg.Key, alg.IV);

    using (MemoryStream ms = new MemoryStream())
    using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write))
    using (StreamWriter w = new StreamWriter(cs))
    {
        w.Write(plainText);
        cs.FlushFinalBlock();

        // Create a byte array big enough to hold the IV and the encrypted value
        encrypted = new byte[alg.IV.Length + ms.Length];
        // Copy the random generated initialization vector to the start of the encrypted bytes
        Buffer.BlockCopy(alg.IV, 0, encrypted, 0, alg.IV.Length);
        // Copy the encrypted value at the end
        Buffer.BlockCopy(ms.ToArray(), 0, encrypted, alg.IV.Length, (int)ms.Length);
    }
}

【问题讨论】:

    标签: .net encryption aes


    【解决方案1】:

    我已经发现我犯的错误了。我使用非常短的字符串进行测试,我认为我的加密大小始终为 16 字节并不奇怪。

    当我用更长的字符串进行测试时,感觉不太对劲。事实证明,我的问题在于加密逻辑:除了CryptoStream 之外,我还需要刷新StreamWriter。所以下面是我现在工作的加密和解密逻辑。

    请注意,对逻辑的另一个改进是我现在还在密钥生成期间生成了一个随机盐,并且该随机盐也被添加到加密字节 []。

    private const int SaltLength = 8;
    
    public class KeyPackage
    {
        public byte[] KeySalt { get; set; }
        public byte[] Key { get; set; }
    }
    
    public KeyPackage GetKey()
    {
        // Read the password from the configuration
        string Key = System.Configuration.ConfigurationManager.AppSettings["EncryptionKey"];
    
        // Generate Key from the password stored in configuration using a random salt
        using (Rfc2898DeriveBytes db = new Rfc2898DeriveBytes(Key, SaltLength))
        {
            // Using AES-128, we need 128 / 8 bytes in the key
            return new KeyPackage() { Key = db.GetBytes(128 / 8), KeySalt = db.Salt };
        }
    }
    
    public byte[] GetKey(byte[] keySalt)
    {
        // Read the password from the configuration
        string Key = System.Configuration.ConfigurationManager.AppSettings["EncryptionKey"];
    
        // Generate Key from the password stored in configuration using the known salt
        using (Rfc2898DeriveBytes db = new Rfc2898DeriveBytes(Key, keySalt))
        {
            // Using AES-128, we need 128 / 8 bytes in the key
            return db.GetBytes(128 / 8);
        }
    }
    
    /// <summary>
    /// Encrypts the specified plain text using the
    /// encryption key found in the configuration file.
    /// </summary>
    /// <param name="plainText">The plain text to encrypted.</param>
    /// <returns>The cipher text.</returns>
    public byte[] Encrypt(string plainText)
    {
        byte[] encrypted = null;
    
        using (AesManaged alg = new AesManaged())
        {
            System.Diagnostics.Debug.WriteLine("Key size: {0}", alg.KeySize);
    
            alg.GenerateIV();
            KeyPackage kp = GetKey();
            alg.Key = kp.Key;
    
            ICryptoTransform transform = alg.CreateEncryptor();
    
            using (MemoryStream ms = new MemoryStream())
            using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write))
            using (StreamWriter w = new StreamWriter(cs))
            {
                w.Write(plainText);
                w.Flush(); // This was missing from my first post
                cs.FlushFinalBlock();
    
                // Create a byte array big enough to hold the IV and the encrypted value
                encrypted = new byte[kp.KeySalt.Length + alg.IV.Length + ms.Length];
                // Copy the random generated salt to the start of the encrypted bytes
                Buffer.BlockCopy(kp.KeySalt, 0, encrypted, 0, kp.KeySalt.Length);
                // Copy the random generated initialization vector to the start of the encrypted bytes
                Buffer.BlockCopy(alg.IV, 0, encrypted, kp.KeySalt.Length, alg.IV.Length);
                // Copy the encrypted value at the end
                Buffer.BlockCopy(ms.ToArray(), 0, encrypted, alg.IV.Length + kp.KeySalt.Length, (int)ms.Length);
            }
        }
        return encrypted;
    }
    
    /// <summary>
    /// 
    /// </summary>
    /// <param name="cipherText"></param>
    /// <returns></returns>
    public string Decrypt(byte[] cipherText)
    {
        string plain = null;
    
        using (AesManaged alg = new AesManaged())
        {
            // Extract the initialization vector from the entire ciphertext
            byte[] IV = new byte[alg.IV.Length];
            byte[] KeySalt = new byte[SaltLength];
    
            Buffer.BlockCopy(cipherText, 0, KeySalt, 0, SaltLength);
            Buffer.BlockCopy(cipherText, SaltLength, IV, 0, alg.IV.Length);
    
            alg.IV = IV;
            alg.Key= GetKey(KeySalt);
    
            ICryptoTransform transform = alg.CreateDecryptor();
    
            // Extract the encrypted value from the entire ciphertext
            int ActualCipherLength = cipherText.Length - alg.IV.Length - SaltLength;
            byte[] encrypted = new byte[ActualCipherLength];
            Buffer.BlockCopy(cipherText, alg.IV.Length + SaltLength, encrypted, 0, ActualCipherLength);
    
            using (MemoryStream ms = new MemoryStream(encrypted))
            using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read))
            using (StreamReader r = new StreamReader(cs))
            {
                plain = r.ReadToEnd();
            }
        }
        return plain;
    }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    • 1970-01-01
    相关资源
    最近更新 更多