VB.NET实现AesCng类加解密的方法及代码 VSTO2019
CNG (下一代加密技术)
CNG,CNG 提供了大量的以开发人员为目标对象的功能,其中包括更方便的算法发现和替换、可替换的随机数生成器和一个内核模式加密 API。CNG(Cryptography Next Generation),即下一代加密技术,是 CryptoAPI 的替代物。
CNG的基本介绍
在 Windows Vista 和 Windows Server 2008 中引入了新的加密 API 以替代旧的 CryptoAPI,旧的 CryptoAPI 植根于早期版本的 Windows NT 和 Windows 95。下一代加密技术(CNG) 旨在长期替代 CryptoAPI。
Windows Vista 和 Windows Server 2008中对加密服务核心的改进体现在两方面。首先,通过引进下一代加密技术 (CNG),Windows 现在提供一种可插入的、协议不可知的加密功能,此功能使得以编程方式开发和访问独立算法更加轻松。其次,CNG 还新增了对 Suite B 算法的支持,该算法在 2005 年由 National Security Agency (NSA) 引入。
功能
CNG 提供了大量的以开发人员为目标对象的功能,其中包括更方便的算法发现和替换、可替换的随机数生成器和一个内核模式加密 API。提供这些新功能的同时,CNG 还与其处理器 CryptoAPI 1.0 中提供的算法集完全向后兼容。目前,CNG 正在接受通过联邦信息处理标准 (FIPS) 140-2 级别 2 认证以及成为所选平台的通用准则所需的评估。
算法
CNG Suite B 支持包括所需的所有算法:AES(所有密钥大小)、SHA-2 系列(SHA-256、SHA-384 和 SHA-512)哈希算法、椭圆曲线 Diffie-Hellman (ECDH) 以及以美国国家标准与技术研究院 (NIST) 标准原始曲线 P-256、P-384 和 P-521 为标准的椭圆曲线数字签名算法 (ECDSA)。NSA 已表明,经过认证的 Suite B 实现将用于保护以下类别的信息:Top Secret、Secret 以及过去被描述为 Sensitive-But-Unclassified 的隐私信息。所有 Suite B 算法的开发都采取公开形式,其他一些政府也在探索尝试采用 Suite B 算法作为国家标准。
对 Windows PKI 平台的这些低级别改进为开发人员保护数据提供了更安全的方法,同时还创建了易于维护和随时间改进的子系统。由于 CNG 是可插入的体系结构,所以可根据需要添加新算法,CNG 会从应用程序层抽象出这些提供程序。最终结果是,Windows Vista 和 Windows Server 2008 的设计旨在为开发支持 PKI 的应用程序和服务提供高级的可发展平台。
CNG提供一种高灵活性的加密开发平台,使得IT专业人员能在活动目录的证书服务(AD CS)、安全套接层(SSL)和IPSec等相关加密应用中创建、更新并使用定制加密算法。CNG采用美国政府的Suite B算法,其中包括加密、数字签名、密钥交换和哈希等算法。
CNG提供一套API,可用来执行诸如创建、存储和检索加密密钥等基本的加密操作。它还能安装和使用更多加密供应商的算法。CNG使企业和开发人员既能使自己的加密算法,又能采用标准的加密算法。
CNG支持当前的CryptoAPI 1.0 系列算法,还支持椭圆曲线加密(ECC)算法。美国政府的Suite B标准算法采用许可ECC算法。
AesCng (Aes下一代加密技术)
这里直接将可使用的代码附后,以便研究探讨。
AesCng 加密模块
Public Function Encrypt_String_By_AesCng_Engine02(ByVal PlainText As String,
ByVal Password As String,
ByVal Optional Salt As String = "Kosher",
ByVal Optional HashAlgorithm As String = "SHA1",
ByVal Optional PasswordIterations As Integer = 2,
ByVal Optional InitialVector As String = "OFRna73m*aze01xY",
ByVal Optional KeySize As Integer = 256) As String
If String.IsNullOrEmpty(PlainText) Then Return ""
Dim InitialVectorBytes As Byte() = Encoding.ASCII.GetBytes(InitialVector)
Dim SaltValueBytes As Byte() = Encoding.ASCII.GetBytes(Salt)
Dim PlainTextBytes As Byte() = Encoding.UTF8.GetBytes(PlainText)
Dim DerivedPassword As PasswordDeriveBytes = New PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations)
'Dim KeyBytes As Byte() = DerivedPassword.GetBytes(KeySize / 8)
Dim KeyBytes As Byte() = (New SHA256Managed).ComputeHash(Encoding.Unicode.GetBytes(Password))
'测试ok。Dim SymmetricKey As RijndaelManaged = New RijndaelManaged()
'Dim SymmetricKey As AesManaged = New AesManaged()
Dim SymmetricKey As New AesCng
SymmetricKey.Mode = CipherMode.CBC
Dim CipherTextBytes As Byte() = Nothing
Using Encryptor As ICryptoTransform = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes)
Using MemStream As MemoryStream = New MemoryStream()
Using CryptoStream As CryptoStream = New CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)
CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length)
CryptoStream.FlushFinalBlock()
CipherTextBytes = MemStream.ToArray()
MemStream.Close()
CryptoStream.Close()
End Using
End Using
End Using
SymmetricKey.Clear()
Return Convert.ToBase64String(CipherTextBytes)
End Function
AesCng 解密模块
Public Function Decrypt_String_By_AesCng_Engine02(ByVal CipherText As String,
ByVal Password As String,
ByVal Optional Salt As String = "Kosher",
ByVal Optional HashAlgorithm As String = "SHA1",
ByVal Optional PasswordIterations As Integer = 2,
ByVal Optional InitialVector As String = "OFRna73m*aze01xY",
ByVal Optional KeySize As Integer = 256) As String
If String.IsNullOrEmpty(CipherText) Then Return ""
Dim InitialVectorBytes As Byte() = Encoding.ASCII.GetBytes(InitialVector)
Dim SaltValueBytes As Byte() = Encoding.ASCII.GetBytes(Salt)
Dim CipherTextBytes As Byte() = Convert.FromBase64String(CipherText)
Dim DerivedPassword As PasswordDeriveBytes = New PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations)
'Dim KeyBytes As Byte() = DerivedPassword.GetBytes(KeySize / 8)
Dim KeyBytes As Byte() = (New SHA256Managed).ComputeHash(Encoding.Unicode.GetBytes(Password))
'/// 测试ok 。Dim SymmetricKey As RijndaelManaged = New RijndaelManaged()
'/// 测试ok 。Dim SymmetricKey As AesManaged = New AesManaged()
Dim SymmetricKey As New AesCng
SymmetricKey.Mode = CipherMode.CBC
Dim PlainTextBytes As Byte() = New Byte(CipherTextBytes.Length - 1) {}
Dim ByteCount As Integer = 0
Using Decryptor As ICryptoTransform = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes)
Using MemStream As MemoryStream = New MemoryStream(CipherTextBytes)
Using CryptoStream As CryptoStream = New CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read)
ByteCount = CryptoStream.Read(PlainTextBytes, 0, PlainTextBytes.Length)
MemStream.Close()
CryptoStream.Close()
End Using
End Using
End Using
SymmetricKey.Clear()
Return Encoding.UTF8.GetString(PlainTextBytes, 0, ByteCount)
End Function
多发点
dim ClipherText as string = Encrypt_String_By_AesCng_Engine02(teststring, "abcd01245368") 'Encrpting_String_By_AesCng(teststring, "abcd01245368")
dim PlainText as string = Decrypt_String_By_AesCng_Engine02(Me.Range("d40").Value, "abcd01245368")
密码说明
严格地说,AES和Rijndael加密法并不完全一样(虽然在实际应用中二者可以互换),因为Rijndael加密法可以支持更大范围的区块和密钥长度:AES的区块长度固定为128位,密钥长度则可以是128,192或256位;而Rijndael使用的密钥和区块长度可以是32位的整数倍,以128位为下限,256位为上限。加密过程中使用的密钥是由Rijndael密钥生成方案产生。
大多数AES计算是在一个特别的有限域完成的。
AES加密过程是在一个4×4的字节矩阵上运作,这个矩阵又称为“体(state)”,其初值就是一个明文区块(矩阵中一个元素大小就是明文区块中的一个Byte)。(Rijndael加密法因支持更大的区块,其矩阵行数可视情况增加)加密时,各轮AES加密循环(除最后一轮外)均包含4个步骤: