Reputation: 355
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!
Upvotes: 5
Views: 17993
Reputation: 2354
Here is a demo function I wrote when I first did RSA encryption and decryption with Crypto++. I wrote it just to understand the basics. I hope it helps:
#include <cryptopp/files.h>
#include <cryptopp/modes.h>
#include <cryptopp/osrng.h>
#include <cryptopp/rsa.h>
#include <cryptopp/sha.h>
using namespace CryptoPP;
void rsa_examples()
{
// Keys created here may be used by OpenSSL.
//
// openssl pkcs8 -in key.der -inform DER -out key.pem -nocrypt
// openssl rsa -in key.pem -check
AutoSeededRandomPool rng;
// Create a private RSA key and write it to a file using DER.
RSAES_OAEP_SHA_Decryptor priv( rng, 4096 );
TransparentFilter privFile( new FileSink("rsakey.der") );
priv.DEREncode( privFile );
privFile.MessageEnd();
// Create a private RSA key and write it to a string using DER (also write to a file to check it with OpenSSL).
std::string the_key;
RSAES_OAEP_SHA_Decryptor pri( rng, 2048 );
TransparentFilter privSink( new StringSink(the_key) );
pri.DEREncode( privSink );
privSink.MessageEnd();
std::ofstream file ( "key.der", std::ios::out | std::ios::binary );
file.write( the_key.data(), the_key.size() );
file.close();
// Example Encryption & Decryption
InvertibleRSAFunction params;
params.GenerateRandomWithKeySize( rng, 1536 );
std::string plain = "RSA Encryption", cipher, decrypted_data;
RSA::PrivateKey privateKey( params );
RSA::PublicKey publicKey( params );
RSAES_OAEP_SHA_Encryptor e( publicKey );
StringSource( plain, true, new PK_EncryptorFilter( rng, e, new StringSink( cipher )));
RSAES_OAEP_SHA_Decryptor d( privateKey );
StringSource( cipher, true, new PK_DecryptorFilter( rng, d, new StringSink( decrypted_keydata )));
assert( plain == decrypted_data );
}
Upvotes: 3
Reputation: 102376
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.
Upvotes: 5