diff --git a/Pilz.Cryptography/AESStringCrypter.cs b/Pilz.Cryptography/AESStringCrypter.cs
new file mode 100644
index 0000000..fdb4160
--- /dev/null
+++ b/Pilz.Cryptography/AESStringCrypter.cs
@@ -0,0 +1,212 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Pilz.Cryptography
+{
+ public class AESStringCrypter : ICrypter
+ {
+ public delegate void AESStringCrypterEventHandler(AESStringCrypter sender);
+
+ ///
+ /// This event throws if no key and no default key was found. You can now provide a key or default key (maybe depending on the given instance). If no value is provided, a default key will be created.
+ ///
+ public static event AESStringCrypterEventHandler NeedKey;
+ ///
+ /// This event throws if no IV and no default IV was found. You can now provide a IV or default IV (maybe depending on the given instance). If no value is provided, a default IV will be created.
+ ///
+ public static event AESStringCrypterEventHandler NeedIV;
+
+ private byte[] key = new byte[] { };
+ private byte[] iv = new byte[] { };
+
+ private static byte[] defaultKey = new byte[] { };
+ private static byte[] defaultIV = new byte[] { };
+
+ public Encoding Encoding { get; set; } = Encoding.Default;
+ public string Name { get; set; }
+ public object Tag { get; set; }
+
+ public string Key
+ {
+ get => Convert.ToBase64String(key);
+ set => key = Convert.FromBase64String(value);
+ }
+
+ public string IV
+ {
+ get => Convert.ToBase64String(iv);
+ set => iv = Convert.FromBase64String(value);
+ }
+
+ public static string DefaultKey
+ {
+ get => Convert.ToBase64String(defaultKey);
+ set => defaultKey = Convert.FromBase64String(value);
+ }
+
+ public static string DefaultIV
+ {
+ get => Convert.ToBase64String(defaultIV);
+ set => defaultIV = Convert.FromBase64String(value);
+ }
+
+ public string Decrypt(string encryptedValue)
+ {
+ return DecryptStringFromBytes_Aes(Convert.FromBase64String(encryptedValue), GetKey(), GetIV());
+ }
+
+ public string Encrypt(string plainValue)
+ {
+ return Convert.ToBase64String(EncryptStringToBytes_Aes(plainValue, GetKey(), GetIV()));
+ }
+
+ private byte[] GetKey(bool createIfFail = false)
+ {
+ byte[] keyToUse;
+
+ if (key.Length != 0)
+ keyToUse = key;
+ else if (defaultKey.Length != 0)
+ keyToUse = defaultKey;
+ else if (createIfFail)
+ keyToUse = defaultKey = GenerateKeyInternal();
+ else
+ {
+ NeedKey?.Invoke(this);
+ keyToUse = GetKey(true);
+ }
+
+ return keyToUse;
+ }
+
+ private byte[] GetIV(bool createIfFail = false)
+ {
+ byte[] ivToUse;
+
+ if (iv.Length != 0)
+ ivToUse = iv;
+ else if (defaultIV.Length != 0)
+ ivToUse = defaultIV;
+ else if (createIfFail)
+ ivToUse = defaultIV = GenerateIVInternal();
+ else
+ {
+ NeedIV?.Invoke(this);
+ ivToUse = GetIV(true);
+ }
+
+ return ivToUse;
+ }
+
+ private static byte[] GenerateKeyInternal()
+ {
+ var aes = Aes.Create();
+ var key = aes.Key;
+ aes.Dispose();
+ return key;
+ }
+
+ public static string GenerateKey()
+ {
+ return Convert.ToBase64String(GenerateKeyInternal());
+ }
+
+ private static byte[] GenerateIVInternal()
+ {
+ var aes = Aes.Create();
+ var iv = aes.IV;
+ aes.Dispose();
+ return iv;
+ }
+
+ public static string GenerateIV()
+ {
+ return Convert.ToBase64String(GenerateIVInternal());
+ }
+
+ private static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
+ {
+ // Check arguments.
+ if (plainText == null || plainText.Length <= 0)
+ throw new ArgumentNullException("plainText");
+ if (Key == null || Key.Length <= 0)
+ throw new ArgumentNullException("Key");
+ if (IV == null || IV.Length <= 0)
+ throw new ArgumentNullException("IV");
+ byte[] encrypted;
+
+ // Create an Aes object
+ // with the specified key and IV.
+ using (Aes aesAlg = Aes.Create())
+ {
+ aesAlg.Key = Key;
+ aesAlg.IV = IV;
+
+ // Create an encryptor to perform the stream transform.
+ ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
+
+ // Create the streams used for encryption.
+ using (MemoryStream msEncrypt = new MemoryStream())
+ {
+ using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
+ {
+ using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
+ {
+ //Write all data to the stream.
+ swEncrypt.Write(plainText);
+ }
+ encrypted = msEncrypt.ToArray();
+ }
+ }
+ }
+
+ // Return the encrypted bytes from the memory stream.
+ return encrypted;
+ }
+
+ private static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
+ {
+ // Check arguments.
+ if (cipherText == null || cipherText.Length <= 0)
+ throw new ArgumentNullException("cipherText");
+ if (Key == null || Key.Length <= 0)
+ throw new ArgumentNullException("Key");
+ if (IV == null || IV.Length <= 0)
+ throw new ArgumentNullException("IV");
+
+ // Declare the string used to hold
+ // the decrypted text.
+ string plaintext = null;
+
+ // Create an Aes object
+ // with the specified key and IV.
+ using (Aes aesAlg = Aes.Create())
+ {
+ aesAlg.Key = Key;
+ aesAlg.IV = IV;
+
+ // Create a decryptor to perform the stream transform.
+ ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
+
+ // Create the streams used for decryption.
+ using (MemoryStream msDecrypt = new MemoryStream(cipherText))
+ {
+ using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
+ {
+ using (StreamReader srDecrypt = new StreamReader(csDecrypt))
+ {
+ // Read the decrypted bytes from the decrypting stream
+ // and place them in a string.
+ plaintext = srDecrypt.ReadToEnd();
+ }
+ }
+ }
+ }
+
+ return plaintext;
+ }
+ }
+}