Encrypting AES Symmetric Key with RSA in Crypto ++
I am trying to exchange an AES key between two parts. The AES key will be encrypted with the RSA receiver publicKey
and then written to a file.
I am using Crypto ++ library and here is the start of my program:
//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());
(You will learn an example of the Crypto ++ wiki)
Then I run the encryption routine:
CryptoPP::SecByteBlock cipher(CryptoPP::AES::MAX_KEYLENGTH), decrypted_data(CryptoPP::AES::MAX_KEYLENGTH);
CryptoPP::RSAES_OAEP_SHA_Encryptor e(publicKey);
I don't know which one to use: CryptoPP:: ArraySource
or CryptoPP::StringSource
?
source to share
... after I don't know what to use: CryptoPP :: ArraySource? CryptoPP :: StringSource?
Then use PK_EncryptorFilter
RSA for encryption; and use ArraySource
for the key you are trying to encrypt. ArraySource
is just a typedef for StringSource
, so you actually use StringSource
.
The code will look something like this: I haven't run the examples, so please correct the typos.
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")));
You can write it in std::string
with something like:
std::string session_key;
ArraySource as(key, key.size(), true, /* pump all data */
new PK_EncryptorFilter(rng, encryptor,
new StringSink(session_key)));
You can also get fancy and use ByteQueue
. Redirector
destroys the chain of ownership. Also see the Redirector
Crypto ++ wiki.
ByteQueue queue;
ArraySource as(key, key.size(), true, /* pump all data */
new PK_EncryptorFilter(rng, encryptor,
new Redirector(queue)));
ByteQueue
are great because they complete SecByteBlock
. In ByteQueue
you can move bytes with TransferTo
and CopyTo
:
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
You may also be interested in the Pipelines on the Crypto ++ wiki. The material you see above is the sources, filters and sinks used in the conveyor.
If it is assumed to contain an encrypted symmetric key, then it is too small:
SecByteBlock cipher(AES::MAX_KEYLENGTH);
Take a look at RSA Encryption Schemes on the Crypto ++ wiki. cipher
should be encryptor.CiphertextLength(AES::MAX_KEYLENGTH);
that roughly equal to the size of the RSA unit minus about 50 bytes for OAEP formatting and padding.
(comment)> Now I am trying to add a part so I can decrypt it with the private key ... Is that correct?
StringSource(readed_key, true, new PK_DecryptorFilter(rng, decryptor, new FileSource("sessionkey.enc")));
Well, the filter part is correct (part PK_DecryptorFilter
). In Crypto ++, data is transferred from source to destination. Thus, the general scheme is shown below. It is called the Pipeline .
Source(..., new Filter(..., new Filter(..., new Sink(...))));
Usually you want something like the following. Redirector
destroys the chain of ownership. Also see the Redirector
Crypto ++ wiki.
// 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)));
(comment)> ... and then compare the original ...
You can compare two byte buffers at almost constant time with VerifyBufsEqual
. Again, see the Crypto ++ wiki.
source to share