如何在.Net Core类库中使用Rijndael加密? (不是.Net Framework)

我们如何在.Net Core类库中使用Rijndael加密? (不是.Net Framework类库)我们需要创建一个共享的.Net Core库,用于多个项目,并且需要实现在项目中使用相同Rijndael加密的Encrypt和Decrypt方法。

我们目前正在使用:

  • VS企业版2015
  • C#
  • .Net核心类库
  • .NETStandard,Version = v1.6 reference

似乎.Net Core 1.0版本中缺少Rijndael和AES的实现…它似乎只包括基类。 我们如何获得Rijndael或AES加密的.Net Core实现作为新的.Net核心类库项目的参考?

以下是在.Net Framework 4.5.2中使用的Encrypt方法:

public static string Encrypt(string valueToEncrypt, string symmetricKey, string initializationVector) { string returnValue = valueToEncrypt; var aes = new System.Security.Cryptography.RijndaelManaged(); try { aes.Key = ASCIIEncoding.ASCII.GetBytes(symmetricKey); aes.IV = ASCIIEncoding.ASCII.GetBytes(initializationVector); aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.ISO10126; var desEncrypter = aes.CreateEncryptor(); var buffer = ASCIIEncoding.ASCII.GetBytes(valueToEncrypt); returnValue = Convert.ToBase64String(desEncrypter.TransformFinalBlock(buffer, 0, buffer.Length)); } catch (Exception) { returnValue = string.Empty; } return returnValue; } 

Rijndael和AES之间的差异(在.NET中)是Rijndael允许块大小改变,但AES不允许。 由于RijndaelManaged的默认块大小与AES块大小(128位/ 16字节)相同,实际上您使用的是AES。

不要按名称实例化实现类型,只需使用工厂( Aes.Create() )。 这适用于.NET Core和.NET Framework。

其他值得一提的事情:

  • 所有SymmetricAlgorithm实例都是IDisposable,您应该在using语句中使用它们。
  • 所有ICryptoTransform实例(例如您错误命名的desEncryptor )都是IDisposable,您应该在using语句中使用它们。
  • .NET Core 1.0中不提供ISO10126填充。 如果需要与现有流兼容,可以自己应用填充并指定PaddingMode.None。 否则,PKCS7更标准。
  • 您的AES密钥不是非常随机,因为它来自ASCII字符串(许多值无效)。
    • Base64至少具有完整的值范围
    • PBKDF2(基于密码的密钥派生函数2)通过Rfc2898DeriveBytes类允许共享字符串秘密,可预测的噪声输出。
    • KeyAgreement通常更好,但是.NET Core 1.0中既没有ECDH也没有经典DH。
  • 通常,加密器应该计算随机IV aes.GenerateIV()如果对多个操作使用相同的对象,则调用aes.GenerateIV() )并将其与密文一起呈现。 因此,加密需要密钥和明文,并产生密文和IV。 Decrypt采用(密钥,IV,密文)并生成明文。

如果你只是想加密/解密东西,请避免直接使用Rijndael,因为asp.net核心有一些更好的包装器,它们更容易使用,并且默认情况下更可能是正确安全的。 它被称为DataProtection。

 using Microsoft.AspNetCore.DataProtection; // During startup add DP serviceCollection.AddDataProtection(); ... // the 'provider' parameter is provided by DI public MyClass(IDataProtectionProvider provider) { _protector = provider.CreateProtector("Contoso.MyClass.v1"); } ... // protect the payload string protectedPayload = _protector.Protect(input); Console.WriteLine($"Protect returned: {protectedPayload}"); ... // unprotect the payload string unprotectedPayload = _protector.Unprotect(protectedPayload); Console.WriteLine($"Unprotect returned: {unprotectedPayload}"); 

有关更多信息,请参阅数据保护文档