How to determine "KeySize" in a RSA::PrivateKey?

673 views
Skip to first unread message

Stu

unread,
Aug 29, 2013, 4:08:46 PM8/29/13
to cryptop...@googlegroups.com
The RSA keysize is the length of the modulus.  If I generate a new key using the GenerateRandomWithKeySize function, then I know what the keySize is because I just set it.  However, if I load the RSA key from a file or some other location, I need a way to determine what the keysize is.

The most direct way would be as follows:

privateKey.GetModulus().ByteCount();

However, this would actually return the number of bytes needed to hold the specific modulus, which could possibly be less than the number of bytes for the maximum modulus.  ie, if I used 256-byte RSA, the random modulus might have all 0's in the last byte and therefore only take up 255 bytes...of course I could round up to the nearest power of 2 but that is messy.

Another way that I know works is this:

CryptoPP::RSA::PrivateKey privateKey;
RSAES_OAEP_SHA_Decryptor decryptor( privateKey );
int keySizeBytes = decryptor.FixedCiphertextLength();

However this is very obtuse and requires creating a high level decryptor object only to be destroyed.  I'd like to find a better way.

From the documentation of PrivateKey here:
http://www.cryptopp.com/docs/ref/class_private_key.html

virtual void GenerateRandom (RandomNumberGenerator &rng, const NameValuePairs &params=g_nullNameValuePairs)
 generate a random key or crypto parameters
void GenerateRandomWithKeySize (RandomNumberGenerator &rng, unsigned int keySize)
 calls the above function with a NameValuePairs object that just specifies "KeySize"

...which would seem to imply that I can look up "KeySize" in the list of NameValuePairs.  However, when I call

privateKey.GetValueNames()

it does not list "KeySize" or anything similar.  I tried the following all of which did not work:

privateKey.GetIntValue( "KeySize", value );
privateKey.GetIntValue( "ModulusSize", value );


Stu

unread,
Aug 29, 2013, 4:19:20 PM8/29/13
to cryptop...@googlegroups.com
Ok, I think I've found the official method....

privateKey.MaxImage().ByteCount();

Jeffrey Walton

unread,
Aug 30, 2013, 10:45:03 AM8/30/13
to cryptop...@googlegroups.com


On Thursday, August 29, 2013 4:08:46 PM UTC-4, Stu wrote:
The RSA keysize is the length of the modulus.  If I generate a new key using the GenerateRandomWithKeySize function, then I know what the keySize is because I just set it.  However, if I load the RSA key from a file or some other location, I need a way to determine what the keysize is.

The most direct way would be as follows:

privateKey.GetModulus().ByteCount();
GetModulus() returns a Crypto++ Integer. Integer has a class method BitCount().

    unsigned int BitCount () const
        number of significant bits = floor(log2(abs(*this))) + 1

http://www.cryptopp.com/docs/ref/class_integer.html.

Jeff

   AutoSeededRandomPool pool;
   
    RSA::PrivateKey k1, k2, k3;
    k1.GenerateRandomWithKeySize(pool, 1023);
    k2.GenerateRandomWithKeySize(pool, 1024);
    k3.GenerateRandomWithKeySize(pool, 1025);
   
    cout << k1.GetModulus().BitCount() << endl;
    cout << k2.GetModulus().BitCount() << endl;
    cout << k3.GetModulus().BitCount() << endl;

    $ ./t.exe
    1023
    1024
    1025

Stu

unread,
Aug 30, 2013, 2:59:51 PM8/30/13
to cryptop...@googlegroups.com
>>GetModulus() returns a Crypto++ Integer. Integer has a class method BitCount().

Yes, but as I noted above, this will sometimes return the wrong value...

When using the high level decryptor

RSAES_OAEP_SHA_Decryptor decryptor( privateKey );

size_t dpl = decryptor.MaxPlaintextLength( ciphertext.size() ); returns 0 if ciphertext.size() does not equal decryptor.FixedCiphertextLength(), which means that any other size is invalid.  The computation is from line 158 in here:

http://www.cryptopp.com/docs/ref/pubkey_8h_source.html
size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();}


So, the official correct value must be returned by
GetTrapdoorFunctionBounds().MaxImage().ByteCount();

Jeffrey Walton

unread,
Aug 31, 2013, 8:38:39 PM8/31/13
to cryptop...@googlegroups.com


On Friday, August 30, 2013 2:59:51 PM UTC-4, Stu wrote:
>>GetModulus() returns a Crypto++ Integer. Integer has a class method BitCount().

Yes, but as I noted above, this will sometimes return the wrong value...
Well, you asked about keysize: "... I need a way to determine what the keysize is." ;)
 
When using the high level decryptor

RSAES_OAEP_SHA_Decryptor decryptor( privateKey );

size_t dpl = decryptor.MaxPlaintextLength( ciphertext.size() ); returns 0 if ciphertext.size() does not equal decryptor.FixedCiphertextLength(), which means that any other size is invalid.  The computation is from line 158 in here:

http://www.cryptopp.com/docs/ref/pubkey_8h_source.html
size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();}
I believe RSAES_OAEP_SHA_Decryptor and friends use InvertibleRSAFunction and RSAFunction. These references might be helpful: http://www.cryptopp.com/docs/ref/class_r_s_a_function.html and http://www.cryptopp.com/docs/ref/class_invertible_r_s_a_function.html.

I believe MaxPreImage() is the maximum plaintext size; and MaxImage() is the maximum ciphertext size. Looking at InvertibleRSAFunction, both return ++(n >> 1) and RSAFunction returns m_n. I don't know how blinding or OAEP affect the values returned.

From the testing below, it looks like both MaxPreImage() and MaxImage() return n-1. That's what I expected.

So, the official correct value must be returned by 
GetTrapdoorFunctionBounds().MaxImage().ByteCount();
What precisely are you looking for?

Message size is a bit different than key size. The message has to be smaller than the modulus, or the modular exponentiation will lose information (m and m_prime will not be equal after the inversion). The message probably cannot be 0 either. But again, I don't know how blinding and OAEP affect that range.

If the plaintext message is too large, Crypto++ will throw an exception.

Jeff

    CryptoPP::InvertibleRSAFunction rsa;
    CryptoPP::AutoSeededRandomPool pool;
    rsa.GenerateRandomWithKeySize(pool, 128);
   
    std::ostringstream ss;
    ss << "n: " << rsa.GetModulus() << std::endl;
    ss << "Preimage: " << rsa.MaxPreimage() << std::endl;
    ss << "Image: " << rsa.MaxImage() << std::endl;
    std::cout << ss.str() << std::endl;

n: 240963096710590365560537833800742742569.
Preimage: 240963096710590365560537833800742742568.
Image: 240963096710590365560537833800742742568.
Reply all
Reply to author
Forward
0 new messages