2

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;
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Shravan40
  • 8,922
  • 6
  • 28
  • 48
  • 4
    You don't normally use PKI to encrypt a message directly as the message will be limited to the key length. You should use a symmetric algorithm (such as AES in CBC mode) to encrypt the message text. Then use the public key to encrypt the symmetric key. – Richard Critten Feb 05 '17 at 00:10
  • 1
    Also see [RSA Cryptography](http://www.cryptopp.com/wiki/RSA_Cryptography) on the Crypto++ wiki. – jww Feb 05 '17 at 13:17

2 Answers2

4

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:

  • In case it hasn't been told (yet): raw RSA without padding is not secure either. So it is not just the key size that would be a problem if this example would be implemented in the field.
  • I haven't got a clue what you're doing with regard to decryption. You should have a look at your textbook again I suppose.
Community
  • 1
  • 1
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • I was just preparing to add some of the notes. Then I thought, let me scroll down to see if Maarten has visited the question :) – jww Feb 05 '17 at 10:30
  • @jww I still visit SO now and then, but I'm doing less and less here, focussing on crypto.SE instead. It's starting to be a bit repetitive here with encoding issues and conversion questions. Rook has a point as well with regards to most of the SO examples on crypto being not/not so secure. Still, I got [a bear](http://stackoverflow.com/tags/cryptography/topusers) (and [an erickson](http://stackoverflow.com/tags/encryption/topusers)) to beat :) – Maarten Bodewes Feb 05 '17 at 12:46
2
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.

jww
  • 97,681
  • 90
  • 411
  • 885