如何将加密的FileSource数据保存到字节数组?

时间:2016-11-19 02:46:45

标签: c++ encryption crypto++

这是用于加密大文件的Crypto ++ FileSource的代码。它的工作完美,但都在blackbox中,并且不允许我在加密时将加密数据保存到字节数组。我想知道下面的机制,以保存临时数据。该文档似乎只是在FileSource Class Reference中提供的界面。

EAX< Blowfish >::Encryption e1;
e1.SetKeyWithIV(key, key.size(), iv, sizeof(iv));

FileSource fs1(ofilename.c_str(), true,
    new AuthenticatedEncryptionFilter(e1,
        new FileSink(efilename.c_str())));

希望有人可以告诉我机制或我可以了解它的地方。

1 个答案:

答案 0 :(得分:0)

  

...并且在加密时不允许我将加密数据保存到字节数组中。我想知道下面的机制,以便保存临时数据。

我不清楚你想用临时数组做什么,所以下面的答案可能不正确。

有两种方法可以在数组中创建临时结果。首先是一个串行操作,您将文件加密为一个数组,然后将该数组写入磁盘。第二种是并行操作,其中阵列和加密文件同时创建。

您无法使用C ++ 11 std::array,因为在运行时,数组的大小已知。您可以使用std::vector,并提供一个代码段。

<强> 串行

#include <fstream>
#include <iostream>
#include <string>
#include <memory>
using namespace std;

#include "osrng.h"
#include "eax.h"
#include "modes.h"
#include "blowfish.h"
#include "filters.h"
#include "files.h"

using namespace CryptoPP;

int main(int argc, char* argv[])
{
    SecByteBlock key(Blowfish::DEFAULT_KEYLENGTH), iv(Blowfish::BLOCKSIZE);
    string ifilename("config.h"), ofilename("config.h.enc");

    memset(key, 0x00, key.size());
    memset(iv, 0x00, iv.size());

    EAX< Blowfish >::Encryption enc;
    enc.SetKeyWithIV(key, key.size(), iv, sizeof(iv));

    ifstream strm(ifilename.c_str(), ios::in | ios::binary);
    size_t len = strm.seekg(0, std::ios_base::end).tellg();
    strm.seekg(0, std::ios_base::beg);

    cout << "Data size: " << len << ", tag size: " << enc.TagSize() << endl;

    FileSource fs1(strm, false);
    len += enc.TagSize();

    cout << "Expected encrypted data and tag size: " << len << endl;
    len += Blowfish::BLOCKSIZE;
    cout << "Overcommitted encrypted data and tag size: " << len << endl;

    unique_ptr<byte[]> ptr(new byte[len]);
    ArraySink as1(ptr.get(), len);

    fs1.Detach(new AuthenticatedEncryptionFilter(enc, new Redirector(as1)));
    fs1.PumpAll();

    len = as1.TotalPutLength();
    cout << "Encrypted data and tag size: " << as1.TotalPutLength() << endl;

    ArraySource as2(ptr.get(), len, true, new FileSink(ofilename.c_str()));

    return 0;
}

序列示例产生:

$ ./test.exe
Data size: 38129, tag size: 8
Expected encrypted data and tag size: 38137
Overcommitted encrypted data and tag size: 38145
Encrypted data and tag size: 38137

$ ls -l config.*
-rw-r--r--. 1 ... 38223 Nov 19 04:40 config.compat
-rw-r--r--. 1 ... 38129 Nov 19 04:40 config.h
-rw-r--r--. 1 ... 38137 Nov 19 06:03 config.h.enc

<强> 并行

#include <fstream>
#include <iostream>
#include <string>
#include <memory>
using namespace std;

#include "osrng.h"
#include "eax.h"
#include "modes.h"
#include "blowfish.h"
#include "filters.h"
#include "files.h"
#include "channels.h"

using namespace CryptoPP;

int main(int argc, char* argv[])
{
    SecByteBlock key(Blowfish::DEFAULT_KEYLENGTH), iv(Blowfish::BLOCKSIZE);
    string ifilename("config.h"), ofilename("config.h.enc");

    memset(key, 0x00, key.size());
    memset(iv, 0x00, iv.size());

    EAX< Blowfish >::Encryption enc;
    enc.SetKeyWithIV(key, key.size(), iv, sizeof(iv));

    ifstream strm(ifilename.c_str(), ios::in | ios::binary);
    size_t len = strm.seekg(0, std::ios_base::end).tellg();
    strm.seekg(0, std::ios_base::beg);

    // Overcommit
    len += enc.TagSize() + Blowfish::BLOCKSIZE;

    // The one and only source
    FileSource fs1(strm, false);

    // The first sink
    FileSink fs2(ofilename.c_str(), true);

    // The second sink
    unique_ptr<byte[]> ptr(new byte[len]);
    ArraySink as1(ptr.get(), len);

    // The magic to output to both sinks
    ChannelSwitch cs;
    cs.AddDefaultRoute(as1);
    cs.AddDefaultRoute(fs2);

    fs1.Detach(new AuthenticatedEncryptionFilter(enc, new Redirector(cs)));
    fs1.PumpAll();

    return 0;
}

并行示例产生:

$ ./test.exe

$ ls -l config.*
-rw-r--r--. 1 ... 38223 Nov 19 04:40 config.compat
-rw-r--r--. 1 ... 38129 Nov 19 04:40 config.h
-rw-r--r--. 1 ... 38137 Nov 19 06:02 config.h.enc

<强> 的std ::矢量

而不是:

unique_ptr<byte[]> ptr(new byte[len]);
ArraySink as1(ptr.get(), len);

您可以使用:

std::vector<byte> v;
...

v.resize(len);
ArraySink as(&v[0], v.size());
...

// Perform encryption
fs.Detach(new AuthenticatedEncryptionFilter(enc, new Redirector(as)));
fs.PumpAll();

// Resize now you know the size of ciphertext and tag
v.resize(as.TotalPutLength());