I'm trying to encrypt my data with AES algorithm with CBC mode. For this reason I use .Net Library 'Bouncy Castle'. I have not a background in crypto, so I'm trying to use it in a straightforward way. Here is my encrypt code
public byte[] encrypt(byte[] key, byte[] iv,byte[] data)
{
IBlockCipher engine=new AesFastEngine();
KeyParameter keyParam = new KeyParameter(key);
CbcBlockCipher cipher = new CbcBlockCipher(engine);
ICipherParameters parameters = new ParametersWithIV(keyParam, iv);
byte[] output=new byte[16+data.Length];
cipher.Init(true, parameters);
cipher.ProcessBlock(data, 0, output, data.Length);
//process output
byte[] cipherArray = new byte[data.Length];
/*
int k=0;
for (int i = 0; i < output.Length; i++)
{
if (output[i]!= 0)
{
cipherArray[k++] = output[i];
}
}
*/
return cipherArray;
}
When I try an input that is not a multiply of 16, I get an exception. When I pad the array to the right with a number of (16-length%16) with zeros on the left, I can get a result. But the result is a problem for me as well. It gives me a result like this:
[0][0][0][0[111][22][33][44][66][77][33][12][32][23][0][0][0][0][0]
zeros on the both left and right.
I thought it may be about my use of ProcessBlock(data, 0, output, data.Length)
function. I use it with the assumption that output will be my ciphered text, but it seems that output should be longer than the input length. since I don't have a documentation about this function, I may be using it in a wrong way. Any help would be appreciated
In cryptography, padding is any of a number of distinct practices which all include adding data to the beginning, middle, or end of a message prior to encryption.
What is padding? Block cipher algorithms like AES and Triple DES in Electronic Code Book (ECB) and Cipher Block Chaining (CBC) mode require their input to be an exact multiple of the block size. If the plaintext to be encrypted is not an exact multiple, you need to pad before encrypting by adding a padding string .
PKCS7 padding is a generalization of PKCS5 padding (also known as standard padding). PKCS7 padding works by appending N bytes with the value of chr(N) , where N is the number of bytes required to make the final block of data the same size as the block size.
When you specify PKCS7, BC will add the padding to the data before encrypting, and remove it again when decrypting. PKCS7 with AES would always add at least 1 byte of padding, and will add enough data to make the input a multiple of the AES block size.
Bouncy Castle will do the padding for you, to start you need to set up your cihper as:
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
For the rest of your code to work would need to use cipher.GetOutputSize(data.Length)
ProcessBytes
,and DoFinal
so the padding is added correctly.
byte[] output = new byte[cipher.GetOutputSize(data.Length)];
int len = cipher.ProcessBytes(data, 0, data.Length, output, 0);
cipher.DoFinal(output, len);
I have a simple example on of using AES-GCM in Bouncy Castle on CodeReview
AES-GCM adds authenticated encryption, but the basic principle of using the api is the same.
I also have a C# port of high level encryption framework, Kecyzar, that I used Bouncy Castle as the backend, although it's a harder example, the abstracted encryption code SymmetricStream is setup for using AES-CBC in BouncyAesKey
Typically one would use a standard padding algorithm to ensure that plaintext data is aligned with the block-size for a cipher.
You are currently hand-coding zero padding. This is not a great choice as it forbids the original data ending in a zero byte - how can you distinguish that from the padding?
I would recommend you use a standard padding, such as PKCS #7 padding. Note that this is often referred to as "PKCS #5 padding", as they are very similar.
You may wish to refer to this other SO question - Encrypt/Decrypt using Bouncy Castle in C# - for an example of using standard padding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With