Search code examples
exceptionrsacrypto++

cryptopp plaintext fixed length limit


When i pass initialText86, the code below works as it should. When i pass initialText87 it fails to construct StringSource ss1, and we meet exception invalid argument!

How can i encode string with length 87?

#include <string>
#include <new>

using namespace std;

#include <../pub/cryptopp/rsa.h>
#include <../pub/cryptopp/osrng.h>
#include <../pub/cryptopp/oaep.h>
#include <../pub/cryptopp/sha.h>

using namespace CryptoPP;

AutoSeededRandomPool& rng_get() {
    static AutoSeededRandomPool defRng;
    return defRng;
}

string rsa_encode( const string& plainText, const RSA::PublicKey& pubKey ) {
    RSAES_OAEP_SHA_Encryptor rsaEnc( pubKey );
    string cipherText;
    StringSource ss1( reinterpret_cast< const byte* >( plainText.c_str() ), plainText.size(), true,
        new PK_EncryptorFilter( rng_get(), rsaEnc,
            new StringSink( cipherText )
        ) // PK_EncryptorFilter
    ); // StringSource
    return move( cipherText );
}

string rsa_decode( const string& cipherText, const RSA::PrivateKey& secretKey ) {
    RSAES_OAEP_SHA_Decryptor rsaDec( secretKey );
    string plainText;
    StringSource ss2( reinterpret_cast< const byte* >( cipherText.c_str() ), cipherText.size(), true,
        new PK_DecryptorFilter( rng_get(), rsaDec,
            new StringSink( plainText )
        ) // PK_DecryptorFilter
    ); // StringSource
    return move( plainText );
}

static const size_t keyLength = 1024;
RSA::PrivateKey _secretKey;
RSA::PublicKey  _pubKey;

bool test( const string& initialText ) {
    auto cipherText = rsa_encode( initialText, _pubKey );
    auto plainText = rsa_decode( cipherText, _secretKey );
    return plainText == initialText;
}

int main() {
    _secretKey.GenerateRandomWithKeySize(rng_get(), keyLength );
    new( &_pubKey ) RSA::PublicKey( _secretKey );
    string initialText87 = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
    string initialText86 = "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
    auto testResult = test( initialText87 );
    assert( testResult );
    return testResult ? 0 : -1;
}

Solution

  • The length of data that can be encrypted using RSA is determined primarily by the size of the key you're using. You appear to be using OAEP, so the maximum length is:

    keyLength - 2 - 2 * hashLength
    

    Where keyLength is the length of the RSA modulus in bytes. You're using a 1024 bit key so:

    keyLength = 1024 / 8 = 128
    

    And since you're using OAEP with SHA-1

    hashLength = 20
    

    So the maximum you can encrypt is:

    128 - 2 - 2 * 20 = 86
    

    Which is exactly what your example shows.

    To encrypt more data, you could use a larger RSA key, but RSA really shouldn't be used for encrypting large amounts of data, so is usually used as part of a hybrid cryptosystem where RSA is instead used to encrypt a randomly generated key for a symmetric algorithm like AES, and then the symmetric algorithm is used to encrypt the actual data so avoiding the length limits associated with RSA.