要解密的数据长度无效AES C#

时间:2017-07-16 05:50:27

标签: c# encryption cryptography

我试图通过this thread了解有关加密的更多信息,并且我在评论中提到了一些改变。

当它尝试将valueBytes转换为Byte时出现异常,这是奇怪的,valueBytes已经是byte[]

byte[] vectorBytes = GetBytes<ASCIIEncoding>(_vector);
byte[] saltBytes = GetBytes<ASCIIEncoding>(_salt);
byte[] valueBytes = GetBytes<UTF8Encoding>(value);

byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector);
byte[] saltBytes = Encoding.ASCII.GetBytes(_salt);
byte[] valueBytes = Encoding.UTF8.GetBytes(value);

加密,工作正常但解密..

private static int _iterations = 2;
    private static int _keySize = 256;

    private static string _hash = "SHA1";
    private static string _salt = "aselrias38490a32"; // Random
    private static string _vector = "8947az34awl34kjq"; // Random


    public static string Encrypt(string value, string password)
    {
        return Encrypt<AesManaged>(value, password);
    }
    public static string Encrypt<T>(string value, string password)
        where T : SymmetricAlgorithm, new()
    {
        byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector);
        byte[] saltBytes = Encoding.ASCII.GetBytes(_salt);
        byte[] valueBytes = Encoding.UTF8.GetBytes(value);

        byte[] encrypted;
        using (T cipher = new T())
        {
            PasswordDeriveBytes _passwordBytes =
                new PasswordDeriveBytes(password, saltBytes, _hash, _iterations);
            byte[] keyBytes = _passwordBytes.GetBytes(_keySize / 8);

            cipher.Mode = CipherMode.CBC;

            using (ICryptoTransform encryptor = cipher.CreateEncryptor(keyBytes, vectorBytes))
            {
                using (MemoryStream to = new MemoryStream())
                {
                    using (CryptoStream writer = new CryptoStream(to, encryptor, CryptoStreamMode.Write))
                    {
                        writer.Write(valueBytes, 0, valueBytes.Length);
                        writer.FlushFinalBlock();
                        encrypted = to.ToArray();
                    }
                }
            }
            cipher.Clear();
        }
        return Convert.ToBase64String(encrypted);
    }

    public static string Decrypt(string value, string password)
    {
        return Decrypt<AesManaged>(value, password);
    }
    public static string Decrypt<T>(string value, string password) where T : SymmetricAlgorithm, new()
    {
        byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector);
        byte[] saltBytes = Encoding.ASCII.GetBytes(_salt);
        byte[] valueBytes = Encoding.UTF8.GetBytes(value);

        byte[] decrypted;
        int decryptedByteCount = 0;

        using (T cipher = new T())
        {
            PasswordDeriveBytes _passwordBytes = new PasswordDeriveBytes(password, saltBytes, _hash, _iterations);
            byte[] keyBytes = _passwordBytes.GetBytes(_keySize / 8);

            cipher.Mode = CipherMode.CBC;

            try
            {
                using (ICryptoTransform decryptor = cipher.CreateDecryptor(keyBytes, vectorBytes))
                {
                    using (MemoryStream from = new MemoryStream(valueBytes))
                    {
                        using (CryptoStream reader = new CryptoStream(from, decryptor, CryptoStreamMode.Read))
                        {
                            decrypted = new byte[valueBytes.Length];
                            decryptedByteCount = reader.Read(decrypted, 0, decrypted.Length);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                return String.Empty;
            }

            cipher.Clear();
        }
        return Encoding.UTF8.GetString(decrypted, 0, decryptedByteCount);
    }

2 个答案:

答案 0 :(得分:3)

Encrypt结束时,您正在撰写return Convert.ToBase64String(encrypted);。您需要在解密期间撤消此过程,而您当前没有这样做:byte[] valueBytes = Encoding.UTF8.GetBytes(value);

将其更改为byte[] valueBytes = Convert.FromBase64String(value);

安全问题:

IV必须是不可预测的(读取:随机),盐必须是随机的。不要使用静态IV和盐,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定何时发送相同的消息前缀。 IV和盐并不是秘密,因此您可以将它们与密文一起发送。通常,它们只是在密文之前加上密码并在解密前切掉。

最好对您的密文进行身份验证,以便像padding oracle attack这样的攻击是不可能的。这可以使用经过身份验证的模式(如GCM或EAX)或encrypt-then-MAC方案来完成。

答案 1 :(得分:1)

我不会使用ASCII编码将byte []转换为字符串。加密将为您提供0到255之间的字节值。这些值不会直接转换为使用ASCII编码器的字符串,ASCII编码器将这些值映射到基于ASCII表的字符串。如果你需要将byte []转换为字符串,你应该使用Convert.ToBase64String。

https://msdn.microsoft.com/en-us/library/dhx0d524(v=vs.110).aspx

这会将byte []转换为可打印字符(A-Za-z1-10 + /),然后可以将其转换回byte []进行解密。