我想用从HEX格式的php服务器收到的Android中的公共RSA密钥进行加密。 以下是RSA公钥的示例:
b74420f5a4d9abfd2072c9d936dd53e2de2aa790822ad1608807bda3e176b335c51902ca2177824198181ce8bea85de132aaea1104fd043e4ad2c0af705bda966b5d2f92a6ab5170d161eb1e8f7a6b1d5fba673f8a4dcebe55407ef9707782c91b17527af820a2c3a3b586341ae54ef03739074d4738e3ff35257bdfb9233c53收到后我试图用它来加密一个字符串。 这是我在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(); }运行代码后,它显示了一个无效的密钥格式:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format生成公钥时会显示此错误。
I want to encrypt with a public RSA key in Android received from my php server in a HEX format. Here is an example of RSA public key:
b74420f5a4d9abfd2072c9d936dd53e2de2aa790822ad1608807bda3e176b335c51902ca2177824198181ce8bea85de132aaea1104fd043e4ad2c0af705bda966b5d2f92a6ab5170d161eb1e8f7a6b1d5fba673f8a4dcebe55407ef9707782c91b17527af820a2c3a3b586341ae54ef03739074d4738e3ff35257bdfb9233c53After 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 me an invalid key format:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key formatThis error it is shown when generating the public key.
最满意答案
首先,这不是我所知的任何格式的RSA公钥,当然也不是X509EncodedKeySpec类所期望的格式。 它看起来像是RSA模数的原始转储。 你错过了公共指数。 有人可能会猜测指数是65537,但你需要验证它。
您可以使用符号量级BigInteger构造函数将RSA模数转换为BigInteger,然后通过RSAPublicKeySpec类创建RSA公钥,而不是X509EncodedKeySpec类。 以下是使用您的代码作为基础的几行示例:
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);另一个问题:您正在使用Cipher.getInstance()默认值。 不要那样做。 找出服务器期望的RSA填充方案并明确指定。 例如,您可能拥有Cipher.getInstance("RSA")而不是
Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding")要么
Cipher.getInstance("RSA/ECB/PKCS1Padding")取决于服务器期望的内容。
In my code i missed two things :
1 - choosing the right Padding Scheme .
2 - using the two factors N and E to generate the public key
Also my server is expecting a HEX value to be returned i have to convert the Byte array to a HexString
and Here is the full code to do that :
try { String arg = "b74420f5a4d9abfd2072c9d936dd53e2de2aa790822ad1608807bda3e176b335c51902ca2177824198181ce8bea85de132aaea1104fd043e4ad2c0af705bda966b5d2f92a6ab5170d161eb1e8f7a6b1d5fba673f8a4dcebe55407ef9707782c91b17527af820a2c3a3b586341ae54ef03739074d4738e3ff35257bdfb9233c53"; String message = "plain text"; 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); try { // decrypts the message byte[] encryptedBytes = null; Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); encryptedBytes = cipher.doFinal(message.getBytes()); System.out.println( "Encrypted text : "+ convertToHexString(encryptedBytes)); } catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException | NoSuchAlgorithmException k) { k.printStackTrace(); } } catch (DecoderException e) { e.printStackTrace(); }Here is the function to Convert the Byte array to HexString
private static String convertToHexString(byte[] data) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < data.length; i++) { int halfbyte = (data[i] >>> 4) & 0x0F; int two_halfs = 0; do { if ((0 <= halfbyte) && (halfbyte <= 9)) buf.append((char) ('0' + halfbyte)); else buf.append((char) ('a' + (halfbyte - 10))); halfbyte = data[i] & 0x0F; } while(two_halfs++ < 1); } return buf.toString(); }更多推荐
发布评论