2016-08-05 30 views
13

Chciałbym zaszyfrować ciąg w .NET Core za pomocą klucza. Mam scenariusz klient/serwer i chciałbym zaszyfrować ciąg na kliencie, wysłać go do serwera i odszyfrować.Szyfruj ciąg w .NET Core

Ponieważ .NET Core jest wciąż we wczesnym stadium (np. Rijndael nie jest jeszcze dostępny), jakie są moje opcje?

+2

Zgodnie z komentarzem [tutaj] (http://stackoverflow.com/questions/38333722/how-to-use-rijndael-encryption-with-a-net-core-class -library-nie-net-framewo), planowane jest wdrożenie w wersji 1.1. Do tego czasu możesz użyć AES, jak pokazano [tutaj] (http://stackoverflow.com/questions/35912849/rijndael-in-class-library-package-not-avaiable-for-dotnet5-4) – keyboardP

Odpowiedz

16

Naprawdę nie powinieneś nigdy używać Rijndael/RijndaelManaged w .NET. Jeśli używasz go z wartością BlockSize równą 128 (co jest domyślną wartością), to używasz AES, tak jak I explained in a similar question.

Symetryczne opcje szyfrowania dostępne w .NET Core są:

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

I do szyfrowania asymetrycznego

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

Szczególnie na .NET Core fabryki są najlepszym sposobem, aby przejść, ponieważ zwrócą obiekt działający na aktualnie uruchomionym systemie operacyjnym. Na przykład RSACng jest typem publicznym, ale działa tylko w systemie Windows; i RSAOpenSsl jest typem publicznym, ale jest obsługiwany tylko w systemach Linux i macOS.

+0

Pracuję z .NET Core z System.Security.Cryptograph i wygląda na to, że brakuje funkcji "Create()" Aes. Do mojego project.json zawarłem "System.Security.Cryptography.Algorithms": "4.3.0", czy brakuje mi referencji? To jest błąd kompilacji poniżej. Błąd CS0426 Nazwa typu "Utwórz" nie istnieje w typie "Aes" – phanf

+0

@phanf https://apisof.net/catalog/System.Security.Cryptography.Aes.Create() mówi, że był tam we wszystkich wersje .NET Core. Czy może używasz innego typu tej samej nazwy? – bartonjs

+0

Również nie można znaleźć metod create() na różnych klasach w tym pakiecie. Najnowszy rdzeń dotnet w macososie. – kevinc

9

Tutaj jest trywialny przykład bez uwierzytelniania:

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(); 
    } 
} 

Do generowania kluczy:

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

Możesz także uniknąć użycia strumieni, jeśli twój bajt [] jest wystarczająco mały i użyj encryptor.TransformFinalBlock (buffer, 0, buffer.Length) –

+0

@ JimW To prawda. Jestem ciekaw, dlaczego powinieneś? –

+0

Mniej kodu, mniej obiektów do stworzenia, czego nie lubić? –

3

Jest już odpowiedź na to pytanie, ale myślę, że możemy zapewnić prostsze rozwiązanie.

Jeśli chcesz po prostu chronić swoje dane, istnieje danych, który uwalnia od problemów związanych z szyfrowaniem; DataProtectionProvider.

W Startup.cs:

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

Jeśli chcesz, to jest możliwe określenie algorytmów (używając Microsoft.AspNetCore.DataProtection) używanych do szyfrowania i sprawdzania, jak to:

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

Następnie szyfrowania/deszyfrowania przy użyciu usługa jako taka:

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

Czy można go również używać w '.NET MVC'? – NoReceipt4Panda

+3

Warto zauważyć, że klucze tutaj są przechowywane na komputerze (domyślnie), więc może być odszyfrowane tylko przez komputer, który je zaszyfrował. Użyj rozproszonego DataProtection, takiego jak 'Microsoft.AspNetCore.DataProtection.Redis', aby współużytkować klucze, jeśli chcesz odszyfrować je w wielu instancjach aplikacji lub różnych usługach (np. W trybie logowania pojedynczego). – hofnarwillie

+1

'' mój-bardzo-długi-klucz-bez-dokładnego-rozmiaru "' nie jest kluczem ekskrementacyjnym, tylko unikalną nazwą dla opiekuna. Rzeczywiste klucze są domyślnie przechowywane jako pliki na dysku (więc uważaj, jeśli na farmie internetowej) – alastairtree

1

Dane pr System otection jest domyślnie włączony w aplikacjach ASP.NET Core. Nie musisz nic robić w swojej metodzie StartUp, chyba że chcesz zmienić domyślną lokalizację pamięci klucza lub czas życia kluczy.W takim przypadku chcesz wykonać następujące czynności w sposób ConfigureServices:

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

Ponieważ system ochrony danych w aplikacji usług kolekcji domyślnie, może być udostępniona poprzez wstrzyknięcie zależności. Oto w jaki sposób można wstrzyknąć IDataProtectionProvider do kontrolera, a następnie użyć go, aby utworzyć instancję IDataProtector w konstruktorze kontrolera:

public class HomeController : Controller 
{ 
    IDataProtector _protector; 

    public HomeController(IDataProtectionProvider provider) 
    { 
     _protector = provider.CreateProtector(GetType().FullName); 
    } 
} 

Można połączyć osłonę do szyfrowania zawartości tak:

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

Mam nadzieję, że to pomoże :)