【发布时间】:2023-02-11 01:54:52
【问题描述】:
我的代码中有一个加密/解密数据的工作解决方案(如下),但是当我将项目升级到 DOTNET6 时,RijndaelManaged 变得过时了:
警告 SYSLIB0022 'RijndaelManaged' 已过时:'Rijndael 和 RijndaelManaged 类型已过时。请改用 Aes。
和
SYSLIB0023 'RNGCryptoServiceProvider' 已过时: 'RNGCryptoServiceProvider 已过时。要生成随机数,请改用 RandomNumberGenerator 静态方法之一。'
现在我想按照说明将其更改为 Aes/RandomNumberGenerator,但希望保持输出与原样相同。不幸的是,我不熟悉 crypt/decrypt。
有人可以帮助我重写当前块以改为使用 Aes - 或者至少帮助我如何更改它并保持公共方法以相同的方式工作?
我拥有的全部代码(按原样工作)
using System.Security.Cryptography; namespace MyApp; internal static class AES { private static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes) { byte[] encryptedBytes; byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; using (MemoryStream ms = new()) { using RijndaelManaged AES = new(); // This reports Warning SYSLIB0022 'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead. AES.KeySize = 256; AES.BlockSize = 128; var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); AES.Key = key.GetBytes(AES.KeySize / 8); AES.IV = key.GetBytes(AES.BlockSize / 8); AES.Mode = CipherMode.CBC; using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length); cs.Close(); } encryptedBytes = ms.ToArray(); } return encryptedBytes; } private static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes) { byte[] decryptedBytes = null; byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; using (MemoryStream ms = new()) { using RijndaelManaged AES = new(); // This reports Warning SYSLIB0022 'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead. AES.KeySize = 256; AES.BlockSize = 128; var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); AES.Key = key.GetBytes(AES.KeySize / 8); AES.IV = key.GetBytes(AES.BlockSize / 8); AES.Mode = CipherMode.CBC; using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length); cs.Close(); } decryptedBytes = ms.ToArray(); } return decryptedBytes; } public static string EncryptText(string password, string salt = "MySecretSaltWhichIWantToKeepWorking") { byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(password); byte[] passwordBytes = Encoding.UTF8.GetBytes(salt); passwordBytes = SHA256.Create().ComputeHash(passwordBytes); byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes); string result = Convert.ToBase64String(bytesEncrypted); return result; } public static string DecryptText(string hash, string salt = "MySecretSaltWhichIWantToKeepWorking") { try { byte[] bytesToBeDecrypted = Convert.FromBase64String(hash); byte[] passwordBytes = Encoding.UTF8.GetBytes(salt); passwordBytes = SHA256.Create().ComputeHash(passwordBytes); byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes); string result = Encoding.UTF8.GetString(bytesDecrypted); return result; } catch (Exception e) { return e.Message; } } private const int SALT_BYTE_SIZE = 24; private const int HASH_BYTE_SIZE = 24; private const int PBKDF2_ITERATIONS = 1000; private const int ITERATION_INDEX = 0; private const int SALT_INDEX = 1; private const int PBKDF2_INDEX = 2; public static string PBKDF2_CreateHash(string password) { RNGCryptoServiceProvider csprng = new(); // This reports SYSLIB0023 'RNGCryptoServiceProvider' is obsolete: 'RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.' byte[] salt = new byte[SALT_BYTE_SIZE]; csprng.GetBytes(salt); byte[] hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE); return PBKDF2_ITERATIONS + ":" + Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash); } public static bool PBKDF2_ValidatePassword(string password, string correctHash) { char[] delimiter = { ':' }; string[] split = correctHash.Split(delimiter); int iterations = Int32.Parse(split[ITERATION_INDEX]); byte[] salt = Convert.FromBase64String(split[SALT_INDEX]); byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]); byte[] testHash = PBKDF2(password, salt, iterations, hash.Length); return SlowEquals(hash, testHash); } private static bool SlowEquals(byte[] a, byte[] b) { uint diff = (uint)a.Length ^ (uint)b.Length; for (int i = 0; i < a.Length && i < b.Length; i++) diff |= (uint)(a[i] ^ b[i]); return diff == 0; } private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes) { Rfc2898DeriveBytes pbkdf2 = new(password, salt) { IterationCount = iterations }; return pbkdf2.GetBytes(outputBytes); } }
【问题讨论】:
-
AES 是 Rijndael——它们是同一回事。出于某种原因,.NET 有几个类做几乎完全相同的事情。您应该能够将对 RijndaelManaged 的所有引用更改为 AES,而无需任何功能更改
-
我可以确认@canton7 所说的内容。我们最近不得不将我们的代码转换为使用符合 FIPS 的加密,我们所要做的就是从 RijndaelManaged 切换到 Aes
-
代码实现了AES,但是严格来说AES和Rijndael是不一样的。 AES 是 Rijndael 的子集。 Rijndael(这不是标准的 btw)以 32 位步长使用 128 位和 256 位之间的块和密钥大小,而 AES 使用 128 位的固定块大小和 128、192 和 256 位的密钥大小。
-
感谢您提供信息 - 已完成,我可以确认升级很容易。
标签: c# cryptography aes rijndaelmanaged