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.

\$\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\$ 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);
 };
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.