.NET 加密模型

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

对象继承

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

通过此派生类模式,可以添加新算法或现有算法的新实现。 例如,若要创建新的公钥算法,需要从 AsymmetricAlgorithm 类继承。 若要创建特定算法的新实现,需要创建该算法的非抽象派生类。

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

一次性 API

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

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

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

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

如何在 .NET 中实现算法

作为可用于算法的不同实现的示例,请考虑对称算法。 所有对称算法的基础是SymmetricAlgorithm,它被AesTripleDES以及其他不再推荐使用的算法所继承。

AesAesCryptoServiceProviderAesCngAesManaged继承。

在 Windows 上的 .NET Framework 中:

  • *CryptoServiceProvider 算法类(例如 AesCryptoServiceProvider)是算法的 Windows 加密 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

选择一种算法

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

下面是按应用程序推荐的算法列表:

另请参阅