I'm working on AES encryption/decryption. I want to encrypt request from my angular app and send it to .net api and decrypt at api then encrypt the response from api side and send it to angular app and decrypt using AES.
But sometimes it gives me 'padding is invalid and cannot be removed' exception at api side.
Here is my angular typescript crypto service code:
aesEncrypt(keys: string, value: string) { // encrypt api request parameter with aes secretkey
var key = CryptoJS.enc.Utf8.parse(keys);
var iv = CryptoJS.enc.Utf8.parse(keys);
var encrypted = CryptoJS.AES.encrypt(JSON.stringify(value), key,
{
keySize: 128 / 8,
//keySize: 128,
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
return encrypted.toString();
}
aesDecrypt(keys: string, value: any) { // decrypt api response parameter with aes secretkey
var key = CryptoJS.enc.Utf8.parse(keys);
var iv = CryptoJS.enc.Utf8.parse(keys);
var decrypted = CryptoJS.AES.decrypt(value, key, {
keySize: 128 / 8,
//keySize: 128,
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return JSON.parse(decrypted.toString(CryptoJS.enc.Utf8));
}
Here is my api crypto filter code:
Way 1:
public static string Encrypt(string key, string data)
{
byte[] encryptedBytes = new UTF8Encoding().GetBytes(data);
AesCryptoServiceProvider aes = AesCryptoServiceProvider(key);
ICryptoTransform crypto = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] secret = crypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
crypto.Dispose();
return Convert.ToBase64String(secret);
}
public static string Decrypt(string key, string encrypted)
{
byte[] encryptedBytes = Convert.FromBase64String(encrypted);
AesCryptoServiceProvider aes = AesCryptoServiceProvider(key);
ICryptoTransform crypto = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] secret = crypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
crypto.Dispose();
return Encoding.UTF8.GetString(secret);
}
private static AesCryptoServiceProvider AesCryptoServiceProvider(string key)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
//aes.BlockSize = 128; //Not Required
//aes.KeySize = 256; //Not Required
//aes.KeySize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Encoding.UTF8.GetBytes(key); //PSVJQRk9QTEpNVU1DWUZCRVFGV1VVT0 =
aes.IV = Encoding.UTF8.GetBytes(key); //2314345645678765
return aes;
}
Way 2:
public static string Encrypt(string key, string data)
{
AesCryptoServiceProvider aes = AesCryptoServiceProvider(key);
ICryptoTransform encryptor = aes.CreateEncryptor();
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
StreamWriter streamWriter = new StreamWriter(cs);
streamWriter.Write(data);
streamWriter.Flush();
cs.FlushFinalBlock();
byte[] cypherTextBytes = ms.ToArray();
ms.Close();
return Convert.ToBase64String(cypherTextBytes);
}
public static string Decrypt(string key, string encrypted)
{
AesCryptoServiceProvider aes = AesCryptoServiceProvider(key);
byte[] encryptedBytes = Convert.FromBase64String(encrypted);
ICryptoTransform decryptor = aes.CreateDecryptor();
byte[] plainText = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
return Encoding.UTF8.GetString(plainText);
}
private static AesCryptoServiceProvider AesCryptoServiceProvider(string key)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
//aes.BlockSize = 128; //Not Required
//aes.KeySize = 256; //Not Required
//aes.KeySize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Encoding.UTF8.GetBytes(key); //PSVJQRk9QTEpNVU1DWUZCRVFGV1VVT0 =
aes.IV = Encoding.UTF8.GetBytes(key); //2314345645678765
return aes;
}
I tried both the ways at api level but still it is giving me padding issue (sometimes, not always)
Related
I'm working on a project where I have to encrypt and decrypt chosen files by user. How can I use a password from user as a key for AES encryption/decryption? Right now they can enter passwords of 8 or 16 characters long. I don't want to force the user to specify a password of 8 or 16 characters.
public static void EncryptFile(string file, string password)
{
try
{
string outputFile = Path.GetFileNameWithoutExtension(file) + "-encrypted" + Path.GetExtension(file);
byte[] fileContent = File.ReadAllBytes(file);
UnicodeEncoding UE = new UnicodeEncoding();
using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
{
AES.Key = UE.GetBytes(password);
AES.IV = new byte[16];
AES.Mode = CipherMode.CBC;
AES.Padding = PaddingMode.PKCS7;
using (MemoryStream memoryStream = new MemoryStream())
{
CryptoStream cryptoStream = new CryptoStream(memoryStream, AES.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(fileContent, 0, fileContent.Length);
cryptoStream.FlushFinalBlock();
File.WriteAllBytes(outputFile, memoryStream.ToArray());
}
}
}
catch (Exception ex)
{
MessageBox.Show("Exception thrown while encrypting the file!" + "\n" + ex.Message);
}
}
AES in .net uses by default a 256 bit key and a 128 bit IV .
SHA256 and MD5 hash algorithms create a 256 bit and a 128 bit hash respectively.
Hmmm.
byte[] passwordBytes = UE.GetBytes(password);
byte[] aesKey = SHA256Managed.Create().ComputeHash(passwordBytes);
byte[] aesIV = MD5.Create().ComputeHash(passwordBytes);
AES.Key = aesKey;
AES.IV = aesIV;
AES.Mode = CipherMode.CBC;
AES.Padding = PaddingMode.PKCS7;
I have the following lines in a PHP 7 program encrypting/decrypting data:
$key = base64_decode("mykey===");
$iv = substr(hash('sha256', "myiv======"), 0, 16);
printf(base64_encode(openssl_encrypt("hello", "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv)));
printf("<br>");
printf(openssl_decrypt(base64_decode("2XJxQXSbPuJ9LMsZ/FESGw=="), "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv));
This is working, PHP decrypts "hello" to "2XJxQXSbPuJ9LMsZ/FESGw==" and vice versa. However I'm trying to decrypt and encrypt the same data (from a Database) with C# but can't seem to figure it out. I used the following method for decryption (C#):
private string aes_decrypt(string cipherText, string key, string iv)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
aes.Key = Convert.FromBase64String(key);
aes.IV = Encoding.UTF8.GetBytes(iv);
if (aes.Key.Length < 32)
{
var paddedkey = new byte[32];
Buffer.BlockCopy(aes.Key, 0, paddedkey, 0, aes.Key.Length);
aes.Key = paddedkey;
}
var decrypt = aes.CreateDecryptor();
byte[] xBuff = null;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
byte[] xXml = Convert.FromBase64String(cipherText);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = ms.ToArray();
}
String Output = Encoding.UTF8.GetString(xBuff);
return Output;
}
But a call to this method:
string encryptionkey = "mykey===";
string encryptioniv = GenerateSHA256String("myiv======").Substring(0, 16);
string str = aes_decrypt("2XJxQXSbPuJ9LMsZ/FESGw==", encryptionkey, encryptioniv);
Console.WriteLine(#str);
returns: HellO++++??????+
The encryption method doesnt seem to work either (referenced online and modified):
private static String EncryptIt(String s, string akey, string aIV)
{
String result;
byte[] key = Convert.FromBase64String(akey);
byte[] IV = Encoding.UTF8.GetBytes(aIV);
RijndaelManaged rijn = new RijndaelManaged();
rijn.Mode = CipherMode.CBC;
rijn.Padding = PaddingMode.PKCS7;
rijn.KeySize = 256;
rijn.BlockSize = 128;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (ICryptoTransform encryptor = rijn.CreateEncryptor(key, IV))
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(s);
}
}
}
result = Convert.ToBase64String(msEncrypt.ToArray());
}
rijn.Clear();
return result;
}
A call to this method: EncryptIt("hello", encryptionkey, encryptioniv); returns ul0axDR0WWGcpeijPRNusg== and not 2XJxQXSbPuJ9LMsZ/FESGw== which was generated by PHP. Anyone knows what's wrong here?
For reference, I used these methods with the IV, they are working without errors:
private string GenerateSHA256String(string inputString)
{
SHA256 sha256 = SHA256Managed.Create();
byte[] bytes = Encoding.UTF8.GetBytes(inputString);
byte[] hash = sha256.ComputeHash(bytes);
return GetStringFromHash(hash);
}
private string GetStringFromHash(byte[] hash)
{
StringBuilder result = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
result.Append(hash[i].ToString("X2"));
}
return result.ToString();
}
Old question, but I ran into this again recently.
When using PHP 7.2 openssl_decrypt/openssl_encrypt padding as OPENSSL_RAW_DATA, it only worked for me when the chsarp AES padding was set to PaddingMode.PKCS7.
The original post has PaddingMode.None for decrypt and PaddingMode.PKCS7 for encrypt.
I have c sharp code snippet for encryption which uses .Key file for key and my requirement is to decrypt the encrypted text using same key in android, having problem
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes) {
byte[] encryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
If you want to decrypt some data with AES you can use this method:
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
for complete code look at : android encryption/decryption with AES
I want to encrypt a string using AES 256-bit encryption algorithm with ECB and PKCS7Padding. I had gone through many sites but none of them were suitable.
Please suggest a solution
public static string Encrypt(string PlainText, string Password,
string Salt = "Kosher", string HashAlgorithm = "SHA1",
int PasswordIterations = 2, string InitialVector = "OFRna73m*aze01xY",
int KeySize = 256)
{
if (string.IsNullOrEmpty(PlainText))
return "";
byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);
PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
RijndaelManaged SymmetricKey = new RijndaelManaged();
SymmetricKey.Mode = CipherMode.CBC;
byte[] CipherTextBytes = null;
using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
{
using (MemoryStream MemStream = new MemoryStream())
{
using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
{
CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
CryptoStream.FlushFinalBlock();
CipherTextBytes = MemStream.ToArray();
MemStream.Close();
CryptoStream.Close();
}
}
}
SymmetricKey.Clear();
return Convert.ToBase64String(CipherTextBytes);
}
source
Note: you can change the mode by changing SymmetricKey.Mode = CipherMode.CBC;
and you can add SymmetricKey.Padding = PaddingMode.PKCS7; for padding
with bounty castle you should be able to do this :
cipher = CipherUtilities.GetCipher("AES/ECB/PKCS7");
cipher.Init(false, new KeyParameter(key));
Every time I run this and encrypt, the output is variable, and when I attempt to decrypt
I get "Padding is invalid and cannot be removed." Been fighting with this for a day or two now and I am at a loss.
private static string strIV = "abcdefghijklmnmo"; //The initialization vector.
private static string strKey = "abcdefghijklmnmoabcdefghijklmnmo"; //The key used to encrypt the text.
public static string Decrypt(string TextToDecrypt)
{
return Decryptor(TextToDecrypt);
}
private static string Encryptor(string TextToEncrypt)
{
//Turn the plaintext into a byte array.
byte[] PlainTextBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToEncrypt);
//Setup the AES providor for our purposes.
AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);
aesProvider.BlockSize = 128;
aesProvider.KeySize = 256;
aesProvider.Padding = PaddingMode.PKCS7;
aesProvider.Mode = CipherMode.CBC;
ICryptoTransform cryptoTransform = aesProvider.CreateEncryptor(aesProvider.Key, aesProvider.IV);
byte[] EncryptedBytes = cryptoTransform.TransformFinalBlock(PlainTextBytes, 0, PlainTextBytes.Length);
return Convert.ToBase64String(EncryptedBytes);
}
private static string Decryptor(string TextToDecrypt)
{
byte[] EncryptedBytes = Convert.FromBase64String(TextToDecrypt);
//Setup the AES provider for decrypting.
AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);
aesProvider.BlockSize = 128;
aesProvider.KeySize = 256;
aesProvider.Padding = PaddingMode.PKCS7;
aesProvider.Mode = CipherMode.CBC;
ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV);
byte[] DecryptedBytes = cryptoTransform.TransformFinalBlock(EncryptedBytes, 0, EncryptedBytes.Length);
return System.Text.Encoding.ASCII.GetString(DecryptedBytes);
}
}
You need to set the BlockSize and the KeySize before you set the Key and the IV. Additionally you should probably be generating a random IV for each message and note that ICryptoTransform implements IDisposable so these objects should be disposed.