如何正确并一致地从字符串中获取字节以进行AES加密? [英] How to correctly and consistely get bytes from a string for AES encryption?

查看:108
本文介绍了如何正确并一致地从字符串中获取字节以进行AES加密?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am currently working on AES implementation in C#. The encryption method has two parameters: a string and a password. I am taking the supplied string and converting it to an array of bytes, so I can use it later for writing data to a stream with BinaryWriter.

问题在于,当我使用 Convert.FromBase64String(string)时,我会得到 FormatException :无效的长度。,当我使用 Encoding.UTF8.GetBytes(string)时,我的解密方法引发并且无效的PKCS7.Padding异常。

The problem is that when I use Convert.FromBase64String(string) I get FormatException: Invalid length.and when I use Encoding.UTF8.GetBytes(string) my decryption method throws and invalid PKCS7.Padding exception.

最近几天我一直在尝试解决此问题。我已经在stackoverflow.com和其他网站上阅读了几乎无限的问题,但是我仍然不知道解决此问题的最可靠方法是什么。

I have been trying to solve this problem for the last couple of days. I have read near infinite questions in stackoverflow.com and other websites, but I still don't know what is the most reliable way to solve this problem.

在此程序中使用的密码仅限于句子(例如加密内容)和数字(例如 12345)。

Strings that will be used in this program are limited to sentences (ex. "Something to encrypt.") and numbers (ex. "12345").

在此先感谢您是我此时的代码:

Thank you in advance, here is the code I have at this point in time:

    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;
                }
            }   
        }
    }
}


推荐答案

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

You need to convert between bytes and strings before and after encryption/decryption. This is not the same operation, and you should not use the same method.

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

When encrypting you start out with an arbitrary string. Convert this to a byte[] using Encoding.UTF8.GetBytes(). Encrypt it. The resulting byte[] can now be converted to a string using Convert.ToBase64String().

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

When decrypting you now start out with a Base64 encoded string. Decode this to a byte[] using Convert.FromBase64String(). Decrypt it. You now have the UTF-8 encoding of your original string, which you can decode using Encoding.UTF8.GetString().

记住:


  • Encoding.UTF8可以将任意字符串转换为字节数组(但只能转换用于

  • 转换。[To / From] Base64String可以将任意字节数组转换为字符串(但只能将包含实际Base64编码的字符串转换回字符串)。 )。

这篇关于如何正确并一致地从字符串中获取字节以进行AES加密?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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