↓ 跳过正文

基于Web3j做账号签名认证

正能量 1 分钟阅读 更新于 2026-10-18

解释 Web3j 签名验签示例中的消息恢复流程,并补充字符编码和防重放的检查点。

基于Web3j做账号签名认证:原站配图。

废话不多说,直接贴代码
#

public class Web3jUtils {
    public static boolean isSignatureValid(final String address, final String signature, final String message) {
        log.info("isSignatureValid invoked for Address {} with Signature {} and Message {} ", address, signature,
                message);

        final String personalMessagePrefix = "\u0019Ethereum Signed Message:\n";
        boolean match = false;

        final String prefix = personalMessagePrefix + message.length();
        final byte[] msgHash = Hash.sha3((prefix + message).getBytes());
        final byte[] signatureBytes = Numeric.hexStringToByteArray(signature);
        byte v = signatureBytes[64];
        if (v < 27) {
            v += 27;
        }

        final Sign.SignatureData sd = new Sign.SignatureData(v,
                Arrays.copyOfRange(signatureBytes, 0, 32),
                Arrays.copyOfRange(signatureBytes, 32, 64));

        String addressRecovered = null;

        // Iterate for each possible key to recover
        for (int i = 0; i < 4; i++) {
            final BigInteger publicKey = Sign.recoverFromSignature((byte) i, new ECDSASignature(
                    new BigInteger(1, sd.getR()),
                    new BigInteger(1, sd.getS())), msgHash);

            if (publicKey != null) {
                addressRecovered = "0x" + Keys.getAddress(publicKey);

                if (addressRecovered.equals(address)) {
                    match = true;
                    break;
                }
            }
        }

        return match;
    }
}

补充阅读
#

解释 Web3j 签名验签示例中的消息恢复流程,并补充字符编码和防重放的检查点。

如何理解与使用
#

原代码恢复公钥并与地址比较,处理的是特定消息签名格式;消息长度应按协议要求的编码字节数计算,中文不能简单按字符串字符数代替。

验证与边界
#

登录挑战还应绑定域名、随机数和有效期,验签成功本身不能阻止旧签名重放。验证时覆盖中文消息、非法长度、地址格式与重复使用。

参考:Ethereum 签名数据标准 ERC-191。