I have following code that works fine when I use a four letter word as input, E.g. “Test”. When the input is not a multiple of 4, it fails E.g. “MyTest”.
Eexception: Invalid length for a Base-64 char array.
QUESTIONS
- Is it guaranteed that the encrypted result will be always compatible to a Unicode string (without any loss). If yes I can use UTF encoding instead of Base64? What's the difference between UTF8/UTF16 and Base64 in terms of encoding
- How can add padding so that we get correct result (after decryption) even if the input is not a multiple of 4?
MAIN PRGORAM
class Program
{
static void Main(string[] args)
{
string valid128BitString = "AAECAwQFBgcICQoLDA0ODw==";
string inputValue = "MyTest";
string keyValue = valid128BitString;
byte[] byteValForString = Convert.FromBase64String(inputValue);
EncryptResult result = Aes128Utility.EncryptData(byteValForString, keyValue);
EncryptResult encyptedValue = new EncryptResult();
string resultingIV = "4uy34C9sqOC9rbV4GD8jrA==";
if (String.Equals(resultingIV,result.IV))
{
int x = 0;
}
encyptedValue.IV = resultingIV;
encyptedValue.EncryptedMsg = result.EncryptedMsg;
string finalResult = Convert.ToBase64String(Aes128Utility.DecryptData(encyptedValue, keyValue));
Console.WriteLine(finalResult);
if (String.Equals(inputValue, finalResult))
{
Console.WriteLine("Match");
}
else
{
Console.WriteLine("Differ");
}
Console.ReadLine();
}
}
AES Crypto UTILITY
public static class Aes128Utility
{
private static byte[] key;
public static EncryptResult EncryptData(byte[] rawData, string strKey)
{
EncryptResult result = null;
if (key == null)
{
if (!String.IsNullOrEmpty(strKey))
{
key = Convert.FromBase64String((strKey));
result = Encrypt(rawData);
}
}
else
{
result = Encrypt(rawData);
}
return result;
}
public static byte[] DecryptData(EncryptResult encryptResult, string strKey)
{
byte[] origData = null;
if (key == null)
{
if (!String.IsNullOrEmpty(strKey))
{
key = Convert.FromBase64String(strKey);
origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
}
}
else
{
origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
}
return origData;
}
private static EncryptResult Encrypt(byte[] rawData)
{
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
aesProvider.Key = key;
aesProvider.Mode = CipherMode.CBC;
aesProvider.Padding = PaddingMode.PKCS7;
aesProvider.IV = Convert.FromBase64String("4uy34C9sqOC9rbV4GD8jrA==");
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream encStream = new CryptoStream(memStream, aesProvider.CreateEncryptor(), CryptoStreamMode.Write);
encStream.Write(rawData, 0, rawData.Length);
encStream.FlushFinalBlock();
EncryptResult encResult = new EncryptResult();
encResult.EncryptedMsg = Convert.ToBase64String(memStream.ToArray());
encResult.IV = Convert.ToBase64String(aesProvider.IV);
return encResult;
}
}
}
private static byte[] Decrypt(byte[] encryptedMsg, byte[] iv)
{
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
aesProvider.Key = key;
aesProvider.IV = iv;
aesProvider.Mode = CipherMode.CBC;
aesProvider.Padding = PaddingMode.PKCS7;
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream decStream = new CryptoStream(memStream, aesProvider.CreateDecryptor(), CryptoStreamMode.Write);
decStream.Write(encryptedMsg, 0, encryptedMsg.Length);
decStream.FlushFinalBlock();
return memStream.ToArray();
}
}
}
}
DTO
public class EncryptResult
{
public string EncryptedMsg { get; set; }
public string IV { get; set; }
}
REFERENCES:
- How to create byte[] with length 16 using FromBase64String
- Getting incorrect decryption value using AesCryptoServiceProvider