3

I am using web3j to verify message signatures but there are some false negative results.

For example this signature should be right, but it seems like the address could not be recovered:

     final String address = "0x638aF69053892CDD7Ad295fC2482d1a11Fe5a9B7";
     final String signature = "0x6c26935cc03e4e93c0bd1c3d068a54eb961bbc7db4ecf6c7b55b5b9bb073d32b61fcabeabd028322401ea62202726b520b84fd27aa7f8a8050dff728e064cebf1c";
     final String message = "5893";

    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 SignatureData sd = new 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;
    }
}

I am still new in this area.

1 Answer 1

1

This should help you:

public static String getAddressUsedToSignHashedMessage(String signedHash, String originalMessageHashInHex) throws SignatureException {
        byte[] messageHashBytes = Numeric.hexStringToByteArray(originalMessageHashInHex);
        String r = signedHash.substring(0, 66);
        String s = "0x"+signedHash.substring(66, 130);
        String v = "0x"+signedHash.substring(130, 132);
        System.out.println();
        byte[] msgBytes = new byte[GETH_SIGN_PREFIX.getBytes().length + messageHashBytes.length];
        byte[] prefixBytes = GETH_SIGN_PREFIX.getBytes();
        System.arraycopy(prefixBytes, 0, msgBytes, 0, prefixBytes.length);
        System.arraycopy(messageHashBytes, 0, msgBytes, prefixBytes.length, messageHashBytes.length);
        String pubkey = Sign.signedMessageToKey(msgBytes,
                new Sign.SignatureData(Numeric.hexStringToByteArray(v)[0],
                        Numeric.hexStringToByteArray(r),
                        Numeric.hexStringToByteArray(s)))
                .toString(16);
        System.out.println("");
        System.out.println("Pubkey: " + pubkey);
        String address = Keys.getAddress(pubkey);
        return address;
    }

Reference: https://gist.github.com/megamattron/94c05789e5ff410296e74dad3b528613

1
  • Thank you, interesting solution. But I have a question only for clarity. What should be the value of original message? The nonce generated, right? Thank you in advance Commented May 8, 2023 at 9:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.