Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site











SourceForge.net Logo

AES Encoder/Decoder Tutorial

These classes manage following tasks:

Maximum protection of personal data while keeping their byte representation in shared container (memory, disks, database, etc.)

Ability to work with huge amounts of data (> 4 GB) without using large memory consumption (using streaming) and without lowering overall security level

 

As a basement, OpenSSL library and AES (Rijndael) algorithms were chosen.

To works with classes, you must have OpenSSL library configured and installed under TheIDE (please look here to see how to do it).

 

SHA-2 functions reference are also included here.

 

1. Encryption

Creating cryptographically stable encryption key. Key length must be 16, 24 or 32 bytes long (128/192/256 bits accordingly). Keys with another length are not supported. Please note that some countries forbid by law using keys with certain lengths.

String key(AESRandomString(32));

NB Do not use user password as key. This will bring to nothing cryptographic strength.

 

Creating AESEncoderStream class object to start encrypting.

AESEncoderStream aesEncoder(dataSize, key);

Arguments are length of data being encoded and the key just created.

NB While encrypting data using steaming, first argument is the overall length of all data.

Object created is intended to encrypt single data stream. To encrypt another stream of data, please create another AESEncoderStream object.

If key is not supported by classes, AESEncoderStream constructor will throw an exception of (const char *) type which will contain error description.

 

Encrypting data. Putting original data into AESEncoderStream input:

String someData;

//...

aesEncoder << someData;

And getting encrypted bytes from AESEncoderStream object:

sOut << aesEncoder;

 

Streaming. AESEncoderStream class will receive any chunks of bytes until their overall length is equal to the overall data size for object (first argument in AESEncoderStream constructor). Each "putting" chunk of data into AESEncoderStream leads to encrypting it inside of object. And the memory consumption of this process matches the size of this chunk. So one may encrypt very big amounts of data dividing it into small chunks and using streamed encrytpion. Maximum supported stream length is MAX_QWORD which is VERY large number.

for (...)

{

    /*...*/

    aesEncoder << someDataXXX;

    /*...*/

    sOut << aesEncoder;

}

Each time one requests getting data from encoder, it puts out data which was not processed in the iterations before. One must also notice that encryption is made by internal chunks. This may lead to empty output data in some iterations of streamed encoding process. When object has enough input data, an outputs data chunks are generated.

The structure of output data doesn't depend on the sizes and the number of input chunks. Decrypting data with right key will always give original stream of bytes.

 

 

2. Decryption

AESDecoderStream is used for decryption. To decrypt data one must have right key. If one uses wrong key and starts decryption with AESDecoderStream, an exception of (const char *) type is thrown. An exception of the same type may also be thrown in the constructor of during the decoding process if any serious problems occur.

 

Creating AESDecoderStream object for decryption. AESDecoderStream object decrypts single data stream. To decrypt another stream of data please create another AESDecoderStream object.

AESDecoderStream aesDecoder(key);

 

Decryption. Putting enctypted bytes into AESDecoderStream input:

aesDecoder << encryptedData;

And getting original (decrypted) bytes from it:

sDecoded << aesDecoder;

One must also handle (const char *) exception if wrong key caused one.

 

Streaming. Streaming is organized in the manner of AESEncoderStream streaming. Encrypted stream is divided into chunks and put into the AESDecoderStream object input. Decrypted chunks are taken from AESDecoderStream output. One should also consider specifics of decryption algorithms which may lead to empty output in some iterations of streamed decryption process. Output data chunk is generated when enough bytes are got from input.

Determining original data size is more serious task when using streamed decryption. The truth is that one may determine original data size only after certain decryption stage when AESDecoderStream object has enough input bytes to decrypt the header. So GetSize() member function returns zero input data size until header is decrypted. For that reason one may check this size with precaution:

if (!aesDecoder.GetSize())

{ //still no answer...

}

else

{//now I know original data size!

}

Once should also notice an exception is thrown (see above) on the stage (streamed decryption cycle iteration) when header is just decrypted and the original key is compared to the one that is set for AESDecoderStream. The original key is not contained in the encrypted data in any kind.

Streamed decryption process is close to the streamed encryption:

for (...)

{

    /*...*/

    aesDecoder << encryptedDataXXX;

    /*...*/

    sOut << aesDecoder;

}

 

 

3. Remarks

In the current version of package and OpenSSL, encrypted data size is bigger than the original one as 32 bytes with regard to 16-byte alignment of original data. E.g., original data size is 170 bytes. The encrypted data size is calculated as:

170 aligned to 16 byte chunks = 176

+

32 bytes

= 208 bytes.

 

 

4. Known issues

OpenSSL fails to compile with gcc/MSYS under Windows as static library.

 

If you have any information on issues or any comments, please feel free to write here.

 

Do you want to contribute?