4

I'm working on a project that uses Crypto++ to encrypt some data using RSA.

Here is my Crypto++ code:

string plain = "Text123", encoded, cipher;
string pkey = "...";

StringSource ss1(pkey, true);
RSA::PublicKey publicKey;
PEM_Load(ss, publicKey);
RSAES_OAEP_SHA_Encryptor e(publicKey);

StringSource ss2(plain, true,
    new PK_EncryptorFilter(prng, e,
        new StringSink(cipher)
    ) 
); 

StringSource ss3(cipher, true,
    new Base64Encoder(
        new StringSink(encoded)
    )
);
cout << encoded;

And I'm trying to decrypt the encrypted message in Python. Here is my Python code:

from Crypto.PublicKey import RSA
from base64 import b64decode  

cipher_text = "[THE OUTPUT OF C++]"
rsakey = RSA.importKey(open("private.txt", "r").read())
raw_cipher_data = b64decode(cipher_text)
decrypted = rsakey.decrypt(raw_cipher_data)

But I'm getting unreadable characters.

Whys am I getting unreadable characters? Can any one help me with this?

Thanks in advance.

jww
  • 97,681
  • 90
  • 411
  • 885
MeNotMe
  • 147
  • 9

1 Answers1

0

Here is a full working example for encrypting the plaintext in C++ and decrypting it in Python:

Prerequisites

  • You have generated an RSA key pair (reference).

  • You have a recent version of crypto++ (I am using 8.2.0) and you have applied the PEM patch (reference).

  • You have a recent version of pycryptodome (I am using 3.9.8). pycryptodome is a drop-in replacement for the no-longer maintained pycrypto package (reference).

Encryption

Your C++ does the right thing. For the sake of completeness, I extended your code with the necessary header includes and the deserialization of the public key:

#include <cryptopp/base64.h>
#include <cryptopp/files.h>
#include <cryptopp/filters.h>
#include <cryptopp/osrng.h>
#include <cryptopp/pem.h>
#include <cryptopp/rng.h>
#include <cryptopp/rsa.h>

#include <iostream>

int main(int argc, char **argv) {

  CryptoPP::AutoSeededRandomPool prng{};

  std::string plain{"Text123"};

  /**
   * Read public key in PEM format.
   */
  CryptoPP::FileSource fs{"public.pem", /*pumpAll=*/true};
  CryptoPP::RSA::PublicKey publicKey{};
  PEM_Load(fs, publicKey);

  std::string encrypted{};

  /**
   * Pump plain text through RSA encryption scheme with OAEP/SHA1 padding.
   *
   * In general, manual memory allocations should be avoided. However,
   * the CryptoPP API expects us to allocate memory for each transformer and
   * then pass the pointer to the next transformer, which then takes ownership
   * of the pointer and will free it. This design obviously predates
   * modern C++ smart pointers, which should be preferred when possible.
   */
  CryptoPP::RSAES_OAEP_SHA_Encryptor cipher{publicKey};
  auto *encoder{
      new CryptoPP::Base64Encoder{new CryptoPP::StringSink{encrypted}}};
  auto *encryptor{new CryptoPP::PK_EncryptorFilter{prng, cipher, encoder}};
  CryptoPP::StringSource ss{plain, /*pumpAll=*/true, encryptor};

  std::cout << encrypted;

  return 0;
}

Decryption

In your Python code you are not specifying the padding scheme. Since your C++ code uses OAEP/SHA1 padding, you also have to specify this padding scheme in your Python code:

from base64 import b64decode

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Hash import SHA1

rsa_key = None
encrypted = None

with open("key.pem", "r") as f:
  rsa_key = RSA.importKey(f.read())

with open("encrypted", "r") as f:
  encrypted = b64decode(f.read())

cipher = PKCS1_OAEP.new(rsa_key, hashAlgo=SHA1)
decrypted = cipher.decrypt(encrypted)

print(decrypted)