You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 21:15:02