Come usare la crittografia Rijndael con una libreria di classi .Net Core? (Not .Net Framework)

Come utilizziamo la crittografia Rijndael in una libreria di classi .Net Core? (Non una libreria di classi .Net Framework) Abbiamo bisogno di creare una libreria Core .Net condivisa da utilizzare in più progetti e abbiamo bisogno di implementare metodi Encrypt e Decrypt che utilizzano la stessa crittografia Rijndael attraverso i progetti.

Attualmente stiamo usando:

  • VS Enterprise 2015
  • c #
  • .Net Core Class Library
  • .NETStandard, versione = riferimento v1.6

Sembra che l’implementazione di Rijndael e AES non sia presente nella versione .Net Core 1.0 … sembra che includa solo le classi di base. Come si ottiene un’implementazione .Net Core di Rijndael o crittografia AES aggiunta come riferimento a un nuovo progetto .Net Core Class Library?

Ecco il metodo Encrypt che funziona in .Net Framework 4.5.2:

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

La differenza (in .NET) tra Rijndael e AES è che Rijndael consente alle dimensioni del blocco di cambiare, ma AES no. Poiché la dimensione del blocco predefinito di RijndaelManaged è la stessa della dimensione del blocco AES (128 bit / 16 byte), in realtà, si utilizza AES.

Invece di istanziare il tipo di implementazione per nome, basta usare la factory ( Aes.Create() ). Funziona sia in .NET Core che in .NET Framework.

Altre cose degne di nota:

  • Tutte le istanze di SymmetricAlgorithm sono IDisposable, dovresti usarle in un’istruzione using .
  • Tutte le istanze di ICryptoTransform (come ad esempio il tuo nome errato desEncryptor ) sono IDisposable, dovresti usarle in una dichiarazione using .
  • La spaziatura ISO10126 non è disponibile in .NET Core 1.0. Se è necessario essere compatibili con gli stream esistenti, è ansible applicare il padding autonomamente e specificare PaddingMode.None. Altrimenti, PKCS7 è più standard.
  • La tua chiave AES non è molto casuale, poiché proviene da una stringa ASCII (molti valori non saranno validi).
    • Base64 ha almeno un intervallo di valori completo
    • PBKDF2 (funzione di derivazione chiave basata su password 2) tramite la class Rfc2898DeriveBytes consente di eseguire il provisioning di un segreto condiviso con stringhe, prevedibile.
    • Il KeyAgreement è in generale migliore, ma né ECDH né il classico DH sono disponibili in .NET Core 1.0.
  • Di solito il crittografo dovrebbe consentire di calcolare un IV casuale (chiamare aes.GenerateIV() se si utilizza lo stesso object per più operazioni) e presentarlo con il testo cifrato. Quindi cripta prende una chiave e un testo in chiaro e produce un testo cifrato e IV. Decifratura prende (chiave, IV, testo cifrato) e produce testo in chiaro.

Se si desidera solo crittografare / decrittografare roba, evitare di utilizzare Rijndael direttamente poiché il nucleo di asp.net ha alcuni wrapper molto più piacevoli che sono molto più facili da usare e con maggiori probabilità di essere adeguatamente protetti per impostazione predefinita. È noto come 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}"); 

Vedere i documenti di protezione dei dati per ulteriori informazioni