如何正确和一致地从字符串中获取AES加密的字节?

Man*_*dos 8 c# encryption byte aes

我目前正在使用C#进行AES实现.加密方法有两个参数:字符串和密码.我正在提供提供的字符串并将其转换为字节数组,因此我可以稍后使用它将数据写入流中BinaryWriter.

问题是,当我使用Convert.FromBase64String(string)我得到FormatException: Invalid length.,当我用Encoding.UTF8.GetBytes(string)我的解密方法抛出的和无效的PKCS7.Padding例外.

在过去的几天里,我一直在努力解决这个问题.我已经在stackoverflow.com和其他网站上阅读了几乎无限的问题,但我仍然不知道什么是最可靠的方法来解决这个问题.

将在此程序中使用的字符串仅限于句子(例如"Something to encrypt.")和数字(例如"12345").

提前谢谢,这是我现在的代码:

    public class AESProvider {

    public byte[] EncryptStringToBytes_Aes(string plainText, string Key)
    {
        // Check arguments. 
        if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException("plainText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        byte[] plainTextInBytes = Convert.FromBase64String(plainText);
        byte[] encrypted;

        //Create an Aes object
        //with the specified key and IV.

        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.GenerateIV();
            byte[] IV = aesAlg.IV;
            //The Salt will be the first 8 bytes of the IV.
            byte[] theSalt = new byte[8];
            Array.Copy(IV,theSalt,8);
            //A key for AES is generated by expanding the password using the following method.
            Rfc2898DeriveBytes keyGen = new Rfc2898DeriveBytes(Key,theSalt);
            byte[] aesKey = keyGen.GetBytes(16);
            aesAlg.Key = aesKey;

            // Create a decrytor to perform the stream transform.
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, IV);

            // Create the streams used for encryption. 
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (BinaryWriter swEncrypt = new BinaryWriter(csEncrypt))
                    {

                        //Write all data to the stream.
                        swEncrypt.Write(plainTextInBytes);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
            // Prepend the IV to the ciphertext so it can be used in the decryption process.
            using (MemoryStream ivPlusCipher = new MemoryStream())
            {
                using (BinaryWriter tBinaryWriter = new BinaryWriter(ivPlusCipher))
                {
                    tBinaryWriter.Write(IV);
                    tBinaryWriter.Write(encrypted);
                    tBinaryWriter.Flush();
                }
                return ivPlusCipher.ToArray();
            }
        }
    }

    public byte[] DecryptStringFromBytes_Aes(byte[] cipherText, string Key)
    {
        // Check arguments. 
        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException("cipherText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        // Declare the string used to hold 
        // the decrypted text. 
        byte[] decrypted;

        // Create an Aes object 
        // with the specified key and IV. 

        // Create the streams used for decryption. 

        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Mode = CipherMode.CBC;
            aesAlg.Padding = PaddingMode.PKCS7;
            //Grab IV from ciphertext
            byte[] IV = new byte[16];
            Array.Copy(cipherText,0,IV,0,16);
            //Use the IV for the Salt
            byte[] theSalt = new byte[8];
            Array.Copy(IV,theSalt,8);
            Rfc2898DeriveBytes keyGen = new Rfc2898DeriveBytes(Key,theSalt);
            byte[] aesKey = keyGen.GetBytes(16);
            aesAlg.Key = aesKey;

            // Create a decrytor to perform the stream transform.
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, IV);

            using (MemoryStream msDecrypt = new MemoryStream())
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
                {
                    using (BinaryWriter srDecrypt = new BinaryWriter(csDecrypt))
                    {
                        //Decrypt the ciphertext
                        srDecrypt.Write(cipherText, IV.Length, (cipherText.Length - IV.Length));
                    }
                    decrypted = msDecrypt.ToArray();
                    return decrypted;
                }
            }   
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ras*_*ber 11

您需要在加密/解密之前和之后在字节和字符串之间进行转换.这不是相同的操作,您不应该使用相同的方法.

加密时,您可以从任意字符串开始.使用将其转换为byte [] Encoding.UTF8.GetBytes().加密它.现在可以使用生成的byte []转换为字符串Convert.ToBase64String().

解密时,现在开始使用Base64编码的字符串.使用将其解码为byte [] Convert.FromBase64String().解密它.您现在拥有原始字符串的UTF-8编码,您可以使用它进行解码Encoding.UTF8.GetString().

记得:

  • Encoding.UTF8用于将任意字符串转换为字节数组(但它只能转换包含实际UTF8编码的字节数组).
  • 转换.[To/From] Base64String用于将任意字节数组转换为字符串(但它只能转换包含实际Base64编码的字符串).