Wednesday, April 2, 2008

open ssl crypto library sample code

Recently I had the need to code some crypto stuff on C ( doing my undergrad thesis), so i set off to find a good library, went through a few of them , but they all had the same thing in common : hard to read documentation, and almost no sample code to view ( the little sample code that there was, was very badly commented).

After about 6 days I finally understood how to use openssl s crypto library to encrypt and decrypt using blowfish algorithm, so I though i d open this blog and put it out there.... maybe i ll save someone some time.

Background info on blowfish : symmetric cipher, 8 byte block size ( 64bits), usually with a 128bit key.

i ll first explain how it works, then paste the documentation which I reordered to get a better view, as I found it very confusing the way it was explained in the oficial site ( maybe its just me).


Context : initial state of cipher, since these functions are interfaces to lower lvl functions, you have to initiate a context in order to tell the libraries what to do.

int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, unsigned char *in, int inl):

this function does 99% of the encryption, basically since bf is a block cipher there is padding at the end of a non-aligned block, so this will encrypt in, and put it in out, the quantity of bytes encripted ( written in out) will be placed in outl. Now it will encrypt inl number of bytes from in, but it will not encrypt the last bytes that don't fill up a whole block. For instance, lets say the block size is 8, and you have to encrypt 22 , the function is called like this : EVP_EncryptUpdate(ctx,out,outl,in,22)
it will actually encrypt 16 bytes ( 2 blocks) and leave a 6 byte block behind, outl will have 16 in it. How do you encript the last block ( which by the way has to be padded) :
EVP_EncryptFinal_ex(ctx,out+outl,tmpcounter);

this is just : encrypt last block with ctx, you will put it in out buffer but at outl offset ( so not to overwrite previous decryption, and the new quantity of bytes encrypted is tmpcounter.

At last outl + tmpcounter have the total bytes encripted, and out has the crypted text.

decription is the same but done backwards.

Hope this helps, leave a comment if it did, or leave it anyway.

This is how I understood it, if there is somekind of error in my explanation, please msg me so i ll correct it.

Some sample code I made ( adapted from link above) here.






Main functions :
void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);

creates the context.

int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, unsigned char *key, unsigned char *iv);

EVP_EncryptInit_ex() sets up cipher context ctx for encryption with cipher type from ENGINE impl. ctx must be initialized before calling this function. type is normally supplied by a function such as EVP_des_cbc(). If impl is NULL then the default implementation is used. key is the symmetric key to use and iv is the IV to use (if necessary), the actual number of bytes used for the key and IV depends on the cipher. It is possible to set all parameters to NULL except type in an initial call and supply the remaining parameters in subsequent calls, all of which have type set to NULL. This is done when the default cipher parameters are not appropriate.

int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, unsigned char *in, int inl);

EVP_EncryptUpdate() encrypts inl bytes from the buffer in and writes the encrypted version to out. This function can be called multiple times to encrypt successive blocks of data. The amount of data written depends on the block alignment of the encrypted data: as a result the amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1) so outl should contain sufficient room. The actual number of bytes written is placed in outl.

int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl);
If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts the ``final'' data, that is any data that remains in a partial block. It uses standard block padding (aka PKCS padding). The encrypted final data is written to out which should have sufficient space for one cipher block. The number of bytes written is placed in outl. After this function is called the encryption operation is finished and no further calls to EVP_EncryptUpdate() should be made.

If padding is disabled then EVP_EncryptFinal_ex() will not encrypt any more data and it will return an error if any data remains in a partial block: that is if the total data length is not a multiple of the block size.
(source).


1 comment:

Oscar Ortegano said...

Que pala eres!!! Felicitaciones jeje