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

基于web3j 5.0.0,如何在Java Spring Boot中压缩以太坊公钥?

以太坊未压缩公钥转压缩格式(web3j 5.0.0)

由于web3j 5.0.0没有内置的公钥压缩方法,你可以通过以下两种方式实现需求:

方法一:利用BouncyCastle库(web3j已依赖)

web3j底层依赖BouncyCastle,可直接用它的椭圆曲线工具类处理:

import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9IntegerConverter;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.math.ec.ECPoint;
import org.web3j.utils.Hex;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Arrays;

// 生成密钥对并获取未压缩公钥
ECKeyPair ecKeyPair = Keys.createEcKeyPair();
BigInteger publicKey = ecKeyPair.getPublicKey();

// 以太坊使用secp256k1曲线
X9ECParameters curveParams = CustomNamedCurves.getByName("secp256k1");

// 将BigInteger公钥拆分为32字节的x、y坐标字节数组
BigInteger x = publicKey.shiftRight(256);
BigInteger y = publicKey.and(new BigInteger("2").pow(256).subtract(BigInteger.ONE));
byte[] xBytes = convertTo32Bytes(x);
byte[] yBytes = convertTo32Bytes(y);

// 构造ECPoint并生成压缩格式编码
ECPoint point = curveParams.getCurve().createPoint(new BigInteger(1, xBytes), new BigInteger(1, yBytes));
byte[] compressedPubKeyBytes = point.getEncoded(true); // true表示压缩格式

// 转成十六进制字符串(用于目标场景)
String compressedPublicKey = Hex.toHexString(compressedPubKeyBytes);

辅助方法:确保坐标是32字节长度

private static byte[] convertTo32Bytes(BigInteger value) {
    byte[] bytes = value.toByteArray();
    if (bytes.length == 32) {
        return bytes;
    } else if (bytes.length > 32) {
        return Arrays.copyOfRange(bytes, bytes.length - 32, bytes.length);
    } else {
        byte[] padded = new byte[32];
        System.arraycopy(bytes, 0, padded, 32 - bytes.length, bytes.length);
        return padded;
    }
}

方法二:手动实现压缩逻辑

直接解析公钥的x、y坐标,根据y的奇偶性添加前缀:

import org.web3j.utils.Hex;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Arrays;

ECKeyPair ecKeyPair = Keys.createEcKeyPair();
BigInteger publicKey = ecKeyPair.getPublicKey();

// 拆分x和y坐标
BigInteger x = publicKey.shiftRight(256);
BigInteger y = publicKey.and(new BigInteger("2").pow(256).subtract(BigInteger.ONE));

// 生成压缩公钥前缀:y为偶数用02,奇数用03
byte prefix = y.testBit(0) ? (byte) 0x03 : (byte) 0x02;

// 将x转成32字节数组
byte[] xBytes = convertTo32Bytes(x);

// 拼接前缀和x字节得到压缩公钥
byte[] compressedPubKeyBytes = ByteBuffer.allocate(33)
        .put(prefix)
        .put(xBytes)
        .array();

// 转十六进制字符串
String compressedPublicKey = Hex.toHexString(compressedPubKeyBytes);

两种方法生成的压缩公钥均以02或03开头,可直接用于你的目标场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 19:31:35