Crypto++ provides 5 sinks for the most common objects. A StringSink requires no additional information to terminate the data chain. Other objects, such as FileSinks require additional information such as a filename.
Private keys and other sensitive material should not be saved to a string using a StringSink. Many code samples and snippets use StringSink and string to hold the sensitive material. Though convenient, the practice is not a very good idea - see Keys and Formats for details.
Sinks are very easy to create: implement a class which inherits from Redirector and provide an appropriate typed constructor.
The following example demonstrates the creation of a StringSink.
string s; StringSink sink( s );
The following example demonstrates reading a file, and placing the contents of the file in a string. This is known as pipelining.
string s; FileSource file( filename, new StringSink( s ) ); cout << s << endl;
The following example performs the same operation as above, but without the variable file.
string s; FileSource( filename, true, new StringSink( s ) ); cout << s << endl;
string s; FileSource( filename, new HexEncoder( new StringSink( s ) ) ); cout << s << endl;
Note that the HexEncoder and StringSink created with new do not require explicit destruction - the FileSource will call delete on the HexEncoder, which in turns calls delete on the StringSink when it (the FileSource) is destroyed.
Finally, the example below places 4 random bytes of data into a StringSink after hex encoding using a random number source. As the chain gets longer, nesting the chaining structure as with if statements offers better readability.
string s; AutoSeededRandomPool rng; RandomNumberSource( rng, 4, true, new HexEncoder( new CryptoPP::StringSink( s ) ) // HexEncoder ); // RandomNumberSource
With the type formatting in place, data flow through the construct is easily traceable.