What is the difference between FileSink, StringSin

2019-08-02 14:36发布

问题:

I am reading in an image, encrypting it, then decrypting it. The goal is to be looping this eventually and recording the time it takes for the process to complete. Currently what I have it reads the file in, then it encrypts it, encrypts it, the creates another file based on the recovered data. I don't need to make another file with the decrypted picture. Previously I had been using StringSource and StringSink, but that only worked for text files. I received some help at How to read an image to a string for encrypting Crypto++ from and started using FileSink and FileSource.

What exactly is the difference between FileSink, StringSink, FileSource and StringSource ?

Also, in following example, why does cipher need to be set to something? Previously when I was just using StringSource, my string cipher was not initialized, but now that I am using FileSource, it needs to be initialized for it to work.

int main(int argc, char* argv[])
{
    AutoSeededRandomPool prng_blowfish;

    SecByteBlock key_blowfish(Blowfish::DEFAULT_KEYLENGTH);
    prng_blowfish.GenerateBlock(key_blowfish, key_blowfish.size());

    byte iv_blowfish[Blowfish::BLOCKSIZE];
    prng_blowfish.GenerateBlock(iv_blowfish, sizeof(iv_blowfish));

    string ifilename = "sample_files/1MB.jpg";
    string cipher = "1MB.enc";
    string rfilename = "r1MB.jpg";

    try
    {
        EAX<Blowfish>::Encryption e_blowfish;
        e_blowfish.SetKeyWithIV(key_blowfish, key_blowfish.size(), iv_blowfish, sizeof(iv_blowfish));

        std::ifstream ifile(ifilename.c_str(), ios::binary);
        std::ifstream::pos_type size = ifile.seekg(0, std::ios_base::end).tellg();
        ifile.seekg(0, std::ios_base::beg);

        FileSource fs1(ifilename.c_str(), true, new AuthenticatedEncryptionFilter(e_blowfish, new FileSink(cipher.c_str())));

        EAX<Blowfish>::Decryption d_blowfish;
        d_blowfish.SetKeyWithIV(key_blowfish, key_blowfish.size(), iv_blowfish, sizeof(iv_blowfish));

        FileSource fs2(cipher.c_str(), true, new AuthenticatedDecryptionFilter(d_blowfish, new FileSink(rfilename.c_str()), AuthenticatedDecryptionFilter::THROW_EXCEPTION));
    }
    catch (const Exception& ex)
    {
        cerr << ex.what() << endl;
    }

    return 0;
}

回答1:

What exactly is the difference between FileSink, StringSink, FileSourcem StringSource.

Sources, Filters and Sinks are part of the Pipeline design in Crypto++. Data flows from a source, is transformed by filters, and then ends at a sink.

All sources are interchangeable. All filters are interchangeable. And all sinks are interchangeable. For example, to switch between a StringSink and FileSink, you need to supply a filename with a FileSink. Otherwise, they operate the same. As another example, you can switch between a HexEncoder and Base64Encoder with no changes. As a final example, a SocketSource or SocketSink are going to need an IP address and port. What may (or may not) need to be changed depends on the object.

There are a number of sources. From Source Class Reference:

  • FileSource
  • StringSource
  • RandomNumberSource
  • WindowPipeSource
  • SocketSource

There are a number of filters. You are using two of them - AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter. From Filter Class Reference and FilterWithBufferedInput Class Reference:

  • HexEncoder
  • HexEncoder
  • Base32Encoder
  • Base32Decoder
  • Base64Encoder
  • Base64Encoder
  • DefaultEncryptor
  • DefaultEncryptorWithMAC
  • DefaultDecryptor
  • DefaultDecryptorWithMAC
  • ...
  • StreamTransformationFilter
  • AuthenticatedEncryptionFilter
  • AuthenticatedDecryptionFilter

There are a number of sinks. From Sink Class Reference:

  • ArraySink
  • BitBucket
  • RandomNumberSink
  • StringSink
  • FileSink
  • SocketSink
  • ...

There are some advanced topics, but I don't think they matter at the moment. For example, the role of BufferedTransformation and what it means if Attachable returns true. The answer is both Filters and Sinks are BufferedTransformation's, and Attachable = true means its a Filter (otherwise its a Sink).


... in following example, why does cipher need to be set to something...

A StringSource and StringSink needs nothing because its just an array of byes in memory. A FileSource and FileSink needs a filename, and you are using cipher for the filename. You have to supply a filename because the objects a file/stream related. If you were using a SocketSource or SocketSink, then you would need to supply an IP address and port (more correctly, a socket_t).

Here are the FileSource constructors from FileSource Class Reference. You are using the third constructor in your code.

FileSource (BufferedTransformation *attachment=NULL)
FileSource (std::istream &in, bool pumpAll, BufferedTransformation *attachment=NULL)
FileSource (const char *filename, bool pumpAll, BufferedTransformation *attachment=NULL, bool binary=true)

Here are the FileSink constructors from FileSink Class Reference. You are using the second constructor in your code.

FileSink (std::ostream &out)
FileSink (const char *filename, bool binary=true)