ArraySink
Documentation |
#include <cryptopp/filters.h>
|
An ArraySink, introduced in version 5.6 of Crypto++, is a sink for byte arrays. An ArraySink is typedef'd from a StringSink's third constructor. Prior to version 5.6 of the library, use a StringSink.
An ArraySink
functions like any other sinks in the library, including a FileSink and StringSink. However, since an array is fixed size, the ArraySink
will effectively discard data once the array is full. The sink will signal the array is full by returning non-0 after a call to Put
or Put2
. Also see How to use Shamir's Secret Sharing to securely divide in memory byte blobs and then disperse the shares over network on the Crypto++ mailing list.
Sources, filters and sinks are discussed at Pipelining. The pipeline article explains the design and shows you how to use them.
Constructor
ArraySink (byte *buffer, size_t size)
buffer
is a byte array.
size
is the length of the byte array.
Sample Programs
Below is an example of storing Adler32 digest in a std::array
using a pipeline.
Adler32 hash; std::array<byte, Adler32::DIGESTSIZE> output; StringSource ss("Wikipedia", true, new HashFilter( hash, new ArraySink(output.data(), Adler32::DIGESTSIZE) ) ); for(auto &it: output) { std::cout << std::hex << (int)it << " "; }
The output is shown below.
11 E6 03 98
If you overcommit the size of the array, then you can get the size of the bytes written to the array with the following. Notice three things. First, a stack based ArraySink
was used. Second, TotalPutLength
was used to determine how many bytes were written to the array. Third, a Redirector
was used to stop ownership so the ArraySink
would survive to allow the call to TotalPutLength
.
Adler32 hash; byte output[1024]; ArraySink as(output, sizeof(output)); StringSource ss("Wikipedia", true, new HashFilter( hash, new Redirector(as) ) ); for(size_t i = 0; i < as.TotalPutLength(); i++) { std::cout << std::hex << (int)output[i] << " "; }
Below is another example of using ArraySource and ArraySink in a pipeline. The Redirector ensures the ArraySink survives so you can call TotalPutLength
.
#include <iostream> #include <string> using namespace std; #include "cryptlib.h" #include "filters.h" #include "files.h" #include "modes.h" #include "hex.h" #include "aes.h" using namespace CryptoPP; int main(int argc, char* argv[]) { byte key[AES::MAX_KEYLENGTH]; byte iv[AES::BLOCKSIZE]; vector<byte> plain, cipher, recover; HexEncoder encoder(new FileSink(cout)); memset(key, 0x00, sizeof(key)); memset(iv, 0x00, sizeof(iv)); string str("Attack at dawn!"); std::copy(str.begin(), str.end(), std::back_inserter(plain)); cout << "Plain text: "; encoder.Put(plain.data(), plain.size()); encoder.MessageEnd(); cout << endl; ///////////////////////////////////////////////////////////// CBC_Mode<AES>::Encryption enc; enc.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv)); // Make room for padding cipher.resize(plain.size()+AES::BLOCKSIZE); ArraySink cs(&cipher[0], cipher.size()); ArraySource(plain.data(), plain.size(), true, new StreamTransformationFilter(enc, new Redirector(cs))); // Set cipher text length now that its known cipher.resize(cs.TotalPutLength()); cout << "Cipher text: "; encoder.Put(cipher.data(), cipher.size()); encoder.MessageEnd(); cout << endl; ///////////////////////////////////////////////////////////// CBC_Mode<AES>::Decryption dec; dec.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv)); // Recovered text will be less than cipher text recover.resize(cipher.size()); ArraySink rs(&recover[0], recover.size()); ArraySource(cipher.data(), cipher.size(), true, new StreamTransformationFilter(dec, new Redirector(rs))); // Set recovered text length now that its known recover.resize(rs.TotalPutLength()); cout << "Recovered text: "; encoder.Put(recover.data(), recover.size()); encoder.MessageEnd(); cout << endl; return 0; }