Crypto++ Encrypting Files in Hybrid Mode with RSA

When encrypting binary files, especially big ones, it not sensible to use asymmetric key cryptography. This will be slow and may produce data inconsistency errors.
But we still want to use public key cryptography somehow, because symmetric key alone is kind of lame. Hybrid mode scheme makes everyone happy.

Encryption:

  • Generate random passphrase (symmetric key)
  • Encrypt the File using this passphrase
  • Encrypt passphrase with asymmetric public key
  • Store encrypted passphrase and encrypted file data into one Encrypted File

Decryption:

  • Read Encrypted File
  • Split into two pieces: encrypted passphrase and encrypted file data
  • Decrypt passphrase using asymmetric private key
  • Decrypt file data using passphrase

It will be fast because most of the data is encrypted using symmetric cryptography and it uses advantages of public key cryptography.

Here is implementation in C++ using Crypto++ library


// Helper function
string randomStrGen (int length)
{
static string charset
= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
string result;
result.resize(length);
for (int i = 0; i < length; i++) {
result[i] = charset[rand() % charset.length()];
}
return result;
}

// Encrypt string with RSA
string RSAEncryptString (string publickeyfile,
string message)
{
string seed = randomStrGen(50);

FileSource pubFile(publickeyfile.c_str(), true, new HexDecoder);
RSAES_OAEP_SHA_Encryptor pub(pubFile);

RandomPool randPool;
randPool.IncorporateEntropy((byte *)seed.c_str(),
strlen(seed.c_str()));

string result;
StringSource(message.c_str(), true,
new PK_EncryptorFilter(
randPool,
pub,
new HexEncoder(new StringSink(result))));
return result;
}

// Decrypt string with RSA
string RSADecryptString (string privatekeyfile,
string ciphertext)
{
FileSource privFile(privatekeyfile.c_str(), true, new HexDecoder);
RSAES_OAEP_SHA_Decryptor priv(privFile);

string result;
StringSource(ciphertext.c_str(), true,
new HexDecoder(
new PK_DecryptorFilter(GlobalRNG(),
priv,
new StringSink(result))));
return result;
}

// Encrypt file in hybrid mode
void EncryptFile (string publickeyfile,
string filetoencrypt,
string encryptedfile)
{
// Generate passphrase
string passphrase = randomStrGen(50);
string encrypted_passphrase = RSAEncryptString(publickeyfile,
passphrase);

// Encrypt the file and save encrypted data to the string
string data;
FileSource f(filetoencrypt.c_str(), true,
new DefaultEncryptorWithMAC(
passphrase.c_str(),
new HexEncoder(new StringSink(data))));

// Append encrypted passphrase to the beginning of the string
data = encrypted_passphrase + data;

// Save string to the file
StringSource ss(data.c_str(), true,
new FileSink(encryptedfile.c_str()));
}

// Decrypt file in hybrid mode
void DecryptFile (string privatekeyfile,
string filetodecrypt,
string decryptedfile)
{
// Read string from file
string data;
FileSource ff(filetodecrypt.c_str(), true, new StringSink(data));

// Grab passphrase from the string
string encrypted_passphrase = data.substr(0,256);
string passphrase = RSADecryptString(privatekeyfile,
encrypted_passphrase);

// Grab cipher from the string
string cipher = data.substr(256, data.length());

// Decrypt string and save to file
StringSource s(cipher.c_str(), true,
new HexDecoder(new DefaultDecryptorWithMAC(
passphrase.c_str(),
new FileSink(decryptedfile.c_str()))));
}

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>