AES 解密无法识别的 unicode 结果

Unrecognized unicode result from AES decryption

我尝试为 encrypt/decrypt 一些字符串构建简单的 AES 加密助手 拳头,我有一个填充模式的问题,其中只有在零时才接受解密,否则会发生有关填充的错误! 第二个问题是当我尝试加密简单字符串时 "Hello World," 它被加密了,我有 base64 字符串,但是当尝试解密时,没有错误,但是显示了一个奇怪的未知字符!像㡲啁䎰廾ử靱힩㡲啁廰廾ử靱힩 我的代码:

        private static int keySizes = 256;
        private static int blockSize = 128;
        private static PaddingMode pMode = PaddingMode.Zeros;
        private static CipherMode cMode = CipherMode.ECB;
        private static byte[] key = GenEncryptionKey();
        private const string passphrase = @"StartYourMorningWithASmile";

    private static byte[] GenEncryptionKey()
    {
        HashAlgorithm hash = MD5.Create();
        return hash.ComputeHash(Encoding.Unicode.GetBytes(passphrase));
    }

    private static AesManaged CreateCryptor()
    {
        AesManaged cryptor = new AesManaged();
        cryptor.KeySize = keySizes;
        cryptor.BlockSize = blockSize;
        cryptor.Padding = pMode;
        cryptor.Key = key;
        cryptor.Mode = cMode;
        cryptor.GenerateIV();
        return cryptor;
    }
public static string EncryptParams(string reqVal)
        {
            string cipherText = "";

            if (string.IsNullOrEmpty(reqVal) || reqVal.Length < 1)
                throw new ArgumentNullException();
            byte[] plainBytes = Encoding.Unicode.GetBytes(reqVal);

            using (var cryptor = CreateCryptor())
            {
                ICryptoTransform encryptor = cryptor.CreateEncryptor();
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                    {
                        cs.Write(plainBytes, 0, plainBytes.Length);

                    }
                    byte[] cipherBytes = ms.ToArray();
                    cipherText = Convert.ToBase64String(cipherBytes);
                }
                cryptor.Clear();
            }
            return cipherText;

        }



        public static string DecryptParams(string resVal)
        {
            var data = Convert.FromBase64String(resVal);
            byte[] cipherBytes = new byte[data.Length];
            string plainText = "";

            using (var crypto = CreateCryptor())
            {


                ICryptoTransform Dec = crypto.CreateDecryptor();
                using (MemoryStream ms = new MemoryStream())
                {
                    using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Write))
                    {
                        cs.Write(cipherBytes, 0, cipherBytes.Length);
                        plainText = Encoding.Unicode.GetString(ms.ToArray());
                    }
                }
                crypto.Clear();
            }

            return plainText;
        }

更新 1:

正如@maarten-bodewes 指出的那样,请自行设置 IV 以实现成功解密。我错过了那部分,解密以某种方式(?)与您现有的代码一起工作,但您始终应该为对称加密算法提供相同的密钥和 IV,以使其双向工作。

原始答案:

您的解密失败(产生不正确的结果),因为您错误地实现了解密部分(通过使用 CryptoStreamMode.Write 而不是 CryptoStreamMode.Read)并且除了向解密流提供全零字节之外

的执行点
cs.Write(cipherBytes, 0, cipherBytes.Length);

变量cipherBytes全为零。真正的加密缓冲区在 data 变量中,你只用它来设置 cipherBytes

的长度

所以把你的解密方式改成这样

BONUS:修正解密部分后,您可以根据需要指定填充!我用PKCS7测试没问题

public static string DecryptParams(string resVal)
{
    var cipherBytes = Convert.FromBase64String(resVal);
    string plainText = "";

    using (var crypto = CreateCryptor())
    {
        ICryptoTransform Dec = crypto.CreateDecryptor();
        using (MemoryStream ms = new MemoryStream(cipherBytes))
        {
            using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Read))
            {
                byte[] decryptBlock = new byte[4096];
                MemoryStream decryptStream = new MemoryStream();
                int readBytes;
                while ((readBytes = cs.Read(decryptBlock, 0, 4096)) > 0)
                {
                    decryptStream.Write(decryptBlock, 0, readBytes);
                }
                plainText = Encoding.Unicode.GetString(decryptStream.ToArray());
            }
        }
        crypto.Clear();
    }

    return plainText;
}

希望对您有所帮助。

感谢奥古兹

以下是我修改后的描述方法

public static string DecryptParams(string resVal)
        {
            var data = Convert.FromBase64String(resVal);
            byte[] cipherBytes = new byte[data.Length];
            string plainText = "";

            using (var crypto = CreateCryptor())
            {  
                ICryptoTransform Dec = crypto.CreateDecryptor();
                using (MemoryStream ms = new MemoryStream(data))
                {
                    using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Read))
                    {
                        cs.Read(cipherBytes, 0, cipherBytes.Length);
                        plainText = Encoding.Unicode.GetString(cipherBytes.ToArray());
                    }
                }
                crypto.Clear();
            }

            return plainText;
        }

关于解密后 return 结果的另一件事我得到了原始字符串加上 [=17=][=17=][=17=][=17=] 所以我使用 myString.TrimEnd('\0') 来解决这个问题。