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

如何在Java中用以太坊私钥签名消息?Web3j无对应方法求解

Java实现区块链私钥消息签名(对应ethers的signMessage)

ethers的signMessage遵循EIP-191标准,会给原始消息添加特定前缀后再签名。web3j没有直接封装成单一方法,但可以通过手动构造前缀+消息,结合内置工具类实现完全一致的功能,代码如下:

依赖导入

确保项目引入web3j核心依赖(版本建议4.9.0+):

<!-- Maven示例 -->
<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>core</artifactId>
    <version>4.9.0</version>
</dependency>

实现代码

import org.web3j.crypto.ECKeyPair;
import org.web3j.crypto.Sign;
import org.web3j.utils.Numeric;
import java.nio.charset.StandardCharsets;
import java.math.BigInteger;

public class MessageSigner {
    public static String signMessage(String message, String privateKeyHex) {
        // 构造EIP-191标准签名前缀:"\x19Ethereum Signed Message:\n" + 消息长度
        String prefix = "\u0019Ethereum Signed Message:\n" + message.length();
        byte[] prefixBytes = prefix.getBytes(StandardCharsets.UTF_8);
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);

        // 拼接前缀与原始消息
        byte[] combinedData = new byte[prefixBytes.length + messageBytes.length];
        System.arraycopy(prefixBytes, 0, combinedData, 0, prefixBytes.length);
        System.arraycopy(messageBytes, 0, combinedData, prefixBytes.length, messageBytes.length);

        // 加载私钥并签名
        ECKeyPair keyPair = ECKeyPair.create(new BigInteger(privateKeyHex, 16));
        Sign.SignatureData signatureData = Sign.signMessage(combinedData, keyPair);

        // 拼接r、s、v字节数组,转换为ethers兼容的十六进制签名字符串
        byte[] signatureBytes = new byte[65];
        System.arraycopy(signatureData.getR(), 0, signatureBytes, 0, 32);
        System.arraycopy(signatureData.getS(), 0, signatureBytes, 32, 32);
        signatureBytes[64] = signatureData.getV();

        return Numeric.toHexString(signatureBytes);
    }

    // 测试示例
    public static void main(String[] args) {
        String testMessage = "Hello Blockchain";
        String privateKey = "你的私钥十六进制字符串(支持带/不带0x前缀)";
        String signature = signMessage(testMessage, privateKey);
        System.out.println("签名结果:" + signature);
    }
}

关键说明

  • 必须添加EIP-191前缀:这是和ethers签名结果一致的核心,缺少前缀会导致签名不兼容
  • web3j的Sign.signMessage方法专门处理这类带前缀的消息签名,底层实现了ECDSA签名逻辑
  • 最终签名格式为r(32字节)+s(32字节)+v(1字节)的十六进制字符串,和ethers返回的signature完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:05:20