Given an java.security.interfaces.RSAKey, how do I get it's size?
-
1dont double post : http://stackoverflow.com/questions/2921508/trying-to-understand-java-rsa-key-size – leonbloy May 27 '10 at 16:06
4 Answers
You could try this:
key.getModulus().bitLength();

- 71,481
- 13
- 158
- 186
-
Beware, this strategy can fail if your key has eight leading zeros. Unfortunately there are interop cases where picking a power of two is necessary. If you try to import a public key generated by Java into .Net and use it to encrypt data, it will not decrypt in Java unless the key length matches expectations. If you generated a 2048-bit key, you cannot give .Net a key with 2040 bits (8 leading zeros in key case) or 2052 bits (if you turn the BigInteger into a hex string you can get an extra leading 0). You must give it exactly 2048 bits. It affects OAEP padding schemes. – Wheezil Mar 02 '19 at 20:20
-
As explained in https://stackoverflow.com/questions/11729893/data-encrypted-in-c-sharp-is-1-byte-too-long-to-be-decrypted-in-java – Wheezil Mar 02 '19 at 20:24
(EDIT: I wrote this response before I understood the restrictions placed on the prime integers that are generated for an RSA key. http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf I now believe that any good key generator should ensure that the modulus is between 2^(n-1) and 2^n-1. Thus the minimal two's-complement representation of the modulus will always have exactly the number of bits that were specified for the key length at the time of key creation. So, for example, if you create a 2048-bit key, then key.getModulus().bitLength() will always return 2048.)
Pardon, but doesn't key.getModulus().bitLength()
return an incorrect value when the most significant bit of the modulus is a 0? For example, for a 2048-bit key, if the most significant bit of the modulus is 0, then key.getModulus().bitLength()
will return 2047 (or less if more bits are 0). I would think the desired result in such a case would actually be 2048.
The documentation for BigInteger.bitLength() reads as follows:
Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit. For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation. (Computes (ceil(log2(this < 0 ? -this : this+1))).)
I am afraid that one needs to make some assumptions about what sizes the key could be. You'll have to assume, for example, that you will only ever see 1024, 2048, or 4096-bit keys and then do something like:
int keySize;
int bitLength = key.getModulus().bitLength();
if (bitLength <= 512) {
throw new IllegalArgumentException(...)
}
else if (bitLength <= 1024) {
keySize = 1024;
}
else if (bitLength <= 2048) {
keySize = 2048;
}
else if (bitLength <= 4096) {
keySize = 4096;
}
else {
throw new IllegalArgumentException(...)
}
return keySize;
This code can still be wrong on the (VERY rare) occasion, for example, when the first 1048 bits of a 2048 bit key are all 0. I think that is not something to worry about, though.

- 397
- 3
- 12
-
This code is wrong on every occasion. `key.getModulus().bitLength()` IS the value defined by the "key size" or "key length" terms. Replacing it with arbitrary chosen values is plain wrong. – Oleg Estekhin Jul 07 '14 at 06:29
-
Oleg, you're right, of course. I added the EDIT to explain my misunderstanding about restrictions on the prime factors that go into key generation. – John L Oct 24 '14 at 21:52
-
If still paranoid over lousy key generators, one may use rounding up: keySize = ((bitLength + 127)/128)*128. Better than guessing. And the chance of high 128 bits being all zeros is, well, on the order of 1 in 2^128. – Seva Alekseyev Nov 14 '15 at 19:49
-
1Unfortunately there are interop cases where picking a power of two is necessary. If you try to import a public key generated by Java into .Net and use it to encrypt data, it will not decrypt in Java unless the key length matches expectations. If you generated a 2048-bit key, you cannot give .Net a key with 2040 bits (8 leading zeros in key case) or 2052 bits (if you turn the BigInteger into a hex string you can get an extra leading 0). You must give it exactly 2048 bits. This doesn't always cause error, but it affects OAEP padding schemes. – Wheezil Mar 02 '19 at 20:19
-
As explained in https://stackoverflow.com/questions/11729893/data-encrypted-in-c-sharp-is-1-byte-too-long-to-be-decrypted-in-java – Wheezil Mar 02 '19 at 20:24
The size of an RSA key is the number of bits in its modulus, so you want
myRSAKey.getModulus().bitLength()
.

- 50,258
- 9
- 107
- 126
I share Wheezil's concerns mentioned in the accepted answer. A modulus with 8 leading 0-bits will break the approach. This has a 0.4% chance of occurring, which is unacceptable in my opinion. So I personally use this instead:
Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, yourKey);
int keyBitSize = rsa.getOutputSize(0) * Byte.SIZE;
...since RSA output size is always the same size as the key's modulus, even with 0-length input.

- 3,892
- 17
- 31