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
Related
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)
I have my own stream cipher algorithm, and I made a comparison between it and AES performance. I tested it on several files with different sizes(to 500KB). Its encryption/decryption time is less than AES for files about 500KB. but with files more than 500KB, its encryption time is more than AES but still its decryption time is the least one.
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 128;
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.Padding = PaddingMode.Zeros;
AES.Mode = CipherMode.CFB;
using (var cs = new CryptoStream(ms,
AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0,
bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
ms.Close();
}
return encryptedBytes;
}
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 128;
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.Padding = PaddingMode.Zeros;
AES.Mode = CipherMode.CFB;
using (var cs = new CryptoStream(ms,
AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0,
bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
I'm making a program to encrypt all files in a folder to not encrypt files 1 by 1.
So, here is my code for the AES 256 encryption
public class CoreEncryption
{
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;
}
}
public class CoreDecryption
{
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = 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.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
}
And this to start encrypting and decrypting files
public class EncryptionFile
{
public void EncryptFile(string file, string password)
{
byte[] bytesToBeEncrypted = File.ReadAllBytes(file);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
// Hash the password with SHA256
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesEncrypted = CoreEncryption.AES_Encrypt(bytesToBeEncrypted, passwordBytes);
string fileEncrypted = file;
File.WriteAllBytes(fileEncrypted, bytesEncrypted);
}
}
public class DecryptionFile
{
public void DecryptFile(string fileEncrypted, string password)
{
byte[] bytesToBeDecrypted = File.ReadAllBytes(fileEncrypted);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesDecrypted = CoreDecryption.AES_Decrypt(bytesToBeDecrypted, passwordBytes);
string file = fileEncrypted;
File.WriteAllBytes(file, bytesDecrypted);
}
}
So now, I want to enter a folder path, and that my encryption process crypt every files in that chosen folder. How can I do that ?
Um....
Just like this?
It works fine on (Windows10 pro x64 / Visual Studio 2017).
Good luck.
//! ----------------------------------------------------------------
static void Test1()
{
string[] files = Directory.GetFiles(#"D:\_test", "*", SearchOption.AllDirectories);
EncryptionFile enc = new EncryptionFile();
//DecryptionFile dec = new DecryptionFile();
string password = "abcd";
for (int i=0; i<files.Length; i++)
{
Console.WriteLine(files[i]);
enc.EncryptFile(files[i], password);
//dec.DecryptFile(files[i], password);
}
}
Description
I am using a slightly modified security class taken straight from codeproject.com, I am using it to encrypt/decrypt aes byte arrays.
I have tested that the key generation method in these produces the same key, and they are given the same password and salt. they also have the same IV
the error is always on the line after the CryptoStream.Write in the AES_Decrypt function
"An unhandled exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll
Additional information: Padding is invalid and cannot be removed."
(yes i know having a static salt is bad, this is only for testing purposes)
Solutions that didn't work
Paddingmode.Zeros
Paddingmode.None
.FlushFinalBlock();
Related Questions
"Padding is invalid and cannot be removed" using AesManaged
Padding is invalid and cannot be removed?
Padding is invalid and cannot be removed Exception while decrypting string using "AesManaged" C#
Error RijndaelManaged, "Padding is invalid and cannot be removed"
Related Links
https://social.msdn.microsoft.com/Forums/vstudio/en-US/d1788582-bf8c-43ec-a686-49647c359136/unexplained-cryptographicexception-padding-is-invalid?forum=netfxbcl
http://www.codeproject.com/Questions/379525/Padding-is-invalid-and-cannot-be-removed-Exception
Code
using System.Security.Cryptography;
using System.IO;
using System;
namespace FinexCore
{
public class Security
{
/*
* AES encrypt and decrypt from:
* http://www.codeproject.com/Articles/769741/Csharp-AES-bits-Encryption-Library-with-Salt
*/
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
private byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8}; //8 bytes
public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.Padding = PaddingMode.PKCS7;
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.FlushFinalBlock();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
public byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.Padding = PaddingMode.PKCS7;
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.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.FlushFinalBlock();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
public void Wipe()
{
Array.Clear(saltBytes, 0, saltBytes.Length);
}
}
}
note: the save and load functions are called with the exact same password
The code that calls the encryption
public void Load(byte[] password)
{
Security decryptor = new Security();
byte[] bytes = decryptor.AES_Decrypt(System.IO.File.ReadAllBytes(Pathname()), password);
using (MemoryStream stream = new MemoryStream(bytes))
{
var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
Root = (Folder)binaryFormatter.Deserialize(stream);
}
Array.Clear(bytes, 0, bytes.Length);
Array.Clear(password, 0, password.Length);
decryptor.Wipe();
}
public void Save(byte[] password)
{
byte[] bytes;
using (MemoryStream stream = new MemoryStream())
{
var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
binaryFormatter.Serialize(stream, Root);
bytes = stream.ToArray();
}
Security encryptor = new Security();
bytes = encryptor.AES_Encrypt(bytes, password);
System.IO.File.WriteAllBytes(Pathname(), bytes);
Array.Clear(bytes, 0, bytes.Length);
Array.Clear(password, 0, password.Length);
encryptor.Wipe();
}
Code for testing key generation
static void keytests()
{
byte[] passwordBytes = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
byte[] saltBytes = { 1, 2, 3, 4, 5, 6, 7, 8};
int iterations = 1000;
var key1 = new Rfc2898DeriveBytes(passwordBytes, saltBytes, iterations);
var key2 = new Rfc2898DeriveBytes(passwordBytes, saltBytes, iterations);
Console.WriteLine(BTS(key1.GetBytes(256 / 8)));
Console.WriteLine(BTS(key2.GetBytes(256 / 8)));
}
public static string BTS(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
Is there a way to encrypt data with AES? I'd love to use at least 128 Bits for the encryption Key.
I tried with AES default class provided by Microsoft but I can't do a lot... I can't set the Key Lenght.
Is there another Class that I can use?
Yes. You can use the code listed at http://www.codeproject.com/Articles/769741/Csharp-AES-bits-Encryption-Library-with-Salt
You Can Use RIJNDAEL:
First you need to include using System.Security.Cryptography;
public 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;
}
public byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = 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.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
public void EncryptFile(string filename, string outfilename, string psw)
{
string file = filename;
string password = psw;
byte[] bytesToBeEncrypted = File.ReadAllBytes(file); //read bytes to encrypt them
byte[] passwordBytes = Encoding.UTF8.GetBytes(password); //read with UTF8 encoding the password.
passwordBytes = SHA256.Create().ComputeHash(passwordBytes); //hash the psw
byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
string fileEncrypted = outfilename;
File.WriteAllBytes(fileEncrypted, bytesEncrypted);
}
public void DecryptFile(string filename, string outfilename, string psw)
{
string fileEncrypted = filename;
string password = psw;
byte[] bytesToBeDecrypted = File.ReadAllBytes(fileEncrypted);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);
string file = outfilename;
File.WriteAllBytes(file, bytesDecrypted);
}