RAW RSA encryption and decryption with Crypto++

crypto++rsa

I need to establish a secure communication between a PC and a device which supports RSA encryption and signature with SHA1. As I have already used Crypto++ in other parts of my application, I would like to utilize Crypto++ for this as well.

The device is very primitive but allows executing a program I write on it. It has raw RSA and SHAa functions built-in; However, it has very little memory to work with, 2K bytes to be precise.

I have to encrypt and sign a message from a PC. Then the device decrypts and verifies the message. The device will then reply an encrypted message and sign on it. The PC will decrypt the message and verify it afterwards. I have implemented the raw RSA encryption, signature and verification with SHA1 inside the device using the built-in functions. The messages is short enough to be done in a single round.

However, I don't know how to encrypt a message with raw RSA using Crypto++ without involving OAEP or PKCS#1. Could somebody kind enough to show me some sample code? Thanks a ton!

Best Answer

I don't know how to encrypt a message with raw RSA using Crypto++ without involving OAEP or PKCS#1. Could somebody kind enough to show me some sample code?

That's easy enough when you know where to look: Raw RSA from the Crypto++ wiki. The code below was taken from the page.


Encryption

Integer n("0xbeaadb3d839f3b5f"), e("0x11"), d("0x21a5ae37b9959db9");

RSA::PublicKey pubKey;
pubKey.Initialize(n, e);

///////////////////////////////////////////////////////////////

Integer m, c;
string message = "secret";  

cout << "message: " << message << endl;

// Treat the message as a big endian byte array
m = Integer((const byte *)message.data(), message.size());
cout << "m: " << hex << m << endl;

// Encrypt
c = pubKey.ApplyFunction(m);
cout << "c: " << hex << c << endl;

Decryption

Integer n("0xbeaadb3d839f3b5f"), e("0x11"), d("0x21a5ae37b9959db9");
AutoSeededRandomPool prng;

RSA::PrivateKey privKey;
privKey.Initialize(n, e, d);

///////////////////////////////////////////////////////////////

Integer c("0x3f47c32e8e17e291"), r;
string recovered;

// Decrypt
r = privKey.CalculateInverse(prng, c);
cout << "r: " << hex << r << endl;

// Round trip the message
size_t req = r.MinEncodedSize();
recovered.resize(req);
r.Encode((byte *)recovered.data(), recovered.size());

cout << "recovered: " << recovered << endl;

Here's a sample output:

$ ./cryptopp-raw-rsa.exe
message: secret
m: 736563726574h
c: 3f47c32e8e17e291h
r: 736563726574h
recovered: secret

There is one caveat: c = m ^ e mod n, so there are some limits on plaint text size and cipher text size. Essentially, m and c must be smaller than n. In this example, replacing the string secret with now is the time for all good men to come to the aid of their country would fail because it's larger than n when converted to an Integer.

You can get the maximum plain text size with the function MaxPreImage(), and the maximum cipher text size with MaxImage().


I have to encrypt and sign a message from a PC. Then the device decrypts and verifies the message. The device will then reply an encrypted message and sign on it. The PC will decrypt the message and verify it afterwards.

On the surface, this looks like it will suffer replay attacks. You might need a protocol with the protection.

Related Topic