使用Crypto ++中的RSA加密对称AES密钥

时间:2017-08-02 14:52:24

标签: c++ encryption cryptography crypto++

我正在尝试在两个部分之间交换AES密钥.AES密钥将使用接收者的RSA publicKey加密,然后写入文件。

我正在使用Crypto ++库,这是我程序的开始:

//generate key pair
CryptoPP::AutoSeededRandomPool rng;
CryptoPP::RSAES_OAEP_SHA_Decryptor priv(rng, 4096);

RSA::PrivateKey privateKey(params);
RSA::PublicKey publicKey(params);

//generate aes key (256bits)
SecByteBlock key(AES::MAX_KEYLENGTH);
rnd.GenerateBlock(key, key.size());

(你会认识到Crypto ++ wiki的例子)

然后我开始加密例程:

CryptoPP::SecByteBlock cipher(CryptoPP::AES::MAX_KEYLENGTH), decrypted_data(CryptoPP::AES::MAX_KEYLENGTH);

CryptoPP::RSAES_OAEP_SHA_Encryptor e(publicKey);

我不知道使用哪一个:CryptoPP:: ArraySourceCryptoPP::StringSource

1 个答案:

答案 0 :(得分:2)

  

...在我不知道该使用什么之后:CryptoPP :: ArraySource? CryptoPP :: StringSource?

在此之后,使用PK_EncryptorFilter作为RSA加密器;并使用ArraySource作为您尝试加密的密钥。 ArraySource只是StringSource的typedef,因此您实际上只是使用了StringSource

代码看起来如下所示。我没有运行这些示例,所以请修复错别字。

SecByteBlock key(AES::MAX_KEYLENGTH);
rng.GenerateBlock(key, key.size());
...

RSAES_OAEP_SHA_Encryptor encryptor(publicKey);
...

ArraySource as(key, key.size(), true, /* pump all data */
    new PK_EncryptorFilter(rng, encryptor,
        new FileSink("session-key.enc")));

您可以使用以下内容将其写入std::string

std::string session_key;
ArraySource as(key, key.size(), true, /* pump all data */
    new PK_EncryptorFilter(rng, encryptor,
        new StringSink(session_key)));

您也可以使用ByteQueueRedirector打破了所有权链。另请参阅Crypto ++ wiki上的Redirector

ByteQueue queue;
ArraySource as(key, key.size(), true, /* pump all data */
    new PK_EncryptorFilter(rng, encryptor,
        new Redirector(queue)));

ByteQueue很酷,因为它们会包裹SecByteBlock。进入ByteQueue后,您可以使用TransferToCopyTo移动字节:

ByteQueue queue;
ArraySource as(key, key.size(), true, /* pump all data */
    new PK_EncryptorFilter(rng, encryptor,
        new Redirector(queue)));

// Copy bytes to a file
FileSink sink1("session-key.enc");
queue.CopyTo(sink1);

// Copy bytes to std::out
HexEncoder encoder(new FileSink(std::cout));
queue.CopyTo(encoder);

// Transfer bytes to a SecByteBlock.
SecByteBlock block(queue.MaxRetrievable());
ArraySink sink2(block, block.size());
queue.TransferTo(sink2);
// No bytes remain in the queue

您可能也对Crypto ++ wiki上的Pipelines感兴趣。您在上面看到的内容是管道中使用的源,过滤器和接收器。

如果这应该保存加密的对称密钥,那么它太小了:

SecByteBlock cipher(AES::MAX_KEYLENGTH);

在Crypto ++ wiki上查看RSA Encryption Schemescipher需要为encryptor.CiphertextLength(AES::MAX_KEYLENGTH);,大致相当于OAA格式和填充的RSA模数减去约50个字节的大小。

  

(评论)>现在我正在尝试使用私钥添加部件来解密它...这是正确的吗?

StringSource(readed_key, true,
    new PK_DecryptorFilter(rng, decryptor, new 
        FileSource("sessionkey.enc")));

嗯,过滤器部分是正确的(PK_DecryptorFilter部分)。在Crypto ++中,数据从源流向接收器。所以一般模式如下所示。它叫做Pipeline

Source(..., new Filter(..., new Filter(..., new Sink(...))));

通常你需要以下内容。 Redirector打破了所有权链。另请参阅Crypto ++ wiki上的Redirector

// decrypted, in-memory
SecByteBlock session_key(AES::MAX_KEYLENGTH);
ArraySink sink(session_key, session_key.size());

FileSource fs("sessionkey.enc", true,
    new PK_DecryptorFilter(rng, decryptor, 
        new Redirector(sink)));
  

(评论)> ...然后比较原始......

您可以在几乎恒定的时间内将两个字节缓冲区与VerifyBufsEqual进行比较。再次,请参阅Crypto ++ wiki。