ChannelSwitch

From Crypto++ Wiki
Jump to: navigation, search

The ChannelSwitch allows you to process data in parallel by pumping it to multiple filters or sinks. It also allows you to combine multiple inputs into a single output through the use of named channels.

ChannelSwitch
Documentation
#include <cryptopp/channels.h>

Construction

ChannelSwitch ()
ChannelSwitch (BufferedTransformation &destination)
ChannelSwitch (BufferedTransformation &destination, const std::string &outChannel)

destination is a BufferedTransformation, such as another filter or sink. Note: unlike many filters and sinks, the ChannelSwitch takes a reference and not a pointer.

outChannel is the name of the channel to use when pipelining data to the destination. Use this contructor if you don't want to use DEFAULT_CHANNEL.

Example

Below are two examples of using a ChannelSwitch. The first pumps string data to four hashes, and the second performs SSH-style authenticated encryption. SSH-style authenticated encryption is known as Encrypt-and-Authenticate (E&A). In general, you should avoid this style of authenticated encryption.

Multiple Hashes

The example below pumps string data to four hashes and then outputs the results.

#include <iostream>
#include <cstring>
#include <cryptopp/channels.h> 
#include <cryptopp/filters.h> 
#include <cryptopp/sha.h> 
#include <cryptopp/hex.h>

int main(int argc, char *argv[]) {
std::string message = "Now is the time for all good men to come to the aide of their country";

// Allow user to override default message from command line arg.
if(argc == 2 && argv[1] != NULL) 
    message = std::string(argv[1]);

// Set hash variables
std::string s1, s2, s3, s4;
CryptoPP::SHA1 sha1; CryptoPP::SHA224 sha224; CryptoPP::SHA256 sha256; CryptoPP::SHA512 sha512;

// Run hash functions
CryptoPP::HashFilter f1(sha1, new CryptoPP::HexEncoder(new CryptoPP::StringSink(s1)));
CryptoPP::HashFilter f2(sha224, new CryptoPP::HexEncoder(new CryptoPP::StringSink(s2)));
CryptoPP::HashFilter f3(sha256, new CryptoPP::HexEncoder(new CryptoPP::StringSink(s3)));
CryptoPP::HashFilter f4(sha512, new CryptoPP::HexEncoder(new CryptoPP::StringSink(s4)));

// Set route to default
CryptoPP::ChannelSwitch cs;
cs.AddDefaultRoute(f1);
cs.AddDefaultRoute(f2);
cs.AddDefaultRoute(f3);
cs.AddDefaultRoute(f4);

CryptoPP::StringSource ss(message, true /*pumpAll*/, new CryptoPP::Redirector(cs));

std::cout << "Message: " << message << std::endl;
std::cout << "SHA-1: " << s1 << std::endl;
std::cout << "SHA-224: " << s2 << std::endl;
std::cout << "SHA-256: " << s3 << std::endl;
std::cout << "SHA-512: " << s4 << std::endl;
}

A run of the program produces the results shown below:

$ ./cryptopp-test.exe password
Message: password
SHA-1: 5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8
SHA-224: D63DC919E201D7BC4C825630D2CF25FDC93D4B2F0D46706D29038D01
SHA-256: 5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8
SHA-512: B109F3BBBC244EB82441917ED06D618B9008DD09B3BEFD1B5E07394C706A8BB9
         80B1D7785E5976EC049B46DF5F1326AF5A2EA6D103FD07C95385FFAB0CACBC86

SSH-style AuthEnc

The example below performs SSH-style authenticated encryption and then outputs the results. In general, you should avoid this style of authenticated encryption because its provably insecure.

// Message to encrypt and authenticate
string message = "Now is the time for all good men to come to the aide of their country";
if(argc == 2 && argv[1] != NULL)
    message = string(argv[1]);

// Setup Keys and IV
SecByteBlock ekey(16), iv(16), hkey(16);
memset(ekey, 0x00, ekey.size());
memset(iv, 0x00, iv.size());
memset(hkey, 0x00, hkey.size());

// Print Keys and IV
HexEncoder encoder(new FileSink(cout));

cout << "Encryption key: ";
encoder.Put(ekey, ekey.size());
encoder.MessageEnd(); cout << endl;

cout << "Encryption iv: ";
encoder.Put(iv, iv.size());
encoder.MessageEnd(); cout << endl;

cout << "HMAC key: ";
encoder.Put(hkey, hkey.size());
encoder.MessageEnd(); cout << endl;

// Setup and key objects
string s1, s2;
HMAC<SHA256> hmac;
CBC_Mode<AES>::Encryption encryptor;

encryptor.SetKeyWithIV(ekey, ekey.size(), iv, iv.size());
hmac.SetKey(hkey, hkey.size());

// Create filters
StreamTransformationFilter ef(encryptor, new HexEncoder(new StringSink(s1)));
HashFilter hf(hmac, new HexEncoder(new StringSink(s2)));

// Encrypt and authenticate message
ChannelSwitch cs;
cs.AddDefaultRoute(ef);
cs.AddDefaultRoute(hf);

StringSource ss(message, true /*pumpAll*/, new Redirector(cs));

// Print stuff
cout << "Message: " << message << endl;
cout << "MAC of Message: " << s2 << endl;
cout << "Cipher text: " << s1 << endl;

A typical run is shown below.

$ ./cryptopp-test.exe
Encryption key: 00000000000000000000000000000000
Encryption iv: 00000000000000000000000000000000
HMAC key: 00000000000000000000000000000000
Message: Now is the time for all good men to come to the aide of their country
MAC of Message: E1396F07CE04D528152443C773E4A20F51AA1AB007F859943225D8F500EAF057
Ciphertext: 7FF8B3EA8A02B37A3D28669C9713A7B30FA2502580D5D232CEE80A5733EF70FF48E9
            E80498A904C25EA7B04043A1FC238B03AA06EC90498478FB29013EE7DE6B9E37B03B
            F7FA2609CE7E48B460BE36AA

Sample

ChannelSwitch.zip - Demonstrates using the ChannelSwitch class to digest a string using multiple hashes - 7.9 kB