I am using Crypto++ library for cryptography related works. And sub-part of task is to encrypt and decrypt a text. The message can be up to 256 character long containing alphanumeric number spaces dot and special characters.
This piece of code is working for text length is less than or equal to 8. But after that it fails to decrypt the encrypted text.
// g++ -std=c++1y crypto.cpp -I /home/shravan40/cryptopp/build -lcryptopp
#include <iostream>
#include <cryptopp/rsa.h>
#include <cryptopp/integer.h>
#include <cryptopp/osrng.h>
int main(){
// Keys
CryptoPP::Integer n("0xbeaadb3d839f3b5f"), e("0x11"), d("0x21a5ae37b9959db9");
CryptoPP::RSA::PrivateKey privKey;
privKey.Initialize(n, e, d);
CryptoPP::RSA::PublicKey pubKey;
pubKey.Initialize(n, e);
// Encryption
std::string message = "Shravan Kumar";
CryptoPP::Integer m((const byte *)message.data(), message.size());
std::cout << "m: " << m << std::endl;
// m: 126879297332596.
CryptoPP::Integer c = pubKey.ApplyFunction(m);
std::cout << "c: " << std::hex << c << std::endl;
// c: 3f47c32e8e17e291h
// Decryption
CryptoPP::AutoSeededRandomPool prng;
CryptoPP::Integer r = privKey.CalculateInverse(prng, c);
std::cout << "r: " << std::hex << r << std::endl;
// r: 736563726574h
std::string recovered;
recovered.resize(r.MinEncodedSize());
r.Encode((byte *)recovered.data(), recovered.size());
std::cout << "recovered: " << recovered << std::endl;
// recovered: Expected : (Shravan Kumar), Received -> y5��dqm0
return 0;
}
Richard Critten is correct in his comment that usually hybrid encryption is used (an asymmetric cipher such as RSA with a symmetric cipher such as AES).
For these kind of insecure examples though you are usually simply required to split up the plaintext into parts the same size as the modulus n
. So in your case just put every 8 bytes / characters together and use it for a (big endian) number. As the input seems to be ASCII the highest bit of those 8 bytes will always be set to zero, so you should not have any problems encrypting/decrypting. The input for RSA must of course always be less than n
.
You may of course have to think up a smart way of handling the last part of the string.
Notes:
Integer m((const byte *)message.data(), message.size());
If you use message.size()+1
, then the message will include the trailing NULL
. You can use it during decryption to determine where the recovered string ends. Otherwise, you are going to need to track length of the message.
You might also be interested in Raw RSA from the Crypto++ wiki. But as Maarten cautined, its tricky to get right and build into a scheme.
You might consider something using RSA encryption with OAEP or PKCS v1.5 padding. Also see RSA Encryption Schemes on the Crypto++ wiki.
I believe this is undefined behavior:
std::string recovered; recovered.resize(r.MinEncodedSize()); r.Encode((byte *)recovered.data(), recovered.size());
I think you need to use &recovered[0]
to get the non-const pointer. It may be causing your problem.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.