Pewnie szyfrujesz za pomocą jakiegoś hasła. Zawsze jedno i drugie możesz generować na jego podstawie:
using System;
using System.Text;
using System.Linq;
using System.Security.Cryptography;
using System.IO;
namespace Prg {
public class AES {
public enum Process {
Encryption,
Decryptopn
}
private AesCryptoServiceProvider _aes;
public AES() {
this._aes = new AesCryptoServiceProvider();
this._aes.KeySize = 256;
this._aes.BlockSize = 128;
}
public byte[] Encrypt(byte[] plain, string password, Process process = Process.Encryption) {
try {
using (var pass = new PasswordDeriveBytes(password, this.GenerateSalt(this._aes.BlockSize / 8, password))) {
using (var stream = new MemoryStream()) {
this._aes.Key = pass.GetBytes(this._aes.KeySize / 8);
this._aes.IV = pass.GetBytes(this._aes.BlockSize / 8);
var proc = (process == Process.Encryption) ? this._aes.CreateEncryptor() : this._aes.CreateDecryptor();
using (var crypto = new CryptoStream(stream, proc, CryptoStreamMode.Write)) {
crypto.Write(plain, 0, plain.Length);
crypto.Clear();
crypto.Close();
}
stream.Close();
return stream.ToArray();
}
}
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
return null;
}
}
private byte[] GenerateSalt(int size, string password) {
var buffer = new byte[size];
var passBytes = ASCIIEncoding.ASCII.GetBytes(password);
if (passBytes.Length > buffer.Length) Array.Copy(passBytes, buffer, buffer.Length);
else Array.Copy(passBytes, buffer, passBytes.Length);
return buffer;
}
public byte[] Decrypt(byte[] encrypted, string password) {
return this.Encrypt(encrypted, password, Process.Decryptopn);
}
}
class Program {
public static void Main(string[] args) {
var aesEncrypt = new AES();
var plain = "Grzesiek Tomek Kasia";
var encrypted = aesEncrypt.Encrypt(ASCIIEncoding.ASCII.GetBytes(plain), "haselko");
// Nowa instancja żeby zasymulować rzeczywiste działanie.
var aesDecrypt = new AES();
var decrypted = aesDecrypt.Decrypt(encrypted, "haselko");
Console.WriteLine(ASCIIEncoding.ASCII.GetString(decrypted));
}
}
}
Jak pewnie zauważyłeś sól przez mnie wygenerowana ma pewną słabość. Kiedy hasło będzie mieć mniej niż żądana ilość bajtów to dopełnienie będzie wypełnione zerami. Trzeba by jakoś to naprawić, żeby była większa losowość, bez konieczności zapamiętywania gdzieś soli ale dla przykładu wystarczy.
Generalnie:
Sól oraz IV możesz przechowywać jawnie, tj. dołączyć gdzieś do szyfrogramu i później sparsować najlepiej serializując taki obiekt:
public class Cryptogram {
public byte[] encrypted { get; set; }
public byte[] IV { get; set; }
public byte[] Salt { get; set; }
}
PS: Nie musisz robić GenerateIV()
czy GenerateKey()
. Klucze są i tak tworzone z automatu więc to zbędne.