Reputation: 31
I'm trying to encrypt XML, and after decryption I end up with 1 byte too many - probably because of padding. This is my code. How can I change this to make it work?
public byte[] encryptData(byte[] source,string key)
{
byte[] btKeyInBytes = UTF8Encoding.UTF8.GetBytes(key);
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, btKeyInBytes);
AesManaged encryptor = new AesManaged();
encryptor.Padding = PaddingMode.Zeros;
using (MemoryStream encryptStream = new MemoryStream())
{
using (CryptoStream encStream = new CryptoStream(encryptStream, encryptor.CreateEncryptor(rfc.GetBytes(16), rfc.GetBytes(16)), CryptoStreamMode.Read))
{
//Read from the input stream, then encrypt and write to the output stream.
encStream.Write(source, 0, source.Length);
encStream.FlushFinalBlock();
encryptor.Clear();
}
encryptStream.Flush();
encryptedSource = encryptStream.ToArray();
}
return encryptedSource;
}
public byte[] decryptData(byte[] source, string key)
{
byte[] encryptedSource = null;
byte[] btKeyInBytes = UTF8Encoding.UTF8.GetBytes(key);
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, btKeyInBytes);
AesManaged encryptor = new AesManaged();
encryptor.Padding = PaddingMode.Zeros;
using (MemoryStream encryptStream = new MemoryStream())
{
using (CryptoStream encStream = new CryptoStream(encryptStream, encryptor.CreateDecryptor(rfc.GetBytes(16), rfc.GetBytes(16)), CryptoStreamMode.Write))
{
//Read from the input stream, then encrypt and write to the output stream.
encStream.Write(source, 0, source.Length);
encStream.FlushFinalBlock();
encryptor.Clear();
}
encryptStream.Flush();
encryptedSource = encryptStream.ToArray();
}
return encryptedSource;
}
It seems that the padding gives me 1 extra byte during decryption
Upvotes: 2
Views: 351
Reputation: 31
I got it!
Now let's try to explain.
Let's say I have a file of 927 bytes.
What I do is to read this file and split it in pieces of 656 bytes. This byte array of 656 bytes is being encrypted. The second array will be 271 bytes.
In every block for encryption I used padding. When decrypting, you will not be able to know in which block padding was used because every block now can be divided by 16 (because of the padding in the encryption). Basically I only want padding used for the last block(271).
so this is my new code:
public byte[] encryptData(byte[] source, string key, bool padding)
{
byte[] encryptedSource = null;
byte[] btKeyInBytes = UTF8Encoding.UTF8.GetBytes(key);
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, btKeyInBytes);
AesManaged encryptor = new AesManaged();
//encryptor.Mode = CipherMode.CFB;
encryptor.KeySize = 128; // in bits
encryptor.Key = new byte[128 / 8]; // 16 bytes for 128 bit encryption
encryptor.IV = new byte[128 / 8];
if (padding) { encryptor.Padding = PaddingMode.PKCS7; }
else { encryptor.Padding = PaddingMode.None; }
using (MemoryStream encryptStream = new MemoryStream())
{
using (CryptoStream encStream =
new CryptoStream(encryptStream,
encryptor.CreateEncryptor(rfc.GetBytes(16),
rfc.GetBytes(16)),
CryptoStreamMode.Write))
{
//Read from the input stream, then encrypt and write to the output stream.
encStream.Write(source, 0, source.Length);
}
encryptStream.Flush();
encryptedSource = encryptStream.ToArray();
}
return encryptedSource;
}
public byte[] decryptData(byte[] source, string key,bool padding)
{
byte[] encryptedSource = null;
byte[] btKeyInBytes = UTF8Encoding.UTF8.GetBytes(key);
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, btKeyInBytes);
AesManaged encryptor = new AesManaged();
encryptor.Key = new byte[128 / 8]; // 16 bytes for 128 bit encryption
encryptor.IV = new byte[128 / 8];
if (padding) { encryptor.Padding = PaddingMode.PKCS7; }
else { encryptor.Padding = PaddingMode.None; }
using (MemoryStream encryptStream = new MemoryStream())
{
using (CryptoStream encStream =
new CryptoStream(encryptStream,
encryptor.CreateDecryptor(rfc.GetBytes(16),
rfc.GetBytes(16)),
CryptoStreamMode.Write))
{
//Read from the input stream, then encrypt and write to the output stream.
encStream.Write(source, 0, source.Length);
}
encryptStream.Flush();
encryptedSource = encryptStream.ToArray();
}
return encryptedSource;
}
I hope this helps!
Upvotes: 1
Reputation: 15685
If your problem is padding, then PaddingMode.Zeros
is about the worst choice, since zeros cannot always be reliably removed. Better to use PKCS7 padding.
It is also possible that the encoding of end-of-line has changed between systems. Some systems use a single byte while other systems use two bytes. You really need to look at exactly what is in the decrypted file, byte by byte, as @Rup suggests.
Upvotes: 1