I want to encrypt picturebox image and save it to file and be able to decrypt it and load back to picturebox. There are various code examples out there but none of them seem to work for me. I always get bigger decrypted file than the original one is.
I tried different methods to do this and here is most current one I wrote:
// Save signature file
public void SaveFile(System.Drawing.Image image, string filename, string password)
{
byte[] img = imgToByteArray(image);
byte[] encrypted = Signatures.Encryption.Encrypt(img, password);
File.WriteAllBytes(filename, encrypted);
// DEBUG
byte[] decrypted = Signatures.Encryption.Decrypt(encrypted, password);
image.Save(filename + "O");
File.WriteAllBytes(filename + "E", encrypted);
File.WriteAllBytes(filename + "D", decrypted);
// End of DEBUG
}
// Open signature file
public System.Drawing.Image ReadFile(string filename, string password)
{
byte[] encrypted = File.ReadAllBytes(filename);
byte[] decrypted = Signatures.Encryption.Decrypt(encrypted, password);
Image image = bytearrayToImage(decrypted);
return image;
}
// Convert image to bytearray
private byte[] imgToByteArray(Image img)
{
using (MemoryStream ms = new MemoryStream())
{
img.Save(ms, ImageFormat.Png);
return ms.ToArray();
}
}
// Convert bytearray to image
private Image bytearrayToImage(byte[] bytearray)
{
using (MemoryStream ms = new MemoryStream(bytearray))
{
return Image.FromStream(ms);
}
}
Signatures.Encryption:
public static byte[] Encrypt(byte[] input, string password)
{
byte[] output;
PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, new byte[] { 0x43, 0x87, 0x23, 0x72 });
Aes aes = new AesManaged();
aes.Padding = PaddingMode.PKCS7;
aes.KeySize = 256;
aes.Key = pdb.GetBytes(aes.KeySize / 8);
aes.IV = pdb.GetBytes(aes.BlockSize / 8);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(input, 0, input.Length);
}
output = ms.ToArray();
}
return output;
}
public static byte[] Decrypt(byte[] input, string password)
{
byte[] output;
PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, new byte[] { 0x43, 0x87, 0x23, 0x72 });
Aes aes = new AesManaged();
aes.Padding = PaddingMode.PKCS7;
aes.KeySize = 256;
aes.Key = pdb.GetBytes(aes.KeySize / 8);
aes.IV = pdb.GetBytes(aes.BlockSize / 8);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(input, 0, input.Length);
}
output = ms.ToArray();
}
return output;
}
Using PaddingMode.PKCS7
generates exception:
+ Thrown: "Padding is invalid and cannot be removed." (System.Security.Cryptography.CryptographicException) Exception Message = "Padding is invalid and cannot be removed.", Exception Type = "System.Security.Cryptography.CryptographicException", Exception WinRT Data = null
and PaddingMode.Zeros
generates exception:
+ Thrown: "Parameter is not valid." (System.ArgumentException) Exception Message = "Parameter is not valid.", Exception Type = "System.ArgumentException", Exception WinRT Data = null
I think that the Parameter is not valid.
exception is generated because the image isn't valid (because of higher decryption byte lenght), the CompareBytes(byte[] first, byte[] second)
gives false
on all these cases.
EDIT: I just found out that one NULL byte is being added to the end of encrypted/decrypted file.
EDIT2: The NULL byte gets added when encrypting. Removing it doesn't do much, the Image.FromStream();
still throws "Parameter is not valid.".