.NET 提供许多标准加密算法的实现。
对象继承
.NET 加密系统实现派生类继承的可扩展模式。 层次结构如下所示:
算法类型类,例如 SymmetricAlgorithm, AsymmetricAlgorithm或 HashAlgorithm。 此级别是抽象的。
从算法类型类继承的算法类,例如Aes、RSA或ECDiffieHellman。 此级别是抽象的。
从算法类继承的算法类实现,例如 AesManaged、RC2CryptoServiceProvider 或 ECDiffieHellmanCng。 此级别已完全实现。
通过此派生类模式,可以添加新算法或现有算法的新实现。 例如,若要创建新的公钥算法,需要从 AsymmetricAlgorithm 类继承。 若要创建特定算法的新实现,需要创建该算法的非抽象派生类。
今后,这种继承模型不用于新类型的基元,例如 AesGcm 或 Shake128。 这些算法是 sealed
。 如果需要这些类型的扩展性模式或抽象,则抽象的实现由开发人员负责。
一次性 API
从 .NET 5 开始,为哈希和 HMAC 引入了更简单的 API。 虽然稍微不那么灵活,但这些一次性 API 具有以下特征:
- 更易于使用(不太容易滥用)
- 减少分配或无分配
- 线程安全
- 使用适用于平台的最佳可用实现
哈希和 HMAC 基元通过 HashData
等类型的静态 SHA256.HashData 方法公开一次性 API。 静态 API 不提供内置扩展性机制。 如果要实现自己的算法,建议也提供该算法的类似静态 API。
该 RandomNumberGenerator 类还提供静态方法,用于使用加密随机数据创建或填充缓冲区。 这些方法始终使用系统的加密安全伪随机数生成器(CSPRNG)。
如何在 .NET 中实现算法
作为可用于算法的不同实现的示例,请考虑对称算法。 所有对称算法的基础是SymmetricAlgorithm,它被Aes、TripleDES以及其他不再推荐使用的算法所继承。
Aes 被AesCryptoServiceProvider、AesCng和AesManaged继承。
在 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
选择一种算法
可以出于不同原因选择算法:例如,出于数据完整性、数据隐私或生成密钥。 对称和哈希算法旨在出于完整性原因(防止更改)或隐私原因(防止查看)来保护数据。 哈希算法主要用于数据完整性。
下面是按应用程序推荐的算法列表:
- 数据隐私:
- 数据完整性:
- 数字签名:
- 密钥交换:
- 随机数生成:
- 从密码生成密钥: