加密.NET Core中的字符串

我想使用密钥加密.NET Core中的字符串。 我有一个客户端/服务器场景,并希望加密客户端上的字符串,将其发送到服务器并解密。

由于.NET Core仍处于早期阶段(例如Rijndael尚未推出),我有哪些选择?

你真的不应该在.NET中使用Rijndael / RijndaelManaged。 如果您使用的BlockSize值为128(这是默认值),那么您正在使用AES,正如我在类似问题中所解释的那样 。

.NET Core中提供的对称加密选项包括:

  • AES(System.Security.Cryptography.Aes.Create())
  • 3DES(System.Security.Cryptography.TripleDES.Create())

对于非对称加密

  • RSA(System.Security.Cryptography.RSA.Create())

特别是在.NET Core上,工厂是最好的方法,因为它们会返回一个对象,该对象可以在当前正在执行的操作系统上运行。 例如,RSACng是一种公共类型,但仅适用于Windows; 和RSAOpenSsl是一种公共类型,但仅在Linux和macOS上受支持。

这是一个没有身份validation的简单示例:

var text = "Hello World"; var buffer = Encoding.UTF8.GetBytes(text); var iv = GetRandomData(128); var keyAes = GetRandomData(256); byte[] result; using (var aes = Aes.Create()) { aes.Key = keyAes; aes.IV = iv; using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV)) using (var resultStream = new MemoryStream()) { using (var aesStream = new CryptoStream(resultStream, encryptor, CryptoStreamMode.Write)) using (var plainStream = new MemoryStream(buffer)) { plainStream.CopyTo(aesStream); } result = resultStream.ToArray(); } } 

用于密钥生成:

 private static byte[] GetRandomData(int bits) { var result = new byte[bits / 8]; RandomNumberGenerator.Create().GetBytes(result); return result; } 

已经有了答案,但我认为我们可以提供更简单的解决方案。

如果您只是想保护您的数据,那么在.NET Core中就可以实现这一function,从而使您免于加密的麻烦; DataProtectionProvider

Startup.cs

 public void ConfigureServices(IServiceCollection services) { services.AddDataProtection(); //Add this [..] services.AddMvc(); } 

如果您愿意,可以指定用于加密和validation的算法(使用Microsoft.AspNetCore.DataProtection ),如下所示:

 services.AddDataProtection() .UseCryptographicAlgorithms(new AuthenticatedEncryptionSettings() { EncryptionAlgorithm = EncryptionAlgorithm.AES_256_GCM, ValidationAlgorithm = ValidationAlgorithm.HMACSHA256 }); 

然后使用服务加密/解密:

 public class CipherService : ICipherService { private readonly IDataProtectionProvider _dataProtectionProvider; private const string Key = "my-very-long-key-of-no-exact-size"; public CipherService(IDataProtectionProvider dataProtectionProvider) { _dataProtectionProvider = dataProtectionProvider; } public string Encrypt(string input) { var protector = _dataProtectionProvider.CreateProtector(Key); return protector.Protect(input); } public string Decrypt(string cipherText) { var protector = _dataProtectionProvider.CreateProtector(Key); return protector.Unprotect(cipherText); } } 

ASP.NET Core应用程序默认启用数据保护系统。 除非要重新配置默认密钥存储位置或密钥的生存时间,否则甚至不需要在StartUp方法中执行任何操作。 在这种情况下,您将在ConfigureServices方法中执行以下操作:

 services.ConfigureDataProtection(dp => { dp.PersistKeysToFileSystem(new DirectoryInfo(@"c:\keys")); dp.SetDefaultKeyLifetime(TimeSpan.FromDays(14)); }); 

由于数据保护系统默认位于应用程序的服务集合中,因此可以通过dependency injection使其可用。 以下是如何将IDataProtectionProvider注入控制器,然后使用它在控制器的构造函数中创建IDataProtector的实例:

 public class HomeController : Controller { IDataProtector _protector; public HomeController(IDataProtectionProvider provider) { _protector = provider.CreateProtector(GetType().FullName); } } 

然后,您可以调用保护程序来加密内容,如下所示:

 public IActionResult Index() { var model = _service.GetAll().Select(c => new ContractViewModel { Id = _protector.Protect(c.Id.ToString()), Name = c.Name }).ToList(); return View(model); } 

我希望这有帮助 :)

我有一个不同的方法,我想用密钥加密一个字符串,并获得一个加扰字符串,我可以再次使用相同的密钥解密。 请参阅以下扩展方法:

  public static string Encrypt(this string text, string key) { if (string.IsNullOrEmpty(key)) throw new ArgumentException("Key must have valid value.", nameof(key)); if (string.IsNullOrEmpty(text)) throw new ArgumentException("The text must have valid value.", nameof(text)); var buffer = Encoding.UTF8.GetBytes(text); var hash = new SHA512CryptoServiceProvider(); var aesKey = new byte[24]; Buffer.BlockCopy(hash.ComputeHash(Encoding.UTF8.GetBytes(key)), 0, aesKey, 0, 24); using (var aes = Aes.Create()) { if (aes == null) throw new ArgumentException("Parameter must not be null.", nameof(aes)); aes.Key = aesKey; using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV)) using (var resultStream = new MemoryStream()) { using (var aesStream = new CryptoStream(resultStream, encryptor, CryptoStreamMode.Write)) using (var plainStream = new MemoryStream(buffer)) { plainStream.CopyTo(aesStream); } var result = resultStream.ToArray(); var combined = new byte[aes.IV.Length + result.Length]; Array.ConstrainedCopy(aes.IV, 0, combined, 0, aes.IV.Length); Array.ConstrainedCopy(result, 0, combined, aes.IV.Length, result.Length); return Convert.ToBase64String(combined); } } } public static string Decrypt(this string encryptedText, string key) { if (string.IsNullOrEmpty(key)) throw new ArgumentException("Key must have valid value.", nameof(key)); if (string.IsNullOrEmpty(encryptedText)) throw new ArgumentException("The encrypted text must have valid value.", nameof(encryptedText)); var combined = Convert.FromBase64String(encryptedText); var buffer = new byte[combined.Length]; var hash = new SHA512CryptoServiceProvider(); var aesKey = new byte[24]; Buffer.BlockCopy(hash.ComputeHash(Encoding.UTF8.GetBytes(key)), 0, aesKey, 0, 24); using (var aes = Aes.Create()) { if (aes == null) throw new ArgumentException("Parameter must not be null.", nameof(aes)); aes.Key = aesKey; var iv = new byte[aes.IV.Length]; var ciphertext = new byte[buffer.Length - iv.Length]; Array.ConstrainedCopy(combined, 0, iv, 0, iv.Length); Array.ConstrainedCopy(combined, iv.Length, ciphertext, 0, ciphertext.Length); aes.IV = iv; using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV)) using (var resultStream = new MemoryStream()) { using (var aesStream = new CryptoStream(resultStream, decryptor, CryptoStreamMode.Write)) using (var plainStream = new MemoryStream(ciphertext)) { plainStream.CopyTo(aesStream); } return Encoding.UTF8.GetString(resultStream.ToArray()); } } }