Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to pad data before encryption with Bouncy Castle

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

like image 295
ikbal Avatar asked Nov 13 '12 08:11

ikbal


People also ask

What is padding in encryption?

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.

Which encryption modes need padding?

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 .

What is PKCS7 padding?

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.

How do you use PKCS 7 padding?

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.


2 Answers

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

like image 152
jbtule Avatar answered Oct 17 '22 06:10

jbtule


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.

like image 30
Duncan Jones Avatar answered Oct 17 '22 08:10

Duncan Jones