1
\$\begingroup\$
#include <cryptopp/cryptlib.h>
#include <assert.h>
#include <cryptopp/queue.h>
#include <cryptopp/secblockfwd.h>
#include <iostream>
#include <fstream>
#include <cryptopp/integer.h>
#include <cryptopp/rsa.h>
#include <cryptopp/osrng.h>
#include <cryptopp/files.h>
#include <cryptopp/secblock.h>
#include <sstream>
void SaveKey(const std::string filename, const CryptoPP::RSA::PublicKey& key);
void SaveKey(const std::string filename, const CryptoPP::RSA::PrivateKey& key);
void Save(const std::string filename, const CryptoPP::BufferedTransformation& bt);
std::string Convert(CryptoPP::SecByteBlock block);
std::string decrypt(CryptoPP::SecByteBlock ciphertext, CryptoPP::RSA::PrivateKey priv_key);
CryptoPP::RSA::PrivateKey createPrivateKey(int size);
CryptoPP::SecByteBlock Encrypt(CryptoPP::RSA::PublicKey pub_key, const std::string file);
std::string read(std::string filename);
int main(int argc, char* argv[]){
 std::string file = read(argv[1]);
 std::cout << file << "\n";
 //creates a public and private key
 CryptoPP::AutoSeededRandomPool prng;
 CryptoPP::RSA::PrivateKey priv_key;
 priv_key.GenerateRandomWithKeySize(prng, 3072);
 
 
 CryptoPP::RSA::PublicKey pub_key(priv_key);
 SaveKey("priv", priv_key);
 SaveKey("pub", pub_key);
 //Encrypts the file using the public key
 CryptoPP::SecByteBlock ciphertext = Encrypt(pub_key, file); 
 //Converts the encrypted data to string format and saves it in a file
 std::string encryptStr = Convert(ciphertext);
 std::ofstream encFile("encrypt.txt");
 encFile << encryptStr;
 
 std::cout << "Decrypted text "<< decrypt(ciphertext, priv_key) << "\n";
 return 0;
}
std::string decrypt(CryptoPP::SecByteBlock ciphertext, CryptoPP::RSA::PrivateKey priv_key){
 CryptoPP::AutoSeededRandomPool rnd;
 CryptoPP::RSAES_OAEP_SHA_Decryptor decryptor(priv_key);
 //checks
 assert(0 != decryptor.FixedMaxPlaintextLength());
 assert(ciphertext.size() <= decryptor.FixedCiphertextLength());
 // Create recovered text space
 size_t dpl = decryptor.MaxPlaintextLength( ciphertext.size() );
 assert( 0 != dpl );
 CryptoPP::SecByteBlock recovered( dpl );
 // Decoding text
 CryptoPP::DecodingResult result = decryptor.Decrypt( rnd,
 ciphertext, ciphertext.size(), recovered );
 // More sanity checks
 assert( result.isValidCoding ); 
 assert( result.messageLength <= decryptor.MaxPlaintextLength( ciphertext.size() ) );
 //Resised the buffer to the correct length and converts it to string format
 recovered.resize(result.messageLength);
 std::string message = Convert(recovered);
 return message;
}
void Save(const std::string filename, const CryptoPP::BufferedTransformation& bt){
 CryptoPP::FileSink file(filename.c_str());
 bt.CopyTo(file);
 file.MessageEnd();
}
void SaveKey(const std::string filename, const CryptoPP::RSA::PublicKey& key){
 CryptoPP::ByteQueue queue;
 key.Save(queue);
 Save(filename, queue);
}
void SaveKey(const std::string filename, const CryptoPP::RSA::PrivateKey& key){
 CryptoPP::ByteQueue queue;
 key.Save(queue);
 Save(filename, queue);
}
CryptoPP::SecByteBlock Encrypt(CryptoPP::RSA::PublicKey pub_key, const std::string file){
 CryptoPP::AutoSeededRandomPool rnd;
 CryptoPP::RSAES_OAEP_SHA_Encryptor encryptor(pub_key);
 CryptoPP::SecByteBlock plaintext(reinterpret_cast<const CryptoPP::byte*>(&file[-1]), file.size());
 size_t ecl = encryptor.CiphertextLength(plaintext.size());
 assert(ecl != -1);
 CryptoPP::SecByteBlock ciphertext(ecl);
 encryptor.Encrypt(rnd, plaintext, plaintext.size(), ciphertext);
 return ciphertext;
}
std::string Convert(CryptoPP::SecByteBlock block){
 std::string str;
 str.resize(block.size());
 memcpy(&str[0], &block[0], str.size());
 return str;
}
std::string read(std::string filename){
 std::ifstream file;
 file.open(filename);
 assert(file.is_open());
 std::ostringstream sstr;
 sstr << file.rdbuf();
 return sstr.str();
}

This code starts by reading in an external file passed in through arg[0]. Them it creates an saves an RSA public and private key using crypto++. Then it encrypts the file using the public key and saves it to a file. Then it decrypts it and prints the result. Is there a way that I can make it more secure, more readable and more efficient.

asked Jan 1, 2022 at 18:11
\$\endgroup\$
1
  • \$\begingroup\$ My standard comment on encryption. Don't roll your own (if you are doing this for practical use). Assuming this is for learning purposes, fine. \$\endgroup\$ Commented Jan 4, 2022 at 19:09

1 Answer 1

1
\$\begingroup\$

The main thing I don't like is the need to load the whole file into memory before you start encryption. This will only work for relatively small files.

I would expect the interface to be more like:

 std::ifstream file(file);
 std::ofstream encryptedFile(file + ".encryp");
 EnctptedStream encryptedStream(encryptedFile, publicKey);
 encryptedStream << file.rdbuf();

So:

 // Make the encryption be a normal stream like object.
 // Then you can send data to the encryption stream just like
 // you send data to a normal stream (so it can be used anywhere
 // you would normally use a stream the using code does not need
 // to know that this is a special stream).
 //
 // I would also make it a wrapper of a stream so we can send the
 // data to any other normla stream be that a file or a memory
 // buffer.
 class EnctptedStream: public std::ostream
 {
 public:
 EnctptedStream(std::ostream& stream, Key key);
 };
answered Jan 4, 2022 at 19:31
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.