CBC Mode

From Crypto++ Wiki
Jump to navigation Jump to search
CBC Mode
Documentation
#include <cryptopp/modes.h>

CBC Mode is cipher block chaining. CBC mode was originally specified by NIST in FIPS 81. The standard, issued in 1981, only offers confidentiality. Other modes, such as CCM and GCM, offer authenticated encryption which places an integrity assurance over the encrpyted data.

CBC requires the plain text be padded to the block size of the cipher. For additional information on this mode, see Block Cipher Modes of Operation.

Crypto++ offers several modes of operation, including ECB, CBC, OFB, CFB, CBC-CTS, CTR, XTS, CCM, EAX, GCM and OCB.

Crypto++ does not provide a way to retrieve the current IV or counter used for encryption or decryption. If you need the current IV or counter then you need to manage it yourself. Some ciphers allow you to seek a number of bytes or blocks in the stream.

If you are used to working in languages like Java or libraries like OpenSSL, then you might want to visit the Init-Update-Final wiki page. Crypto++ provides the transformation model, but its not obvious because its often shrouded behind Pipelines.

Note: if your project is using encryption alone to secure your data, encryption alone is usually not enough. Please take a moment to read Authenticated Encryption and consider using an algorithm or mode like CCM, GCM, EAX or ChaCha20Poly1305.

Sample Program

There are three sample programs for CBC mode. The samples use filters in a pipeline. Pipelining is a high level abstraction and it handles buffering input, buffering output and padding for you. The first sample shows the basic use of a pipeline. The second sample shows how to change padding. The third shows how to manually insert into a filter.

If you are benchmarking then you may want to visit Benchmarks | Sample Program . It shows you how to use StreamTransformation and its ProcessString method to process multiple blocks at a time. ProcessString eventually calls BlockTransformation and ProcessBlock. Calling a cipher's ProcessString or ProcessBlock eventually call ProcessAndXorBlock or AdvancedProcessBlocks, and they are the lowest level API you can use.

AutoSeededRandomPool prng;

SecByteBlock key(AES::DEFAULT_KEYLENGTH);
prng.GenerateBlock( key, key.size() );

byte iv[ AES::BLOCKSIZE ];
prng.GenerateBlock( iv, sizeof(iv) );

string plain = "CBC Mode Test";
string cipher, encoded, recovered;

/*********************************\
\*********************************/

try
{
    cout << "plain text: " << plain << endl;

    CBC_Mode< AES >::Encryption e;
    e.SetKeyWithIV( key, key.size(), iv );

    // The StreamTransformationFilter adds padding
    //  as required. ECB and CBC Mode must be padded
    //  to the block size of the cipher.
    StringSource ss( plain, true, 
        new StreamTransformationFilter( e,
            new StringSink( cipher )
        ) // StreamTransformationFilter      
    ); // StringSource
}
catch( const CryptoPP::Exception& e )
{
    cerr << e.what() << endl;
    exit(1);
}

/*********************************\
\*********************************/

// Pretty print cipher text
StringSource ss( cipher, true,
    new HexEncoder(
        new StringSink( encoded )
    ) // HexEncoder
); // StringSource
cout << "cipher text: " << encoded << endl;

/*********************************\
\*********************************/

try
{
    CBC_Mode< AES >::Decryption d;
    d.SetKeyWithIV( key, key.size(), iv );

    // The StreamTransformationFilter removes
    //  padding as required.
    StringSource ss( cipher, true, 
        new StreamTransformationFilter( d,
            new StringSink( recovered )
        ) // StreamTransformationFilter
    ); // StringSource

    cout << "recovered text: " << recovered << endl;
}
catch( const CryptoPP::Exception& e )
{
    cerr << e.what() << endl;
    exit(1);
}

A typical output is shown below. Note that each run will produce different results because the key and initialization vector are randomly generated.

$ ./Driver.exe 
key: B00DDF9D93E199EFEAE967805E0A5228
iv: CA8A8878F145C9B9B3C31A1F15C34A6D
plain text: CBC Mode Test
cipher text: D6AF39534926C21CFF3E7477A7146FF3
recovered text: CBC Mode Test

When using a StreamTransformationFilter, the filter will pad the plain text as required. This means 13 bytes of input will receive 3 bytes of padding (for a 128 bit block cipher). This also means 16 bytes of input will receive 16 bytes of PKCS padding, resulting in 32 bytes of cipher text. For the latter case, padding can be removed as follows.

StringSource ss( plain, true, 
    new StreamTransformationFilter( e,
        new StringSink( cipher ),
        StreamTransformationFilter::NO_PADDING
    ) // StreamTransformationFilter      
); // StringSource

To manually insert bytes into the filter, perform multiple Puts. Though Get is used below, a StringSink could easily be attached and save the administrivia.

const size_t SIZE = 16 * 4;
string plain(SIZE, 0x00);

for(size_t i = 0; i < plain.size(); i++)
    plain[i] = 'A' + (i%26);
...

CBC_Mode < AES >::Encryption encryption(key, sizeof(key), iv);
StreamTransformationFilter encryptor(encryption, NULL);

for(size_t j = 0; j < plain.size(); j++)
    encryptor.Put((byte)plain[j]);

encryptor.MessageEnd();
size_t ready = encryptor.MaxRetrievable();

string cipher(ready, 0x00);
encryptor.Get((byte*) &cipher[0], cipher.size());

Downloads

2TDEA-CBC-Filter.zip - Demonstrates encryption and decryption using 2-key TripleDES in CBC mode with filters

3TDEA-CBC-Filter.zip - Demonstrates encryption and decryption using 3-key TripleDES in CBC mode with filters

Blowfish-CBC-Filter.zip - Demonstrates encryption and decryption using Blowfish in CBC mode with filters

IDEA-CBC-Filter.zip - Demonstrates encryption and decryption using IDEA in CBC mode with filters

AES-CBC-Filter.zip - Demonstrates encryption and decryption using AES in CBC mode and filters

Serpent-CBC-Filter.zip - Demonstrates encryption and decryption using Serpent in CBC mode with filters

Camellia-CBC-Filter.zip - Demonstrates encryption and decryption using Camellia in CBC mode with filters