Oussaki Oussaki - 1 month ago 16
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:

b74420f5a4d9abfd2072c9d936dd53e2de2aa790822ad1608807bda3e176b335c51902ca2177824198181ce8bea85de132aaea1104fd043e4ad2c0af705bda966b5d2f92a6ab5170d161eb1e8f7a6b1d5fba673f8a4dcebe55407ef9707782c91b17527af820a2c3a3b586341ae54ef03739074d4738e3ff35257bdfb9233c53


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());
System.out.println(encryptedBytes);

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) {
k.printStackTrace();
}
} catch (DecoderException e) {
e.printStackTrace();
}


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

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

Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding")

or

Cipher.getInstance("RSA/ECB/PKCS1Padding")

depending on what the server expects.

Comments