crypto++ 中的 PumpMessages,正在读取密钥文件?
PumpMessages in crypto++, reading a key file?
我正在使用以下代码使用 crypto++ 将 AES 密钥和 iv 写入文件:
// write the key:
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
SecByteBlock iv(AES::BLOCKSIZE);
string file = m_file_name + ".key";
FileSink* key_out = new FileSink(file.c_str());
Base64Encoder base64_key_enc(key_out);
base64_key_enc.Put(key.BytePtr(), key.size());
base64_key_enc.MessageEnd();
base64_key_enc.Put(iv.BytePtr(), iv.size());
base64_key_enc.MessageEnd();
并从文件中读取密钥和 iv,我使用以下内容:
// read key
string file = m_file_name + ".key";
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
ArraySink* arr_key_in = new ArraySink(key, key.size());
Base64Decoder* base64_key_dec = new Base64Decoder(arr_key_in);
FileSource source(file.c_str(), false, base64_key_dec);
source.PumpMessages(1); // read only the key
// read iv
SecByteBlock iv(AES::BLOCKSIZE);
ArraySink* arr_iv_in = new ArraySink(iv, iv.size());
base64_key_dec->Detach(arr_iv_in);
source.PumpAll(); // read the rest (the iv)
问题是在读取文件后密钥是正确的但 iv 不是,所以我很奇怪我的 sintax 有什么问题吗?
密钥文件的内容是 base64 十六进制编码的,如下所示:
2Gnh3TbAJeQPmza9FKdqNg==
FowuKut3pBl7g0Or+4FJUg==
== 意味着 message/key...
第一个是key,另一个是iv,上面的代码没有正确地从文件中读取iv。
我的代码有什么问题?
Problem is that after reading a file the key is correct but iv is not, so i wonder what could be wrong with my syntax?
我认为问题在于图书馆不理解您的消息概念,因此它不知道如何流式传输消息。我怀疑它会一口气读完所有内容。
您可能可以用source.Pump(AES::DEFAULT_KEYLENGTH * 4 / 3)
更正它。我认为这是正确的,以补偿基本编码扩展。或者,您可以读取 Base64 连接字符串,在 space 上拆分,然后分别处理两条消息。
或者您可以尝试以下方法。它和你的没什么不同,除了它写了一个长度前缀,这样 Key 和 IV 可以很容易地描述和恢复。
典型的 运行 看起来像:
$ ./cryptopp-test.exe
Key 1: 434477042E70083441961B2F98A9FB1C
IV 1: 73A06DA15676B5AFB80C1741B3651982
Encoded: ABBDRHcELnAINEGWGy+YqfscABBzoG2hVna1r7gMF0GzZRmC
Key 2: 434477042E70083441961B2F98A9FB1C
IV 2: 73A06DA15676B5AFB80C1741B3651982
HexEncoder hex;
string filename = "test.txt", r1, r2, r3, r4, r5;
Base64Encoder encoder;
AlgorithmParameters params = MakeParameters(Pad(), false)(InsertLineBreaks(), false);
encoder.Initialize(params);
SecByteBlock k1(AES::DEFAULT_KEYLENGTH), v1(AES::BLOCKSIZE);
// Generate random key and iv
OS_GenerateRandomBlock(false, k1, k1.size());
OS_GenerateRandomBlock(false, v1, v1.size());
// Print key
hex.Detach(new StringSink(r1));
hex.Put(k1, k1.size());
hex.MessageEnd();
cout << "Key 1: " << r1 << endl;
// Print iv
hex.Detach(new StringSink(r2));
hex.Put(v1, v1.size());
hex.MessageEnd();
cout << "IV 1: " << r2 << endl;
// Write key
encoder.PutWord16(static_cast<word16>(k1.size()), BIG_ENDIAN_ORDER);
encoder.Put(k1.data(), k1.size());
// Write iv
encoder.PutWord16(static_cast<word16>(v1.size()), BIG_ENDIAN_ORDER);
encoder.Put(v1.data(), v1.size());
encoder.MessageEnd();
// Save it
FileSink f1(filename.c_str(), true);
encoder.CopyTo(f1);
f1.MessageEnd();
// Print Base64 encoded
StringSink ss(r3);
encoder.TransferTo(ss);
ss.MessageEnd();
cout << "Encoded: " << r3 << endl;
// Read file
ByteQueue queue;
FileSource f2(filename.c_str(), false, new Base64Decoder(new Redirector(queue)));
f2.PumpAll();
// Read key and iv
SecByteBlock k2, v2;
word16 size = 0;
// Read key
queue.GetWord16(size, BIG_ENDIAN_ORDER);
k2.resize(size);
queue.Get(k2, k2.size());
// Read iv
queue.GetWord16(size, BIG_ENDIAN_ORDER);
v2.resize(size);
queue.Get(v2, v2.size());
// Print key
hex.Detach(new StringSink(r4));
hex.Put(k2, k2.size());
hex.MessageEnd();
cout << "Key 2: " << r4 << endl;
// Print iv
hex.Detach(new StringSink(r5));
hex.Put(v2, v2.size());
hex.MessageEnd();
cout << "IV 2: " << r5 << endl;
有关删除填充和换行符的 MakeParameters
技巧的参考位于 Crypto++ wiki 上的 NameValuePairs。
OS_GenerateRandomBlock
的参考位于 Crypto++ wiki 上的 RandomNumberGenerator。
您可以在 Crypto++ 维基上找到 HexEncoder, Base64Encoder, Redirector 和朋友。
此外,AES::DEFAULT_KEYLENGTH
是 16 字节 (AES-128)。这通常足以满足大多数人的需求。如果需要,您可以将其提高到 32 (AES-256)。
我正在使用以下代码使用 crypto++ 将 AES 密钥和 iv 写入文件:
// write the key:
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
SecByteBlock iv(AES::BLOCKSIZE);
string file = m_file_name + ".key";
FileSink* key_out = new FileSink(file.c_str());
Base64Encoder base64_key_enc(key_out);
base64_key_enc.Put(key.BytePtr(), key.size());
base64_key_enc.MessageEnd();
base64_key_enc.Put(iv.BytePtr(), iv.size());
base64_key_enc.MessageEnd();
并从文件中读取密钥和 iv,我使用以下内容:
// read key
string file = m_file_name + ".key";
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
ArraySink* arr_key_in = new ArraySink(key, key.size());
Base64Decoder* base64_key_dec = new Base64Decoder(arr_key_in);
FileSource source(file.c_str(), false, base64_key_dec);
source.PumpMessages(1); // read only the key
// read iv
SecByteBlock iv(AES::BLOCKSIZE);
ArraySink* arr_iv_in = new ArraySink(iv, iv.size());
base64_key_dec->Detach(arr_iv_in);
source.PumpAll(); // read the rest (the iv)
问题是在读取文件后密钥是正确的但 iv 不是,所以我很奇怪我的 sintax 有什么问题吗?
密钥文件的内容是 base64 十六进制编码的,如下所示:
2Gnh3TbAJeQPmza9FKdqNg== FowuKut3pBl7g0Or+4FJUg==
== 意味着 message/key... 第一个是key,另一个是iv,上面的代码没有正确地从文件中读取iv。
我的代码有什么问题?
Problem is that after reading a file the key is correct but iv is not, so i wonder what could be wrong with my syntax?
我认为问题在于图书馆不理解您的消息概念,因此它不知道如何流式传输消息。我怀疑它会一口气读完所有内容。
您可能可以用source.Pump(AES::DEFAULT_KEYLENGTH * 4 / 3)
更正它。我认为这是正确的,以补偿基本编码扩展。或者,您可以读取 Base64 连接字符串,在 space 上拆分,然后分别处理两条消息。
或者您可以尝试以下方法。它和你的没什么不同,除了它写了一个长度前缀,这样 Key 和 IV 可以很容易地描述和恢复。
典型的 运行 看起来像:
$ ./cryptopp-test.exe
Key 1: 434477042E70083441961B2F98A9FB1C
IV 1: 73A06DA15676B5AFB80C1741B3651982
Encoded: ABBDRHcELnAINEGWGy+YqfscABBzoG2hVna1r7gMF0GzZRmC
Key 2: 434477042E70083441961B2F98A9FB1C
IV 2: 73A06DA15676B5AFB80C1741B3651982
HexEncoder hex;
string filename = "test.txt", r1, r2, r3, r4, r5;
Base64Encoder encoder;
AlgorithmParameters params = MakeParameters(Pad(), false)(InsertLineBreaks(), false);
encoder.Initialize(params);
SecByteBlock k1(AES::DEFAULT_KEYLENGTH), v1(AES::BLOCKSIZE);
// Generate random key and iv
OS_GenerateRandomBlock(false, k1, k1.size());
OS_GenerateRandomBlock(false, v1, v1.size());
// Print key
hex.Detach(new StringSink(r1));
hex.Put(k1, k1.size());
hex.MessageEnd();
cout << "Key 1: " << r1 << endl;
// Print iv
hex.Detach(new StringSink(r2));
hex.Put(v1, v1.size());
hex.MessageEnd();
cout << "IV 1: " << r2 << endl;
// Write key
encoder.PutWord16(static_cast<word16>(k1.size()), BIG_ENDIAN_ORDER);
encoder.Put(k1.data(), k1.size());
// Write iv
encoder.PutWord16(static_cast<word16>(v1.size()), BIG_ENDIAN_ORDER);
encoder.Put(v1.data(), v1.size());
encoder.MessageEnd();
// Save it
FileSink f1(filename.c_str(), true);
encoder.CopyTo(f1);
f1.MessageEnd();
// Print Base64 encoded
StringSink ss(r3);
encoder.TransferTo(ss);
ss.MessageEnd();
cout << "Encoded: " << r3 << endl;
// Read file
ByteQueue queue;
FileSource f2(filename.c_str(), false, new Base64Decoder(new Redirector(queue)));
f2.PumpAll();
// Read key and iv
SecByteBlock k2, v2;
word16 size = 0;
// Read key
queue.GetWord16(size, BIG_ENDIAN_ORDER);
k2.resize(size);
queue.Get(k2, k2.size());
// Read iv
queue.GetWord16(size, BIG_ENDIAN_ORDER);
v2.resize(size);
queue.Get(v2, v2.size());
// Print key
hex.Detach(new StringSink(r4));
hex.Put(k2, k2.size());
hex.MessageEnd();
cout << "Key 2: " << r4 << endl;
// Print iv
hex.Detach(new StringSink(r5));
hex.Put(v2, v2.size());
hex.MessageEnd();
cout << "IV 2: " << r5 << endl;
有关删除填充和换行符的 MakeParameters
技巧的参考位于 Crypto++ wiki 上的 NameValuePairs。
OS_GenerateRandomBlock
的参考位于 Crypto++ wiki 上的 RandomNumberGenerator。
您可以在 Crypto++ 维基上找到 HexEncoder, Base64Encoder, Redirector 和朋友。
此外,AES::DEFAULT_KEYLENGTH
是 16 字节 (AES-128)。这通常足以满足大多数人的需求。如果需要,您可以将其提高到 32 (AES-256)。