Redirector

From Crypto++ Wiki
Jump to navigation Jump to search
Redirector
Documentation
#include <cryptopp/filters.h>

A Redirector is a sink that does not own its attached transformation. A Redirector will end an ownership chain, but still pass the data it receives to its referenced filter (the word attached was avoided in this particular case). Because the Redirector does not ultimately own the attached transformation, a BufferedTransformation reference is passed to the constructor rather than a pointer.

There are two applications of the Redirector. First is to configure an intermediate object participating in a pipeline. For example, you would need a Redirector to configure an encoder to disable padding. Second is to facilitate the retrieval of a result from an intermediate object that is participating in a pipeline. Most notable are the results from a HashVerificationFilter, SignatureVerificationFilter or AuthenticatedDecryptionFilter.

Sources, filters and sinks are discussed at Pipelining. The pipeline article explains the design and shows you how to use them.

Constructor

There are two constructors available for a Redirector since it is not possible to overload the constructor with a NULL reference.

Redirector()

Initializes the Redirector with a NULL BufferedTransformation and default Behavior flags. The default flags is PASS_EVERYTHING. This behavior is some what unique among filters in that most filters, when presented with a NULL attachment, will create a MessageQueue for internal use.

Redirector(BufferedTransformation &target, Behavior behavior=PASS_EVERYTHING)

target is a BufferedTransformation, such as another filter or sink.

behavior controls the Redirector's behavior for passing data and signals. It can be a combination of the following:

  • DATA_ONLY (0x00)
  • PASS_SIGNALS (0x01)
  • PASS_WAIT_OBJECTS (0x02)
  • PASS_EVERYTHING (PASS_SIGNALS | PASS_WAIT_OBJECTS)

Sample Programs

The following two sample programs show how to configure an object used in a pipeline; and how to retrieve an intermediate result from an object in a pipeline.

Configuration

The first example uses a Redirector in a pipeline to allow for configuration options not available in a constructor. A Base64Encoder does not allow a library user to specify padding, so it must be done through IsolatedInitialize.

using CryptoPP::Name::Pad;
using CryptoPP::Name::InsertLineBreaks;

byte raw[] = {
    0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
    0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
    0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
    0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
    0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
    0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
    0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
    0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 };

string encoded, hexed;
Base64Encoder encoder;

AlgorithmParameters params = MakeParameters(Pad(), false)(InsertLineBreaks(), false);
encoder.IsolatedInitialize(params);
encoder.Attach(new StringSink( encoded ));

ArraySource as(raw, sizeof(raw), true, new Redirector(encoder));
cout << encoded << endl;

StringSource ss(encoded, true, new Base64Decoder(new HexEncoder(new StringSink(hexed))));
cout << hexed << endl;

A run of the program produces the following:

$ ./cryptopp-test.exe
/+7dzLuqmYh3ZlVEMyIRAP/u3cy7qpmId2ZVRDMiEQD/7t3Mu6qZiHdmVUQzIhEA/+7dzLuqmYh3ZlVEMyIRAA
FFEEDDCCBBAA99887766554433221100FFEEDDCCBBAA99887766554433221100FFEEDDCCBBAA99887766554433221100FFEEDDCCBBAA99887766554433221100

For a more complete discussion of the example, see NameValuePairs.

Intermediate Result

In the second example below, the Redirector takes a reference to an object, and not a pointer to an object. The AuthenticatedDecryptionFilter will survive to the result to be fetched.

const int TAG_SIZE = 12;
CCM< AES, TAG_SIZE >::Decryption dec;
dec.SetKeyWithIV( key, sizeof(key), iv, sizeof(iv) );
...

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

// Cipher text includes the MAC tag
StringSource ss( 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;
}