While serializing the Modulus
component of RSAPublicKey
in Java or Android, you might run into issues. Normally, you would expect getModulus
from 2048 bit RSAKey
converted to byte array to give you a 256 byte key.
final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
final KeyPair rsaKey = generator.generateKeyPair();
final RSAPublicKey publicKey = (RSAPublicKey) rsaKey.getPublic();
final byte[] modulus = publicKey.getModulus().toByteArray();
System.out.println("Length of modulus = " + modulus.length); // Prints 257
The strange thing is that the length of modulus turns out to be 257 (instead of 256). We all know that all cryptographic keys are multiples of 8. Then why does Java generate a cryptographic key of 257 bytes? To troubleshoot this, you need to understand the logic of modulus and its selization.
The Modulus
of an RSAKey
is represented by a BigIntiger
. 256-bit modulus is unsigned
whereas BigInteger.toByteArray()
returns the signed representation of the value. The most significant bit of BigInteger.toByteArray()
is the sign bit. Since the BigInteger
here represents a 256-bit modulus, which will always be positive, the leftmost bit always turns out to be zero.
To solve the problem, you can write a trim method that removes the most significant bit with value zero from the byte array.
public static byte[] trim(byte[] array)
{
if (array[0] == 0) {
array = Arrays.copyOfRange(array, 1, array.length);
}
return array;
}
Overall, the final solution looks like this:
final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
final KeyPair rsaKey = generator.generateKeyPair();
final RSAPublicKey publicKey = (RSAPublicKey) rsaKey.getPublic();
final byte[] modulus = trim(publicKey.getModulus().toByteArray());
System.out.println("Length of modulus = " + modulus.length); // Prints 256