134 lines
4.7 KiB
C#
134 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace ServiceShared.Crypto
|
|
{
|
|
public static class AES
|
|
{
|
|
private static string MemoryMasterKey = "!ZEqy2Zsb#VK6<8`H6;W~VxJ$r:w.{ffzwDt=<yKC6m6N3;T<9nyeF&+.4&D@rhK";
|
|
public const string PGS_ENCRYPT_PARTIAL_KEY = "wA6j@x.CcmM>~5Ss^C_!#,zch)$YsDsd59,::>dW#F`@U]Ye5ETZcMT7}&+#*!%z";
|
|
|
|
/// <summary>
|
|
/// Sets the memory master key
|
|
/// </summary>
|
|
/// <param name="key">master key that should be set in the memory</param>
|
|
public static void SetMemoryMasterKey(string deriveKey)
|
|
{
|
|
MemoryMasterKey = deriveKey;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Encrypts string with password
|
|
/// </summary>
|
|
/// <param name="value">string value that should be encrypted</param>
|
|
/// <param name="deriveKey">shared deriveKey that should be used for encryption(max. 32 bytes)</param>
|
|
/// <returns>returns encrypted base64 string</returns>
|
|
public static string Encrypt(string value, byte[] deriveKey = null)
|
|
{
|
|
string result = null;
|
|
|
|
try
|
|
{
|
|
if (deriveKey == null)
|
|
{
|
|
deriveKey = AES.GetKey(MemoryMasterKey);
|
|
}
|
|
|
|
using (AesGcm aes = new AesGcm(deriveKey))
|
|
{
|
|
byte[] nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
|
|
RandomNumberGenerator.Fill(nonce);
|
|
byte[] plainText = Encoding.UTF8.GetBytes(value);
|
|
byte[] chiperBuffer = new byte[plainText.Length];
|
|
byte[] tag = new byte[AesGcm.TagByteSizes.MaxSize];
|
|
aes.Encrypt(nonce, plainText, chiperBuffer, tag);
|
|
byte[] resultBuffer = nonce.Concat(chiperBuffer).Concat(tag).ToArray();
|
|
result = Convert.ToBase64String(resultBuffer);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
result = null;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Decrypts encrypted base64 string with password
|
|
/// </summary>
|
|
/// <param name="value">base64 string that should be decrypted</param>
|
|
/// <param name="deriveKey">HKDF.DeriveKey of sharedSecret</param>
|
|
/// <returns>returns plain string</returns>
|
|
public static string Decrypt(string value, byte[] deriveKey = null)
|
|
{
|
|
string result = null;
|
|
|
|
try
|
|
{
|
|
if (deriveKey == null)
|
|
{
|
|
deriveKey = AES.GetKey(MemoryMasterKey);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(value) && deriveKey != null && deriveKey.Length == 32)
|
|
{
|
|
using (AesGcm aes = new AesGcm(deriveKey))
|
|
{
|
|
byte[] combined = Convert.FromBase64String(value);
|
|
byte[] tag = combined.Skip(combined.Length - AesGcm.TagByteSizes.MaxSize).ToArray();
|
|
byte[] nonce = combined.Take(AesGcm.NonceByteSizes.MaxSize).ToArray();
|
|
byte[] chiperText = combined.Skip(nonce.Length).Take(combined.Length - nonce.Length - tag.Length).ToArray();
|
|
byte[] plainTextBuffer = new byte[chiperText.Length];
|
|
aes.Decrypt(nonce, chiperText, tag, plainTextBuffer);
|
|
result = Encoding.UTF8.GetString(plainTextBuffer);
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
result = null;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts the text passed password to the 32 byte array
|
|
/// </summary>
|
|
/// <param name="password">Text based password</param>
|
|
/// <returns></returns>
|
|
public static byte[] GetKey(string password)
|
|
{
|
|
byte[] result = null;
|
|
|
|
try
|
|
{
|
|
if (!string.IsNullOrEmpty(password))
|
|
{
|
|
if (password.Length < 32)
|
|
{
|
|
password = password.PadRight(32, '@');
|
|
}
|
|
else if (password.Length > 32)
|
|
{
|
|
password = MD5.Encrypt(password);
|
|
}
|
|
|
|
result = Encoding.ASCII.GetBytes(password);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Critical(ex, "ServiceShared.Crypto.AES", "GetKey");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|