Oussaki Oussaki - 9 months ago 69
Android Question

How to Encrypt with RSA in Android using a HEX Public key from php server

Im receiving a public RSA key from my php server in HEX format
Here is an example of RSA public key:


After receiving i tried to use it to encrypt a String Here is my code sample in ANDROID :

try {
String arg = "b74420f5a4d9abfd2072c9d936dd53e2de2aa790822ad1608807bda3e176b335c51902ca2177824198181ce8bea85de132aaea1104fd043e4ad2c0af705bda966b5d2f92a6ab5170d161eb1e8f7a6b1d5fba673f8a4dcebe55407ef9707782c91b17527af820a2c3a3b586341ae54ef03739074d4738e3ff35257bdfb9233c53";

byte[] bytes = org.apache.commons.codec.binary.Hex.decodeHex(arg.toCharArray());
System.out.println(new String(bytes, "UTF-8"));

String message = "oussaki";

byte[] publicBytes = org.apache.commons.codec.binary.Hex.decodeHex(arg.toCharArray());

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
try {

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
// Encrypt the message
byte[] encryptedBytes = null;
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);

encryptedBytes = cipher.doFinal(message.getBytes());

byte[] b2 = new byte[encryptedBytes.length + 1];
b2[0] = 1;
System.arraycopy(encryptedBytes, 0, b2, 1, encryptedBytes.length);
String s = new BigInteger(b2).toString(36);
System.out.println("Encrypted text" + s);

} catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException
| NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeySpecException k) {
} catch (DecoderException e) {

After running the code it shows that invalid key format

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format

This error shows when generating the public key

Answer Source

First of all, that is not an RSA public key in any format I know of, and certainly not in the format expect by the X509EncodedKeySpec class. It looks like the raw dump of an RSA modulus. You are missing the public exponent. One might guess that the exponent is 65537, but you need to verify that.

You can turn your RSA modulus into a BigInteger by using the sign-magnitude BigInteger constructor, and then create an RSA public key via the RSAPublicKeySpec class, not the X509EncodedKeySpec class. Here are few lines by way example using your code as a basis:

byte[] publicBytes = org.apache.commons.codec.binary.Hex.decodeHex(arg.toCharArray());

BigInteger modulus = new BigInteger(1, publicBytes);
BigInteger publicExponent = BigInteger.valueOf(65537L);

RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);

Another issue: You are using defaults in Cipher.getInstance(). Don't do that. Find out what RSA padding scheme is expected by the server and specify that explicitly. For example, instead of Cipher.getInstance("RSA") you might have




depending on what the server expects.