我在属性文件中有一个未格式化的公钥,这意味着它只包含公钥hexa值:
K_PUB_CCE = 3082010902820100A515281FAC9ABAA8E966DC1B6EC0F1C431674B4E7BCB718955A34211D5CC6BA53F2C93F67C030A970D4E41341949E6BC3F9336287EEA21702FE663C83D4BAFEE2AAA2EEE7A6AFDC423A159D420E42ABDE2792080249C5D6E25367F804333665CAFB79FD5A59D70B9F69159F4EDAD2DA4B434F41D0EC5217808E7D91FF547C83774E4BDE813302E16377156E52CAF02D1E68371D536AA0E7E32DE484FF4863538DCBC69E8D3E3C1F3CECEA9861DA5516A06D3208F6363B86CF66641BE18C4F41ABD7F1B5CDC9BD964914515DDC58F32F49437BD7E89431C8F484BBCEBA86A5FFF74E01D12E6D1D7EBBF6E5DCD7A9134BF27185F4BD347B23007FF366C0009E14F0203010001
正如你所看到的,它长达538个。我想要实现的是获得具有此值的 java.security.PublicKey 。
但使用此方法时:
private PublicKey createPublicKey(String stringPublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] bytesKey= Hex.decodeHex(stringPublicKey.toCharArray());
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(bytesKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(encodedKeySpec);
}
我得到以下异常:
java.security.InvalidKeyException: IOException: algid parse error, not a sequence
我做错了什么?我应该使用其他任何关键规范类吗?
答案 0 :(得分:5)
将公钥存储为base64字符串然后将其转换回来是非常麻烦的(因为根据平台格式可能会有所不同)。使用KeyStore文件会容易得多。
如果这不是您的选择,还有另一种方法。您需要输入您的密钥(模数)和使用的指数。指数通常是65537,但也有一些方法可以找到它(参见参考资料)。这对我有用:
public static void main(String[] args) {
try{
// example key generated via: $ openssl genrsa -out tmp-key.pem 2048
// modulus and exponent extracted via: $ openssl rsa -text -in tmp-key.pem
// (modulus 514 hex long)
String pubModulus = "00e45679a14c6cbd4646bbe90b3c820eb19fe8366822ce2e4beed9d158b9e8863bdc4e3f0fbad31144ef193493dff8619a5aaa7504541c5d97c20cd29c87435eb2e4fbbab8e3b02d82353016c91e971e8d497e1699eeb77a833833617369333c4d0d93cd6f1a9e6090fafd4cbf00b1e0fc6478003ed6e762fb921446c84f0f281117e692a5f76e4b75cbb1252436b3268893195d25344cc3e5d5a52560243d62e5ce8a7bd72a89fce5fbf009435901e274c3cca5eab0f2b2057683ed6e3ed851723adbabb4028a7900ddc46d8c894097c07ab071f6af8fc1c520681e0abd7685f4851d360a7c6d425373da806d356a517ae764093e6999d2cc9305f46a7e1744ed";
String pubExp = "65537"; // most common exponent is 65537 which encodes to AQAB
PublicKey key = createPublicKey(pubModulus, pubExp);
byte[] data = encrypt("Secret Message", key);
System.out.println(""+data.length); // prints "256" in this example code
} catch(Exception e) {
e.printStackTrace();
}
}
public static PublicKey createPublicKey(String stringPublicKey, String exponentString) throws NoSuchAlgorithmException, InvalidKeySpecException {
try{
// for key modulus and exponent value as base64 encoded string from key file
//BigInteger keyInt = new BigInteger(Base64.getDecoder().decode(stringPublicKey.getBytes("UTF-8")));
//BigInteger exponentInt = new BigInteger(Base64.getDecoder().decode(exponentString.getBytes("UTF-8")));
// for key modulus and exponent values as hex and decimal string respectively
BigInteger keyInt = new BigInteger(stringPublicKey,16); // hex base
BigInteger exponentInt = new BigInteger(exponentString,10); // decimal base
RSAPublicKeySpec keySpeck = new RSAPublicKeySpec(keyInt, exponentInt);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpeck);
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] encrypt(String message, PublicKey key) {
try{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] data = cipher.doFinal(message.getBytes());
return data;
} catch(Exception e) {
e.printStackTrace();
}
return new byte[1];
}
修改强>
对不起,我刚看到你使用的是十六进制字符串。原始RSA格式应该是一些base64编码值。由于您已经具有十六进制值,因此模数的BigInteger创建应该不同(请参阅源代码编辑)。 同样如下面的注释中所述,Hex字符串或Base64格式不会出现平台问题。这里唯一需要注意的是,当使用getBytes()从String编译为Base64时,要指定一种格式(例如UTF-8)。如果未指定格式,则将使用平台默认值。
<强>参考文献:强>
Convert RSA Hex String to PublicKey
答案 1 :(得分:1)
你所拥有的是几乎 PKCS#1 public key的DER编码的十六进制编码。这与X509EncodedKeySpec类处理的SubjectPublicKeyInfo不同。我说差不多因为编码有点错误。模数被编码为负整数,这是错误的。
处理此问题的最简单方法是手动分解模数和指数,如下面的小例子中使用十六进制字符串。
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
public class ProcessPKCS1RSAPublicKey {
public static void main(String[] args) throws Exception {
String modulusHex = "A515281FAC9ABAA8E966DC1B6EC0F1C431674B4E7BCB718955A34211D5CC6BA53F2C93F67C030A970D4E41341949E6BC3F9336287EEA21702FE663C83D4BAFEE2AAA2EEE7A6AFDC423A159D420E42ABDE2792080249C5D6E25367F804333665CAFB79FD5A59D70B9F69159F4EDAD2DA4B434F41D0EC5217808E7D91FF547C83774E4BDE813302E16377156E52CAF02D1E68371D536AA0E7E32DE484FF4863538DCBC69E8D3E3C1F3CECEA9861DA5516A06D3208F6363B86CF66641BE18C4F41ABD7F1B5CDC9BD964914515DDC58F32F49437BD7E89431C8F484BBCEBA86A5FFF74E01D12E6D1D7EBBF6E5DCD7A9134BF27185F4BD347B23007FF366C0009E14F";
BigInteger modulus = new BigInteger(modulusHex, 16);
String exponentHex = "010001";
BigInteger exponent = new BigInteger(exponentHex, 16);
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory keyFac = KeyFactory.getInstance("RSA");
RSAPublicKey rsaPub = (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
System.out.println(rsaPub);
}
}