ChannelSwitch

From Crypto++ Wiki
Jump to navigation Jump to 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.

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

Note: unlike many filters and sinks, the ChannelSwitch takes a reference and not a pointer. Since ChannelSwitch takes a reference, the caller owns the destination object. The caller is responsible for destroying the destination. Also see ownership on the Crypto++ wiki.

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[])
{
   using namespace CryptoPP;

   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;
   SHA1 sha1; SHA224 sha224; SHA256 sha256; SHA512 sha512;

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

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

   StringSource ss(message, true /*pumpAll*/, new 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. The SSH-style is Authenticate-then-Encrypt (AtE). 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