AES 256加密无法从字节数组正确获取IV

时间:2019-03-01 06:58:51

标签: c# cryptography

我正在尝试为AES 256加密创建一个处理程序类,并且我发现为每种加密使用不同的IV并将其放在字节数组的开头显然是安全的。所以我尝试添加它,但它无法正确获取。这是我的代码:

using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace EncryptionTest
{
    public class Aes256Handler
    {
        private byte[] key;

        public Aes256Handler(byte[] key)
        {
            this.key = key;
        }

        public string EncryptString(string plaintext)
        {
            return Encoding.UTF8.GetString(Encrypt(Encoding.UTF8.GetBytes(plaintext)));
        }

        public string DecryptString(string encryptedtext)
        {
            return Encoding.UTF8.GetString(Decrypt(Encoding.UTF8.GetBytes(encryptedtext)));
        }

        public byte[] Encrypt(byte[] bytes)
        {
            if (bytes == null || bytes.Length < 1)
            {
                throw new ArgumentException("Invalid bytes");
            }

            if (key == null || key.Length < 1)
            {
                throw new InvalidOperationException("Invalid encryption settings");
            }

            byte[] encrypted;

            try
            {
                using (Aes aes = Aes.Create())
                {
                    aes.Mode = CipherMode.CBC;
                    aes.Key = key;
                    aes.KeySize = 256;
                    aes.BlockSize = 128;
                    Util.PrintByteArray(aes.IV);
                    ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

                    using (MemoryStream ms = new MemoryStream())
                    {
                        ms.Write(aes.IV, 0, aes.IV.Length);

                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(bytes, 0, bytes.Length);
                            cs.FlushFinalBlock();
                        }

                        encrypted = ms.ToArray();
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
                throw new InvalidOperationException("Unable to encrypt data");
            }

            return encrypted;
        }

        public byte[] Decrypt(byte[] bytes)
        {
            if (bytes == null || bytes.Length < 1)
            {
                throw new ArgumentException("Invalid bytes");
            }

            if (key == null || key.Length < 1)
            {
                throw new InvalidOperationException("Invalid encryption settings");
            }

            byte[] decrypted;

            try
            {
                using (Aes aes = Aes.Create())
                {
                    aes.Mode = CipherMode.CBC;
                    aes.Key = key;
                    aes.KeySize = 256;
                    aes.BlockSize = 128;
                    byte[] iv = new byte[16];
                    MemoryStream ms = new MemoryStream(bytes);
                    ms.Read(iv, 0, iv.Length);
                    Util.PrintByteArray(iv);
                    ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, iv);

                    using (ms)
                    {
                        using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                        {
                            using (BinaryReader br = new BinaryReader(cs))
                            {
                                decrypted = new byte[iv.Length];
                                br.Read(decrypted, 0, decrypted.Length - iv.Length);
                            }
                        }

                        decrypted = ms.ToArray();
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
                throw new InvalidOperationException("Unable to decrypt data");
            }

            return decrypted;
        }
    }
}

输出:

Plain text: Hello World!
198 66 49 215 139 95 165 131 201 119 136 16 45 170 140 70 
Encrypted text: �B1׋_���w�-��F?�����8#*�����
239 191 189 66 49 215 139 95 239 191 189 239 191 189 239 191 
Decrypted text: �B1׋_���w�-��F?�����8#*�����

对于我的问题的解决方案和其他建议将不胜感激。

1 个答案:

答案 0 :(得分:1)

我提供了下面提供的代码的工作版本:

$user = $this->getUser();
$user->addRole('ROLE_ADMIN');
$this->get('fos_user.user_manager')->updateUser($user);
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.context')->setToken($token);

所做的主要更改是在处理加密的字节数组时使用Convert.ToBase64String和Convert.FromBase64String。我还删除了针对AES对象的不必要的参数声明,因为它只是设置默认值,并且我从解密方法中删除了不必要的解密= ms.ToArray()。

还有一点很重要,那就是在进行解密时,您想要获取读取的字节数。使用由于加密的块大小而增加的填充而没有修整解密的字节数组,您会发现由于填充而在该数组的结尾将为0。