Web3js

使用 web3j 從簽名中恢復地址

  • March 26, 2022

我已經使用web3js中的以下程式碼片段對數據字元串進行了簽名

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簽署所述字元串的地址

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;
}

但是,生成的地址都不匹配用於創建簽名的地址。

誰能闡明我做錯了什麼?

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

您正在嘗試驗證簽名而不提供經過雜湊處理的消息。這是您需要提供的另一個參數

引用自:https://ethereum.stackexchange.com/questions/55454