Java中EC secp160r2十六进制公钥字符串转公钥报InvalidKeyException如何解决
问题根因
你当前拿到的80位十六进制字符串解码后是secp160r2算法的裸公钥值,仅包含公钥的X、Y坐标拼接内容,而X509EncodedKeySpec要求输入的是完整的带ASN.1编码头的X509格式公钥字节,直接传入裸字节自然会解码失败。
解决方案
你需要先将裸公钥字节封装为ECPublicKeySpec结构,再通过KeyFactory生成公钥对象,代码实现如下(你项目已经引入BouncyCastle依赖可直接使用):
import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.math.ec.ECPoint; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.ECPublicKeySpec; import java.util.Arrays; // 公钥还原方法 public static PublicKey restoreSecp160r2PublicKey(String pubKeyHex) throws Exception { // 1. 十六进制转40字节裸公钥数组,复用你现有parseHexBinary方法即可 byte[] rawPubKey = parseHexBinary(pubKeyHex); if (rawPubKey.length != 40) { throw new IllegalArgumentException("公钥长度错误,secp160r2非压缩裸公钥应为40字节"); } // 2. 获取secp160r2的曲线参数 ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp160r2"); // 3. 拆分X、Y坐标,生成公钥点对象 byte[] xBytes = Arrays.copyOfRange(rawPubKey, 0, 20); byte[] yBytes = Arrays.copyOfRange(rawPubKey, 20, 40); ECPoint pubPoint = ecSpec.getCurve().createPoint( new java.math.BigInteger(1, xBytes), new java.math.BigInteger(1, yBytes) ); // 4. 生成标准公钥对象 KeyFactory kf = KeyFactory.getInstance("EC", "BC"); return kf.generatePublic(new ECPublicKeySpec(pubPoint, ecSpec)); }
注意事项
如果后续收到的是21字节/42位十六进制的压缩格式公钥,仅需要调整公钥点解析逻辑即可,当前非压缩格式公钥可直接复用上述代码。
内容的提问来源于stack exchange,提问作者M.Mark
相关产品推荐
相关产品推荐

