2016-08-05 61 views
13

我想使用密鑰加密.NET核心中的字符串。我有一個客戶端/服務器方案,並希望加密客戶端上的字符串,將其發送到服務器並對其進行解密。由於.NET Core仍處於早期階段(例如Rijndael尚未推出),我有什麼選擇?使用.NET核心加密字符串

+2

根據評論[這裏](http://stackoverflow.com/questions/38333722/how-to-use-rijndael-encryption-with-a-net-core-class -library-not-net-framewo),它正在版本1.1中實現。直到那時,你可以使用AES [如圖所示](http://stackoverflow.com/questions/35912849/rijndael-in-class-library-package-not-avaiable-for-dotnet5-4) – keyboardP

回答

16

你真的不應該在.NET中使用Rijndael/RijndaelManaged。如果您使用的BlockSize值爲128(這是默認值),那麼您使用AES,因爲我的explained in a similar question

在.NET核心可用的對稱加密選項是:

  • 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上受支持。

+0

我正在工作與.Net核心與System.Security.Cryptograph,它看起來Aes「創建()」功能缺失。我在我的project.json中包含了「System.Security.Cryptography.Algorithms」:「4.3.0」,我是否缺少參考?這是下面的編譯錯誤。 錯誤CS0426 \t'Aes'類型中不存在類型名稱'Create' – phanf

+0

@phanf https://apisof.net/catalog/System.Security.Cryptography.Aes.Create()表示它存在於所有.NET Core的版本。你可能使用了不同類型的相同名稱? – bartonjs

+0

也不能在這個包中的各個類上找到create()方法。最新的macnetosx dotnet核心。 – kevinc

9

下面是一個簡單的示例認證:

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; 
} 
+0

如果你的byte []足夠小,你也可以避免使用流,並使用encryptor.TransformFinalBlock(buffer,0,buffer.Length) –

+0

@JimW沒錯。我很好奇,你爲什麼要這樣? –

+0

代碼少,創建對象少,不喜歡什麼? –

3

已經有一個答案,這一點,但我認爲我們可以提供一個簡單的解決方案。

如果您只是想要保護保護您的數據,那麼在.NET Core中有一個實現可以讓您免於加密的煩惱; DataProtectionProvider

Startup.cs

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

如果你想,就可以指定算法(使用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); 
    } 
} 
+0

這是否也可以在'.NET MVC'中使用? – NoReceipt4Panda

+3

值得注意的是這裏的密鑰存儲在機器上(默認情況下),所以它只能被加密的機器解密。如果您需要能夠在應用程序或不同服務的多個實例上進行解密(如單點登錄),請使用分佈式DataProtection(如「Microsoft.AspNetCore.DataProtection.Redis」)來共享密鑰。 – hofnarwillie

+1

''我的非常長尺寸不準確的尺寸「'不是一個excrpytion鍵,只是保護器的唯一名稱。實際的密鑰在默認情況下以文件形式存儲在磁盤上(因此請注意,如果在Web場中) – alastairtree

1

數據pr ASP.NET Core應用程序默認啓用保護系統。除非要重新配置默認密鑰存儲位置或密鑰的生存時間,否則您甚至不需要在StartUp方法中執行任何操作。在這種情況下,你會做你的ConfigureServices方法如下:

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

因爲數據保護系統,在應用程序的服務集合在默認情況下,它可以製成通過依賴注入提供。這裏是你如何能注入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); 
} 

我希望這可以幫助:)