C#AES解密代码 [英] C# AES Decryption code

查看:193
本文介绍了C#AES解密代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有使用AES算法的字符串加密/解密的代码。加密工作正常,但我无法获得正确的纯文本,当我解密回来。解密代码中必须有错误。

I have the code for string encryption/decryption with AES algorithm. Encryption works fine as expected but I could not get correct plain text when I decrypt it back. There must be something wrong in the decryption code.

我已复制下面的代码。

请帮助这个。感谢。

I have copied the code below.
Please help with this. Thanks.

下面是加密和解密代码。

Below is the encryption and Decryption code.

public static class EncryptionHelper
{
    private static int BlockSize = 16;

    private static byte[] Key
    {
        get
        {
            byte[] hash = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes("BlahBlahBlah"));
            byte[] key = new byte[BlockSize];
            Array.Copy(hash, 0, key, 0, BlockSize);
            return key;
        }
    }

    private static byte[] IV
    {
        get
        {
            StringBuilder builder = new StringBuilder();
            Random random = new Random();
            for (int i = 0; i < BlockSize; i++)
            {
                char ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                builder.Append(ch);
            }
            return Encoding.UTF8.GetBytes(builder.ToString());
        }
    }

    public static string DecodeAndDecrypt(string cipherText)
    {
        string DecodeAndDecrypt = AesDecrypt(Convert.FromBase64String(HttpUtility.UrlDecode(cipherText)));
        return (DecodeAndDecrypt);
    }

    public static string EncryptAndEncode(string plaintext)
    {
        return HttpUtility.UrlEncode(Convert.ToBase64String(AesEncrypt(plaintext))); 
    }

    public static string AesDecrypt(Byte[] inputBytes)
    {
        Byte[] outputBytes = inputBytes;

        string plaintext = string.Empty;

        using (MemoryStream memoryStream = new MemoryStream(outputBytes))
        {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, GetCryptoAlgorithm().CreateDecryptor(Key, IV), CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(cryptoStream))
                {
                    plaintext = srDecrypt.ReadToEnd();
                }
            }
        }

        return plaintext;
    }

    public static byte[] AesEncrypt(string inputText)
    {
        byte[] inputBytes = UTF8Encoding.UTF8.GetBytes(inputText); 

        for (int i = 0; i < BlockSize; i++)
        {
            inputBytes[i] ^= IV[i];
        }

        byte[] result = null;
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, GetCryptoAlgorithm().CreateEncryptor(Key, IV), CryptoStreamMode.Write))
            {
                cryptoStream.Write(inputBytes, 0, inputBytes.Length);
                cryptoStream.FlushFinalBlock();
                result = memoryStream.ToArray();
            }
        }
        return result;
    }

    private static RijndaelManaged GetCryptoAlgorithm()
    {
        RijndaelManaged algorithm = new RijndaelManaged();
        algorithm.Padding = PaddingMode.PKCS7;
        algorithm.Mode = CipherMode.CBC;
        algorithm.KeySize = 128;
        algorithm.BlockSize = 128;
        return algorithm;
    }
}


推荐答案

上面的注释(在问题上)有最重要的一点:你需要使用与encrypt上使用的同样的解密方法,否则你的前16个字节的恢复的纯文本将被丢弃。 (CBC模式将在第一个块之后自动更正。)

The comments above (on the question) have the most important point: you need to use the same IV on decrypt as used on the encrypt, otherwise your first 16 bytes of recovered plaintext will be trashed. (CBC mode will auto-correct after the first block.)

您可以在发送之前简单地将IV与密文相结合,然后在另一个

You could simply combine the IV with the ciphertext before sending it, and then just break them apart at the other end before decrypting.

如果IV是公开的知识,只要它是加密强的,随机数据,每个加密不同。但是你需要在对方的相同,个别IV在另一端解密。

It doesn't matter if the IV is public knowledge, as long as it is cryptographically strong, random data, different for each encryption. But you need that same corresponding, individual IV at the other end to decrypt.

另外,正如WDS指出,你不应该执行XOR操作。 (但我不能看到WDS的代码恢复前16个字节,而不保留IV。)

Also, as WDS points out, you should not perform that XOR operation. (But I can't see how WDS's code recovers the first 16 bytes without preserving the IV.)

此外,IMHO使用SHA1的密码生成密钥安全风险。你应该使用PBKDF2或类似的方法来导出密码。

Also, IMHO using a SHA1 over the password to generate the key is a security risk. You should be using PBKDF2 or similar to derive a password.

编辑:As Artjom B.指出,由于原始代码XOR是针对第一个明文块的IV,您可以通过使用解密时所有0x00字节的IV恢复前16个字节。但这只会工作,如果密文至少两个块(32字节),否则,你会得到填充错误,因为这将损坏填充。尝试在解密时使用所有零字节的IV,并确定输入是否始终至少为16个字节 - 如果不是加密,则在加密中有一个off-the-end-of-the-array错误。 (你仍然有一个不安全的IV,但至少你会得到解密工作。)

As Artjom B. points out, since your original code XOR's the IV against the first block of plaintext, you could recover the first 16 bytes by using an IV of all 0x00 bytes on decrypt. But this would only work if the ciphertext was at least two blocks (32 bytes), otherwise, you will get padding errors as this will corrupt the padding. Try using an IV of all zero bytes on your decrypt, and find out if the input is always at least 16 bytes -- you have an off-the-end-of-the-array bug anyway in your encrypt if it isn't. (You'll still have an insecure IV, but at least you will get decrypt working.)

这篇关于C#AES解密代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆