.NET 加密模型

.NET 提供许多标准加密算法的实现。

对象继承

.NET Framework 系统实现派生类继承的可扩展模式。 层次结构如下所示:

使用此模式派生类,可轻松添加新算法或现有算法的新实现。 例如,要创建新的公共密钥算法,你会继承 AsymmetricAlgorithm 类。 要创建特定算法的新实现,将需要创建该算法的非抽象派生类。

此后,这种继承模型不会用于新类型的基元,例如 AesGcmShake128。 这些算法是 sealed。 如果需要这些类型的扩展性模式或抽象,则抽象的实现由开发人员负责。

一次性 API

从 .NET 5 开始,引入了哈希和 HMAC 的一次性 API。 虽然稍微不那么灵活,但这些一次性 API 具有以下特征:

  • 更易于使用(且不太容易被滥用)
  • 减少分配或无分配
  • 线程安全
  • 使用平台的最佳可用实现

哈希和 HMAC 基元通过 SHA256.HashData 等类型的静态 HashData 方法公开一次性 API。 静态 API 不提供内置扩展性机制。 如果要实现自己的算法,建议还提供该算法的类似静态 API。

RandomNumberGenerator 类还提供静态方法,用于创建或填充包含加密随机数据的缓冲区。 这些方法始终使用系统的加密安全伪随机数生成器 (CSPRNG)。

如何在 .NET 中实现算法

作为可用于一种算法的不同实现的示例,请考虑对称算法。 所有对称算法的基数都是 SymmetricAlgorithm,它由 AesTripleDES 和不再推荐的其他算法继承。

AesAesCryptoServiceProviderAesCngAesManaged 继承。

Windows 上的 .NET Framework:

  • *CryptoServiceProvider 算法类(如 AesCryptoServiceProvider)是 Windows Cryptography API (CAPI) 的包装算法的实现。
  • *Cng 算法类(如 ECDiffieHellmanCng)是 Windows Cryptography Next Generation (CNG) 实现的包装器。
  • *Managed 类(如 AesManaged)完全在托管代码中编写。 *Managed 实现未获得美国联邦信息处理标准 (FIPS) 认证,并且可能比 *CryptoServiceProvider*Cng 包装器类更慢。

在 .NET Core 和 .NET 5 及更高版本中,所有实现类(*CryptoServiceProvider*Managed*Cng)都是操作系统 (OS) 算法的包装器。 如果 OS 算法通过 FIPS 认证,则 .NET 使用 FIPS 认证的算法。 有关详细信息,请参阅跨平台加密

在大多数情况下,无需直接引用算法实现类,例如 AesCryptoServiceProvider。 通常需要的方法和属性位于基算法类上,例如 Aes。 在基算法类上使用工厂方法创建默认实现类的实例,并引用基算法类。 例如,请参阅以下示例中突出显示的代码行:

using System.Security.Cryptography;

try
{
    using (FileStream fileStream = new("TestData.txt", FileMode.OpenOrCreate))
    {
        using (Aes aes = Aes.Create())
        {
            byte[] key =
            {
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
            };
            aes.Key = key;

            byte[] iv = aes.IV;
            fileStream.Write(iv, 0, iv.Length);

            using (CryptoStream cryptoStream = new(
                fileStream,
                aes.CreateEncryptor(),
                CryptoStreamMode.Write))
            {
                // By default, the StreamWriter uses UTF-8 encoding.
                // To change the text encoding, pass the desired encoding as the second parameter.
                // For example, new StreamWriter(cryptoStream, Encoding.Unicode).
                using (StreamWriter encryptWriter = new(cryptoStream))
                {
                    encryptWriter.WriteLine("Hello World!");
                }
            }
        }
    }

    Console.WriteLine("The file was encrypted.");
}
catch (Exception ex)
{
    Console.WriteLine($"The encryption failed. {ex}");
}
Imports System
Imports System.IO
Imports System.Security.Cryptography

Module Module1
    Sub Main()
        Try
            ' Create a file stream
            Using fileStream As New FileStream("TestData.txt", FileMode.OpenOrCreate)

                ' Create a new instance of the default Aes implementation class  
                ' and configure encryption key.
                Using aes As Aes = Aes.Create()
                    'Encryption key used to encrypt the stream.
                    'The same value must be used to encrypt and decrypt the stream.
                    Dim key As Byte() = {
                        &H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8,
                        &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16
                    }

                    aes.Key = key

                    ' Stores IV at the beginning of the file.
                    ' This information will be used for decryption.
                    Dim iv As Byte() = aes.IV
                    fileStream.Write(iv, 0, iv.Length)

                    ' Create a CryptoStream, pass it the FileStream, and encrypt
                    ' it with the Aes class.
                    Using cryptoStream As New CryptoStream(fileStream, aes.CreateEncryptor(), CryptoStreamMode.Write)

                        ' By default, the StreamWriter uses UTF-8 encoding.
                        ' To change the text encoding, pass the desired encoding as the second parameter.
                        ' For example, New StreamWriter(cryptoStream, Encoding.Unicode).
                        Using sWriter As New StreamWriter(cryptoStream)

                            'Write to the stream.
                            sWriter.WriteLine("Hello World!")
                        End Using
                    End Using
                End Using
            End Using

            'Inform the user that the message was written  
            'to the stream.  
            Console.WriteLine("The text was encrypted.")
        Catch
            'Inform the user that an exception was raised.  
            Console.WriteLine("The encryption failed.")
            Throw
        End Try
    End Sub
End Module

选择一种算法

可以出于各种原因选择一种算法:例如,为了保护数据完整性,为了保护数据隐私或为了生成密钥。 为了保护完整性(防止更改)或保护隐私(防止查看),对称算法和哈希算法用于保护数据。 哈希算法主要用于保护数据完整性。

下面是按应用程序分类的建议算法列表:

另请参阅