Pipelining

From Crypto++ Wiki

Jump to: navigation, search

Chain.png

Pipelining is a paradigm in Crypto++ which allows data to flow from a source to a sink. As data flows, the data will encounter filters which transforms the data in some way in route to the sink. The motivation for the design was the Unix pipe system, so a Crypto++ pipeline has very close analogies to a Unix command line.

For example, consider a set of commands to Base64 encode a file and then saves the encoding to a second file:

cat filename | base64 > filename.b64

The Crypto++ pipeline to accomplish the same would be:

FileSource f(filename, new Base64Encoder(new FileSink(filename + ".b64")));

Generalizing the pipeline would be:

Source(source, new Filter(new Filter(new Sink(destination))));

The Annotated Class Reference includes documentation for the Source interface and Sink interface.

All filters inherit from BufferedTransformation. With respect to BufferedTransformations, intermediate objects of interest are:

With respect to Filters, objects of interest are:

Generally, a user defined filter will derive from class Filter. Wei Dai recommends examining SignerFilter in filters.h for a filter example.

[edit] Sample Program

The following program transfers data from the first string to the second string. Though not very useful, it is the simplest demonstration of pipelining. An important reminder (from the ReadMe) is that the StringSource, which takes a pointer to the StringSink, owns the StringSink. So the StringSource will delete the StringSink when the StringSource destructor is invoked.

string s1 = "Pipeline", s2;

StringSource( s1, new StringSink( s2 ) );

cout << "s1: " << s1 << endl;
cout << "s2: " << s2 << endl;

The following program uses an AutoSeededRandomPool to generate an AES key. The key is hex encoded and then printed.

AutoSeededRandomPool prng;

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

string encoded;

StringSource( key, key.size(), true,
    new HexEncoder(
        new StringSink( encoded )
    ) // HexEncoder
); // StringSource

cout << "key: " << encoded << endl;

At times, a result is required from an intermediate object that is participating in a pipeline. Most notably is the DecodingResult from a HashVerificationFilter. In this situation, we do not want the filter to own the object and attempt to destroy it. To accomplish the goal, a Redirector would be used. Notice that the Redirector takes a reference to an object, and not a pointer to an object.

CCM< AES, TAG_SIZE >::Decryption d;
d.SetKeyWithIV( key, key.size(), iv, sizeof(iv) );
...

AuthenticatedDecryptionFilter df( d,
    new StringSink( recovered )
); // AuthenticatedDecryptionFilter

// Cipher text includes the MAC tag
StringSource( cipher, true,
    new Redirector( df )
); // StringSource

// If the object does not throw, here's the only
//  opportunity to check the data's integrity
bool b = df.GetLastResult();

if( true == b ) {
    cout << recovered << endl;
}
Personal tools