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

如何用Java将secp256k1曲线的ECDSA压缩公钥转换为PEM格式?

将secp256k1压缩ECDSA公钥转换为PEM格式的Java实现

要把secp256k1曲线的压缩ECDSA公钥转成PEM格式,核心是正确解析压缩公钥、生成符合ASN.1标准的SubjectPublicKeyInfo结构,再编码为PEM格式。以下是可行的实现方案:

依赖准备

需要引入BouncyCastle作为加密 provider(JDK原生对secp256k1的支持有限),如果用Maven,添加依赖:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>

完整实现代码

import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;

import java.io.StringWriter;
import java.security.KeyFactory;
import java.security.Security;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;

public class CompressedPubKeyToPem {

    public static void main(String[] args) throws Exception {
        // 示例压缩公钥
        String compressedPubKeyHex1 = "0252972572d465d016d4c501887b8df303eee3ed602c056b1eb09260dfa0da0ab2";
        String compressedPubKeyHex2 = "0318ed2e1ec629e2d3dae7be1103d4f911c24e0c80e70038f5eb5548245c475f50";

        // 转换并输出PEM
        System.out.println(convertCompressedPubKeyToPem(compressedPubKeyHex1));
        System.out.println("\n" + convertCompressedPubKeyToPem(compressedPubKeyHex2));
    }

    public static String convertCompressedPubKeyToPem(String compressedPubKeyHex) throws Exception {
        // 1. 将十六进制公钥转为字节数组
        byte[] compressedPubKeyBytes = hexStringToByteArray(compressedPubKeyHex);

        // 2. 注册BouncyCastle Provider
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        // 3. 获取secp256k1曲线参数
        ECNamedCurveParameterSpec curveSpec = ECNamedCurveTable.getParameterSpec("secp256k1");
        ECNamedCurveSpec params = new ECNamedCurveSpec("secp256k1", curveSpec.getCurve(), curveSpec.getG(), curveSpec.getN());

        // 4. 解析压缩公钥为ECPoint
        ECPoint ecPoint = java.security.spec.ECPointUtil.decodePoint(params.getCurve(), compressedPubKeyBytes);

        // 5. 生成ECPublicKey对象
        KeyFactory keyFactory = KeyFactory.getInstance("ECDSA", "BC");
        ECPublicKey publicKey = (ECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, params));

        // 6. 生成SubjectPublicKeyInfo并编码为PEM
        try (StringWriter stringWriter = new StringWriter();
             PemWriter pemWriter = new PemWriter(stringWriter)) {
            PemObject pemObject = new PemObject("PUBLIC KEY", publicKey.getEncoded());
            pemWriter.writeObject(pemObject);
            return stringWriter.toString();
        }
    }

    // 十六进制字符串转字节数组工具方法
    private static byte[] hexStringToByteArray(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }
}

常见问题排查

若之前使用SubjectPublicKeyInfo未得到预期结果,大概率是以下原因:

  • 曲线参数配置错误:必须使用secp256k1的标准曲线参数,不能用其他曲线替代;
  • 压缩公钥解析失败:压缩公钥首字节(02/03)标识y坐标奇偶性,解析时需依赖曲线参数还原完整公钥点;
  • 未注册BouncyCastle:JDK原生不支持secp256k1的命名曲线解析,必须注册该Provider。

内容的提问来源于stack exchange,提问作者menakshisundaram

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 21:32:42