首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用web3j从签名中恢复地址

使用web3j从签名中恢复地址
EN

Ethereum用户
提问于 2018-07-30 12:48:54
回答 3查看 3.1K关注 0票数 5

我在web3js中使用以下代码片段签名了一个数据字符串

代码语言:javascript
复制
var data = "hello world";

web3.personal.sign(web3.fromUtf8(data), web3.eth.accounts[0], function(error, result) {
    if (!error) {
        console.log(data);
    } else {
        console.log(error);
    }
});

现在,我正在尝试验证用于从web3j签名said字符串的地址。

代码语言:javascript
复制
public static boolean verifyAddressFromSignature(String address, String signature) 
{
    byte[] signatureBytes = Hash.sha3(signature).getBytes();
    byte v = signatureBytes[64];
    if(v < 27) 
    { 
        v += 27; 
    }

    SignatureData sd = new SignatureData(v, (byte[]) Arrays.copyOfRange(signatureBytes, 0, 32), (byte[]) Arrays.copyOfRange(signatureBytes, 32, 64));

    String addressRecovered = null;
    boolean match = false;

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

        if (publicKey != null) 
        {
            addressRecovered = "0x" + Keys.getAddress(publicKey); 
            System.out.println(addressRecovered);
            if (addressRecovered.equals(address)) 
            {
                match = true;
                break;
            }
        }
    }

    return match;
}

但是,生成的地址中没有一个与用于创建签名的地址相匹配。

有人能说明我做错了什么吗?

EN

回答 3

Ethereum用户

发布于 2022-03-26 14:02:08

下面是我编写的一个实现,它的工作方式与JavaScript、ethers.utils.verifyMessage(message, signature)ethers.utils.recoverAddress(digest, signature)方法完全一样。

EthersUtils.java

代码语言:javascript
复制
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

import org.web3j.crypto.ECDSASignature;
import org.web3j.crypto.Hash;
import org.web3j.crypto.Keys;
import org.web3j.crypto.Sign;
import org.web3j.crypto.Sign.SignatureData;
import org.web3j.utils.Numeric;

public class EthersUtils {
  private static final String MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n";

  public static String verifyMessage(String message, String signature) {
    return EthersUtils.recoverAddress(EthersUtils.hashMessage(message), signature);
  }

  public static String hashMessage(String message) {
    return Hash.sha3(
        Numeric.toHexStringNoPrefix(
            (EthersUtils.MESSAGE_PREFIX + message.length() + message).getBytes(StandardCharsets.UTF_8)));
  }

  public static String recoverAddress(String digest, String signature) {
    SignatureData signatureData = EthersUtils.getSignatureData(signature);
    int header = 0;
    for (byte b : signatureData.getV()) {
      header = (header << 8) + (b & 0xFF);
    }
    if (header < 27 || header > 34) {
      return null;
    }
    int recId = header - 27;
    BigInteger key = Sign.recoverFromSignature(
        recId,
        new ECDSASignature(
            new BigInteger(1, signatureData.getR()), new BigInteger(1, signatureData.getS())),
        Numeric.hexStringToByteArray(digest));
    if (key == null) {
      return null;
    }
    return ("0x" + Keys.getAddress(key)).trim();
  }

  private static SignatureData getSignatureData(String signature) {
    byte[] signatureBytes = Numeric.hexStringToByteArray(signature);
    byte v = signatureBytes[64];
    if (v < 27) {
      v += 27;
    }
    byte[] r = (byte[]) Arrays.copyOfRange(signatureBytes, 0, 32);
    byte[] s = (byte[]) Arrays.copyOfRange(signatureBytes, 32, 64);
    return new SignatureData(v, r, s);
  }
}
票数 2
EN

Ethereum用户

发布于 2021-11-09 03:43:47

代码语言:javascript
复制
package org.web3j.crypto;

import java.math.BigInteger;
import java.util.Arrays;

import org.junit.jupiter.api.Test;

import org.web3j.crypto.Sign.SignatureData;
import org.web3j.utils.Numeric;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class ECRecoverTest {

    public static final String PERSONAL_MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n";

    @Test
    public void testRecoverAddressFromSignature() {

        String signature =
                "0x2c6401216c9031b9a6fb8cbfccab4fcec6c951cdf40e2320108d1856eb532250576865fbcd452bcdc4c57321b619ed7a9cfd38bd973c3e1e0243ac2777fe9d5b1b";

        String address = "0x31b26e43651e9371c88af3d36c14cfd938baf4fd";
        String message = "v0G9u7huK4mJb2K1";

        String prefix = PERSONAL_MESSAGE_PREFIX + message.length();
        byte[] msgHash = Hash.sha3((prefix + message).getBytes());

        byte[] signatureBytes = Numeric.hexStringToByteArray(signature);
        byte v = signatureBytes[64];
        if (v < 27) {
            v += 27;
        }

        SignatureData sd =
                new SignatureData(
                        v,
                        (byte[]) Arrays.copyOfRange(signatureBytes, 0, 32),
                        (byte[]) Arrays.copyOfRange(signatureBytes, 32, 64));

        String addressRecovered = null;
        boolean match = false;

        // Iterate for each possible key to recover
        for (int i = 0; i < 4; i++) {
            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;
                }
            }
        }

        assertEquals(addressRecovered, (address));
        assertTrue(match);
    }
}

https://github.com/web3j/web3j/blob/master/crypto/src/test/java/org/web3j/crypto/ECRecoverTest.java

票数 1
EN

Ethereum用户

发布于 2019-03-19 13:53:35

您正在试图验证签名,而不提供消息的哈希。这是您需要提供的另一个参数

票数 0
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/55454

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档