6

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

ikbal
  • 1,844
  • 4
  • 26
  • 46

2 Answers2

5

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

Community
  • 1
  • 1
jbtule
  • 31,383
  • 12
  • 95
  • 128
  • thank you jbtule, but I have a problem with this patter when I try to use paddedCipher.DoFinal(output,len); it throws an exception "last block incomplete in decription", processBytes method returns a value that is a multiplication of 16 which is smaller than data length, would you know what causes this problem? thanks – ikbal Nov 14 '12 at 10:15
  • @paskalnikov I added more code to show how to use. `ProcessBytes` is going to output bytes for every complete block and keep the rest buffered (you can also call `ProcessBytes` as many times as you want giving it a portion of data at a time), it's not going to assume you are finished until you call `DoFinal`, and then `DoFinal` will write out the last bytes (with padding), so if you have `DoFinal` write to your final output array you need to give it the index of where it should write to in the array. – jbtule Nov 14 '12 at 14:02
3

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.

Community
  • 1
  • 1
Duncan Jones
  • 67,400
  • 29
  • 193
  • 254