
Encrypt e Decrypt stringa in C#
Un utility in C# per codificare (encrypt) e decodificare (decrypt) una stringa:
da usare come
C#: Classe Helper
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Sgart.Base
{
public static class EncryptHelper
{
// per sicurezza cambiate la COMMON_KEY con un valore diverso
// deve essere di 16 caratteri
private const string COMMON_KEY = "DA82179464E44E67B8006317BB5C3838";
/// <summary>
/// prende una stringa e la cripta restituendo un cipherText
/// </summary>
/// <param name="text">testo in chiaro da cifrare</param>
/// <param name="keyString">se null usa quella comune definita nella classe</param>
/// <returns></returns>
public static string EncryptString(string text, string keyString = null)
{
if (keyString == null) keyString = COMMON_KEY;
var key = Encoding.UTF8.GetBytes(keyString);
using var aesAlg = Aes.Create();
var iv = aesAlg.IV;
using var encryptor = aesAlg.CreateEncryptor(key, iv);
using var msEncrypt = new MemoryStream();
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(text);
}
var decryptedContent = msEncrypt.ToArray();
var result = new byte[iv.Length + decryptedContent.Length];
Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
Buffer.BlockCopy(decryptedContent, 0, result, iv.Length, decryptedContent.Length);
return Convert.ToBase64String(result);
}
/// <summary>
/// passando il cipherText restituisce la stringa in chiaro
/// </summary>
/// <param name="cipherText">testo cifrato da decifrare</param>
/// <param name="keyString">se null usa quella comune definita nella classe</param>
/// <returns></returns>
public static string DecryptString(string cipherText, string keyString = null)
{
if (keyString == null) keyString = COMMON_KEY;
var fullCipher = Convert.FromBase64String(cipherText);
var iv = new byte[16];
var cipher = new byte[fullCipher.Length - iv.Length];
Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length);
Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, cipher.Length);
var key = Encoding.UTF8.GetBytes(keyString);
using var aesAlg = Aes.Create();
using var decryptor = aesAlg.CreateDecryptor(key, iv);
string result;
using (var msDecrypt = new MemoryStream(cipher))
{
using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
using var srDecrypt = new StreamReader(csDecrypt);
result = srDecrypt.ReadToEnd();
}
return result;
}
}
}
C#: Esempio d'uso
var data = "stringa da secretare";
// encryption
var enc = EncryptHelper.EncryptString(data);
Console.WriteLine(enc);
// decryption
var dec = EncryptHelper.DecriptString(enc);
Console.WriteLine(dec);
Nuova versione CryptoHelper.cs
Versione migliorata per .NET 10C#: CryptoHelper.cs
public static class CryptoHelper
{
/// <summary>
/// *** ATTENZIONE: ENCRYPTION_KEY Da cambiare per ogni applicazione, ***
/// deve essere una chiave segreta e sicura per la cifratura e decifratura dei dati lunga almeno 16 caratteri.
/// </summary>
private static readonly string ENCRYPTION_KEY = "Ci9jyYofATU3WzlH_CD1EF";
private const int IterazioniPbkdf2 = 600_000; // Standard di sicurezza consigliato
private const int DimensioneSaleBytes = 16; // 128 bit
private const int DimensioneIvBytes = 16; // 128 bit per AES
/// <summary>
/// Cripta il testo in chiaro usando AES con una chiave derivata dalla password fornita.
/// </summary>
/// <param name="clearText"></param>
/// <param name="password"></param>
/// <returns>ritorna una codificata in Base64 contenente: [Sale (16B)] + [IV (16B)] + [clearText Criptato]</returns>
public static string Encrypt(string clearText, string? password = null)
{
password ??= ENCRYPTION_KEY;
// Genera Salt e IV casuali e sicuri per questa specifica operazione
byte[] salt = RandomNumberGenerator.GetBytes(DimensioneSaleBytes);
byte[] iv = RandomNumberGenerator.GetBytes(DimensioneIvBytes);
// Deriva una chiave a 256 bit (32 byte) dalla password usando PBKDF2
byte[] key = Rfc2898DeriveBytes.Pbkdf2(password, salt, IterazioniPbkdf2, HashAlgorithmName.SHA256, outputLength: 32);
using MemoryStream ms = new();
// Scriviamo prima il Salt e l'IV nel flusso, non sono segreti!
ms.Write(salt, 0, salt.Length);
ms.Write(iv, 0, iv.Length);
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
// Criptiamo il testo e lo accodiamo nello stesso flusso
using CryptoStream cs = new(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);
using StreamWriter sw = new(cs, Encoding.UTF8);
sw.Write(clearText);
}
return Convert.ToBase64String(ms.ToArray());
}
/// <summary>
/// Decifra il testo criptato usando AES con la chiave derivata dalla password fornita.
/// </summary>
/// <param name="encryptedTextBase64"></param>
/// <param name="password"></param>
/// <returns></returns>
public static string Decrypt(string encryptedTextBase64, string? password = null)
{
password ??= ENCRYPTION_KEY;
byte[] datiCompleti = Convert.FromBase64String(encryptedTextBase64);
// Estraiamo il Salt e l'IV leggendo i rispettivi byte dall'inizio del pacchetto
byte[] salt = new byte[DimensioneSaleBytes];
byte[] iv = new byte[DimensioneIvBytes];
Buffer.BlockCopy(datiCompleti, 0, salt, 0, DimensioneSaleBytes);
Buffer.BlockCopy(datiCompleti, DimensioneSaleBytes, iv, 0, DimensioneIvBytes);
// Rigeneriamo la stessa identica chiave partendo dalla password e dal salt estratto
byte[] key = Rfc2898DeriveBytes.Pbkdf2(password, salt, IterazioniPbkdf2, HashAlgorithmName.SHA256, outputLength: 32);
using Aes aes = Aes.Create();
aes.Key = key;
aes.IV = iv;
// Calcoliamo dove inizia il vero testo criptato saltando i byte di Salt e IV
int offsetTestoCriptato = DimensioneSaleBytes + DimensioneIvBytes;
int lunghezzaTestoCriptato = datiCompleti.Length - offsetTestoCriptato;
using MemoryStream ms = new(datiCompleti, offsetTestoCriptato, lunghezzaTestoCriptato);
using CryptoStream cs = new(ms, aes.CreateDecryptor(), CryptoStreamMode.Read);
using StreamReader sr = new(cs, Encoding.UTF8);
return sr.ReadToEnd();
}
}