Web3js
使用 web3j 從簽名中恢復地址
我已經使用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
您正在嘗試驗證簽名而不提供經過雜湊處理的消息。這是您需要提供的另一個參數