249 lines
8.0 KiB
C#
249 lines
8.0 KiB
C#
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);
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public static event AESStringCrypterEventHandler NeedKey;
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
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 AESStringCrypter()
|
|
{
|
|
}
|
|
|
|
public AESStringCrypter(string key, string iv) : this()
|
|
{
|
|
Key = key;
|
|
IV = iv;
|
|
}
|
|
|
|
public string Decrypt(string encryptedValue)
|
|
{
|
|
try
|
|
{
|
|
return DecryptStringFromBytes_Aes(Convert.FromBase64String(encryptedValue), GetKey(), GetIV());
|
|
}
|
|
catch (CryptographicException)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
public static string Decrypt(string encryptedValue, string key, string iv)
|
|
{
|
|
var crypter = new AESStringCrypter(key, iv);
|
|
return crypter.Decrypt(encryptedValue);
|
|
}
|
|
|
|
public string Encrypt(string plainValue)
|
|
{
|
|
try
|
|
{
|
|
return Convert.ToBase64String(EncryptStringToBytes_Aes(plainValue, GetKey(), GetIV()));
|
|
}
|
|
catch (CryptographicException)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
public static string Encrypt(string plainValue, string key, string iv)
|
|
{
|
|
var crypter = new AESStringCrypter(key, iv);
|
|
return crypter.Encrypt(plainValue);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|