在 .NET Core 和 .NET Framework 中使用 AES 进行加密和解密

发布:2024-09-12 16:03 阅读:10 点赞:0

一. 介绍

AES(高级加密标准)是一种对称密钥算法,这意味着加密和解密使用相同的密钥。与非对称加密(使用公钥进行加密和私钥进行解密)不同,AES 在处理数据时,保持了密钥的一致性。

二. 加密过程

1. 设置 RijndaelManaged 对象

using (var rijndaelManaged = new RijndaelManaged 
{
    Key = cryptkey, 
    IV = initVector, 
    Mode = CipherMode.CBC, 
    Padding = PaddingMode.PKCS7, 
    KeySize = 128 
})
  • RijndaelManaged: .NET 框架中用于执行 AES 加密的类。
  • Key: 加密密钥。必须是 128、192 或 256 位(16、24 或 32 字节)长。
  • IV: 初始化向量,用于为加密过程添加随机性。
  • Mode = CipherMode.CBC: 设置为密码块链模式(CBC)。在加密前,每块明文会与前一个密文块进行异或操作。
  • Padding = PaddingMode.PKCS7: 指定填充方案,以确保数据长度与密码块大小兼容。
  • KeySize = 128: 加密密钥的大小,以位为单位(这里是 128 位)。

2. 使用 MemoryStream

using (var memoryStream = new MemoryStream())
  • MemoryStream: 内存中的流,用于写入加密后的字节。

3. 创建 CryptoStream

using (var cryptoStream = new CryptoStream(memoryStream, 
    rijndaelManaged.CreateEncryptor(cryptkey, initVector), 
    CryptoStreamMode.Write))
  • CryptoStream: 将数据流链接到加密变换。这里它包裹了 MemoryStream。
  • CreateEncryptor(cryptkey, initVector): 使用提供的密钥和 IV 创建对称加密器对象。
  • CryptoStreamMode.Write: 指定该流将用于写入操作。

4. 写入数据

using (var ws = new StreamWriter(cryptoStream))
{
    ws.Write(textToCrypt);
}
  • StreamWriter: 用于向流中写入字符。它将明文 textToCrypt 写入 CryptoStream,CryptoStream 会自动加密,并将结果写入 MemoryStream。

5. 返回加密结果

return Convert.ToBase64String(memoryStream.ToArray());
  • Convert.ToBase64String: 将存储在 MemoryStream 中的加密字节转换为 Base64 字符串,并作为加密结果返回。

完整的加密方法

public string EncryptAES(string textToCrypt)
{
    private byte[] cryptkey = Encoding.ASCII.GetBytes("1234567891234567");
    private byte[] initVector = Encoding.ASCII.GetBytes("1234567891234567");

    try
    {
        using (var rijndaelManaged =
               new RijndaelManaged { Key = cryptkey, IV = initVector, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7, KeySize = 128 })
        using (var memoryStream = new MemoryStream())
        using (var cryptoStream =
               new CryptoStream(memoryStream,
                   rijndaelManaged.CreateEncryptor(cryptkey, initVector),
                   CryptoStreamMode.Write))
        {
            using (var ws = new StreamWriter(cryptoStream))
            {
                ws.Write(textToCrypt);
            }
            return Convert.ToBase64String(memoryStream.ToArray());
        }
    }
    catch (CryptographicException e)
    {
        Console.WriteLine("发生加密错误: {0}", e.Message);
        return null;
    }
}

运行结果

输出

三. 解密过程

完整的解密方法

public string DecryptAES(string cipherData)
{
    try
    {
        using (var rijndaelManaged =
               new RijndaelManaged { Key = cryptkey, IV = initVector, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7, KeySize = 128 })
        using (var memoryStream =
               new MemoryStream(Convert.FromBase64String(cipherData)))
        using (var cryptoStream =
               new CryptoStream(memoryStream,
                   rijndaelManaged.CreateDecryptor(cryptkey, initVector),
                   CryptoStreamMode.Read))
        {
            return new StreamReader(cryptoStream).ReadToEnd();
        }
    }
    catch (CryptographicException e)
    {
        Console.WriteLine("发生解密错误: {0}", e.Message);
        return null;
    }
}

解密示例输出

通过 DecryptAES 方法可以将加密的 Base64 字符串转换回原始文本。

解密

四. AES 的不同选项

密钥大小

  • 192 位: 可使用 KeySize = 192 以提高安全性。
  • 256 位KeySize = 256 提供最高级别的安全性,但可能会影响性能。
  • 128 位: 默认密钥大小为 128 位。

填充模式

  • PaddingMode.None: 不添加填充。需确保明文长度是块大小的倍数。
  • PaddingMode.Zeros: 使用零填充,但如果明文以零字节结尾,可能在解密时造成歧义。
  • PaddingMode.ANSIX923: 用零填充,并添加一个字节表示填充字节的数量。
  • PaddingMode.ISO10126: 用随机字节填充,并添加一个字节表示填充字节的数量。
  • PaddingMode.PKCS7: 使用填充以使明文成为块大小的倍数。PKCS7 是常见的填充方案,它在明文末尾追加字节,每个字节的值表示添加的填充字节数。

模式

  • CipherMode.ECB: 电子密码本模式(ECB),每个明文块独立加密。这种模式安全性较差,因为相同的明文块会产生相同的密文块。
  • CipherMode.CFB: 密码反馈模式(CFB),将块密码转化为流密码,允许以更小的块加密数据。
  • CipherMode.OFB: 输出反馈模式(OFB),同样将块密码转化为流密码,避免错误传播。
  • CipherMode.CTS: 密文偷取模式(CTS),处理不是块大小倍数的明文数据而不需要填充。
  • CipherMode.CBC: 密码块链接模式(CBC),每个明文块与前一个密文块进行异或后加密,是常见的块密码模式。

五. 结论

在 AES 加密过程中,你可以定义加密密钥、初始化向量(IV)、密码模式、填充模式和密钥大小。这些选项在确定加密过程的安全性和行为方面起着关键作用。根据具体的安全需求,可以定制这些设置,平衡安全强度、性能和兼容性。