使用密文Crypto ++ CBC AES加密存储IV [英] Storing the IV with the ciphertext Crypto++ CBC AES encryption

查看:203
本文介绍了使用密文Crypto ++ CBC AES加密存储IV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在CBC模式和Crypto ++库中使用AES加密(并解密)文件

I'm trying to encrypt(and decrypt after) a file using AES in CBC mode and Crypto++ library

这是我已经做过的事情:

Here's what I already did:

using namespace CryptoPP;
AutoSeededRandomPool rnd;

//generating the key and iv
SecByteBlock key(AES::MAX_KEYLENGTH);
rnd.GenerateBlock(key, key.size());
byte iv[AES::BLOCKSIZE];
rnd.GenerateBlock(iv, AES::BLOCKSIZE);

要加密文件,我以二进制模式打开它,并将内容转储到字符串中:

To encrypt a file,I open it in binary mode,and dump the content to a string :

std::ifstream fin(file_path, std::ios::binary);
if (!fin)
{
    std::cout << "error";
}
std::ostringstream ostrm;
ostrm << fin.rdbuf();
std::string plaintext(ostrm.str());
fin.close();

然后,我使用密钥和以前生成的iv加密此字符串:

Then,I encrypt this string using the key and iv previously generated:

std::string ciphertext;

AES::Encryption aesEncryption(key, CryptoPP::AES::MAX_KEYLENGTH);
CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);

StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(ciphertext));
stfEncryptor.Put(reinterpret_cast<const unsigned char*>(plaintext.c_str()), plaintext.length() + 1);
stfEncryptor.MessageEnd();

现在,我想将加密后的字符串写入文件,然后将IV与其一起存储,因为iv不需要保密,最好是在密文的开头或结尾

Now,i want to write the encrypted string to a file,and store the IV with it,since the iv doesn't need to be kept secret,ideally at the beginning or the end of the ciphertext

这里出现了问题:IV是字节数组和密文是一个字符串,我是否需要将两者之一转换为另一种类型,或者我可以做:

Here comes the problem : the IV is a byte array and the ciphertext is a string,do i need to convert one of the two to another type,or can i just do :

std::ofstream fdout(file_path2, std::ios::binary);
if (!fdout)
{
    std::cout << "error";
}
fdout << iv;
fdout << ciphertext;
fdout.close();

当我尝试解密此文件时,如何分别提取iv和密文? IV长16字节,但是在这里我完全迷失了,我不知道该怎么办。

When i will try to decrypt this file,how can i extract the iv and ciphertext separately ? The IV is 16 Bytes long,but here i'm completely lost and i don't know how to do.

推荐答案


使用密文Crypto ++ CBC AES加密存储IV

Storing the IV with the ciphertext Crypto++ CBC AES encryption

您使用的某些代码有点不寻常对我来说。我将介绍一些方法,并向您展示一些Crypto ++方式。

Some of the code you are using is a bit unusual to me. I'll pick a couple things out and show you some of the Crypto++ ways.

在开始之前,请先查看管道抽取数据在Crypto ++ Wiki上。请记住,数据从源流向接收器。在数据之间会遇到转换数据的过滤器。

Before you begin, take a look at Pipelines and Pumping Data on the Crypto++ wiki. Remember that data flows from sources to sinks. In between the data encounters filters which transform the data.

std::ifstream fin(file_path, std::ios::binary);
if (!fin)
{
    std::cout << "error";
}
std::ostringstream ostrm;
ostrm << fin.rdbuf();
std::string plaintext(ostrm.str());
fin.close();

Crypto ++ FileSource 的构造函数采用 std :: istream 。您可以执行以下操作。另请参阅Crypto ++ Wiki上的 FileSource

A Crypto++ FileSource has a constructor that takes a std::istream. You could do something like the following. Also see FileSource on the Crypto++ wiki.

std::ifstream fin(file_path, std::ios::binary);
FileSource source(fin, true /*pump all*/, NULLPTR);
...








AES::Encryption aesEncryption(key, CryptoPP::AES::MAX_KEYLENGTH);
CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);


ExternalCipher 用于FIPS DLL。您可以在没有DLL的情况下使用它们,但是它们存在于DLL中。通常,您使用:

ExternalCipher are for the FIPS DLL. You can use them without the DLL, but they exist for the DLL. Usually you use:

 CBC_Mode<AES>::Encryption encryptor;

此外,您通常希望避免使用仅限机密模式。通常,您要使用经过身份验证的加密操作模式。它提供机密性和真实性

Also, you usually want to avoid a confidentiality-only mode. Typically you want to use an Authenticated Encryption mode of operation. It provides confidentiality and authenticity.

Crypto ++提供CCM,EAX和GCM认证的加密操作模式。 OCB和EAX是非常好的选择。在Crypto ++ Wiki上的 EAX模式中记录了EAX模式。 OCB目前不可用。我们已经准备好以OCB模式签入。

Crypto++ provides CCM, EAX and GCM authenticated encryption modes of operation. OCB and EAX are very good choices. EAX mode is documented at EAX Mode on the Crypto++ wiki. OCB is not available at the moment. We are getting ready to check-in OCB mode.


现在,我想写将加密的字符串保存到文件中,然后将其与IV一起存储,因为iv不需要保密,最好在密文的开头或结尾处

Now,i want to write the encrypted string to a file,and store the IV with it,since the iv doesn't need to be kept secret,ideally at the beginning or the end of the ciphertext

使用类似以下的内容。我没有编译它,所以您将需要纠正拼写错误。

Use something like the following. I did not compile it, so you will need to fix the typos.

AutoSeededRandomPool prng;
SecByteBlock key(AES::MAXIMUM_KEYLENGTH), iv(AES::BLOCKSIZE);

RandomNumberSource rs1(prng, AES::MAXIMUM_KEYLENGTH, new ArraySink(key, key.size()));
RandomNumberSource rs2(prng, AES::BLOCKSIZE, new ArraySink(iv, iv.size()));

HexEncoder encoder(new FileSink(std::cout));

std::cout << "Key: ";
encoder.Put(key, key.size());
encoder.MessageEnd();
std::cout << std::endl;

std::cout << "IV: ";
encoder.Put(iv, iv.size());
encoder.MessageEnd();
std::cout << std::endl;

EAX<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, key.size(), iv, iv.size());

// Plaintext message
std::string message;

// Output file
FileSink file("message.enc");

// Source wrappers
ArraySource as(iv, iv.size(), true,
    new Redirector(file));

// Source wrapper
StringSource ss(message, true,
    new StreamTransformationFilter(encryptor,
       new Redirector(file)));








我何时尝试解密该文件,如何分别提取IV和密文?

When i will try to decrypt this file,how can i extract the iv and ciphertext separately ?

使用如下所示的内容。

// Key is from previous example. It cannot change
SecByteBlock key(AES::MAXIMUM_KEYLENGTH), iv(AES::BLOCKSIZE);    
FileSource fs("message.enc", false /* DO NOT Pump All */);

// Attach new filter
ArraySink as(iv, iv.size());
fs.Attach(new Redirector(as));
fs.Pump(AES::BLOCKSIZE);  // Pump first 16 bytes

EAX<AES>::Decryption decryptor;
decryptor.SetKeyWithIV(key, key.size(), iv, iv.size());

// Detach previously attached filter, attach new filter
ByteQueue queue;
fs.Detach(new StreamTransformationFilter(decryptor, new Redirector(queue)));
fs.PumpAll();  // Pump remainder of bytes

加密的数据将位于 ByteQueue 。它不会提供与C ++迭代器类似的功能,例如指针和大小。要从 ByteQueue 中获取数据,可以将其传输或复制到另一个过滤器或接收器中:

The encrypted data will be in a ByteQueue. It does not provide C++ iterator-like functionality, like a pointer and a size. To get the data out of the ByteQueue you transfer it or copy it to another filter or a sink:

SecByteBlock block(queue.MaxRetrievable());
ArraySink sink(block, block.size());
queue.TransferTo(sink);

您可以从 ByteQueue 并将其放在 std :: string 中,并带有:

You can get the data out of the ByteQueue and put it in astd::string with:

std::string recovered;
StringSink sink(recovered);
queue.TransferTo(sink);

您可以使用以下命令打印从文件中恢复的IV:

And you can print the IV recovered from the file with:

HexEncoder encoder(new FileSink(std::cout));

std::cout << "IV: ";
encoder.Put(iv, iv.size());
encoder.MessageEnd();
std::cout << std::endl;

这篇关于使用密文Crypto ++ CBC AES加密存储IV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆