-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Signatures differ in web3J and web3js #208
Comments
Behind the scenes, web3.js is using the personal_sign method. If you refer to the specification, you'll see that the message has additional information added to it which invalidates the above comparisons.
It doesn't help that the format of this message is also encoding the length incorrectly - see the following go-ethereum issue. An equivalent implementation to what you've done in JavaScript should be along the lines of this: String privateKey1 = "fba4137335dc20dc23ad3dcd9f4ad728370b09131a6a14abf6c839748700780d";
Credentials credentials = Credentials.create(privateKey1);
System.out.println("Address: " + credentials.getAddress());
String hash = Hash.sha3(Numeric.toHexStringNoPrefix("TEST".getBytes()));
System.out.println("Hash" + hash);
String message = "\\x19Ethereum Signed Message:\n" + hash.length() + hash;
byte[] data = message.getBytes();
Sign.SignatureData signature = Sign.signMessage(data, credentials.getEcKeyPair());
System.out.println("R: " + Numeric.toHexString(signature.getR()));
System.out.println("S: " + Numeric.toHexString(signature.getS()));
System.out.println("V: " + Integer.toString(signature.getV())); EIP 683 is attempting to clean up this mess. |
In case it helps for others, I had to use this prefix string instead:
|
The problem was solved according this commit 4997746 in 4.0.0 release
Just because it does exactly what So here is the code helped me to handle web3j created signature with smart contract
Hope it helps someone :) |
@ChocolateSlayer thanks for the information above. I hope some of this isn't repetition of questions elsewhwere, but I noticed that the Hash.sha3() function doesn't return the same value as Geth, Web3JS or literally any of the other Ethereum libraries out there... at least not following your suggestion above. I have been able to get favorable results with the following:
The resulting hex string ought to be: "0x93b90fab55adf4e98787d33a38e71106e8c016f1a124dfc784f3cca4d938b1af" and with the code I've included here, you're able to do that. If I follow your example above, the hex string is not correct compared to Geth. That aside, I've been trying to follow your instructions to sign a message and then get the hex string value of the signature to use within a Solidity contract. Again, as above, the output from Geth and Web3JS is different from what I'm getting with Web3J. Passing either testMessage to Sign.signPrefixedMessage() or a variation using Numeric.hexStringToByteArray() to create the byte[] variable does not produce a hex string that matches Geth. Can you go a little more in-depth on your explanation above? I'm using 4.0.0, just to be clear, and I have a feeling that there's still not quite something right going on within Web3J here (or perhaps--more likely--I'm just doing something dumb). |
Ok. I think I've got it, at least for my purposes. I was calling:
and then creating a String following the same basic steps above that I used to create the hash variable:
However, this only created a bunch of junk values that didn't match the signature I'm getting from Geth. Instead, I've been able to successfully get the hex string value by doing the following:
There ought to be a method in this library that does this for me! Here's my full code, which creates a hashed message and a signature that match the output of Geth and Web3JS:
In order to obtain the output from web3.personal.sign in Geth, you just need to prune off the 0x on S and then concatenate R, S, and V to achieve desired results. In short, what can be accomplished in just two lines of code in Geth takes a few more here, but at least it finally works. I hope this helps anyone who has been experiencing a similar level of misery. Also, if anyone knows an easier way, I'm listening! 😉 |
is there anyone has the solution. I am using version 4.2.0-android and I am unable to recover the address from the message and R S V component. |
After some jiggery-pokery I've managed to get Web3J producing the exact same signatures as Web3JS like this: byte[] hash = SIGNATURE_MESSAGE.getBytes(StandardCharsets.UTF_8);
Sign.SignatureData signature = Sign.signPrefixedMessage(hash, credentials.getEcKeyPair());
String r = Numeric.toHexString(signature.getR());
String s = Numeric.toHexString(signature.getS());
String v = Integer.toHexString(signature.getV()-27);
StringBuilder builder = new StringBuilder(r);
builder.append(s.substring(2));
if (v.length() == 1) {
builder.append("0");
}
builder.append(v);
String fullSignature = builder.toString(); |
Tried all the solutions above but none of them worked for me. A lot of inconsistencies with types used. I did manage to get things working such that I could take the same message and get the same signature hex back for ether.js, web3j, and MyCrypto.
Message: "Hello"
|
We now have |
For your copy/paste joy, here is an implementation of message signing in web3j that is compatible with Ethers.js and everything else, which uses byte arrays. public byte[] sign(String message, Credentials credentials) {
byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
Sign.SignatureData signature = Sign.signPrefixedMessage(message, credentials.getEcKeyPair());
// Match the signature output format as Ethers.js v5.0.31
// https://github.com/ethers-io/ethers.js/blob/v5.0.31/packages/bytes/src.ts/index.ts#L444-L448
byte[] retval = new byte[65];
System.arraycopy(signature.getR(), 0, retval, 0, 32);
System.arraycopy(signature.getS(), 0, retval, 32, 32);
System.arraycopy(signature.getV(), 0, retval, 64, 1);
return retval;
} |
Hello, I'm using web3J version 2.3.1 and hit following problem. When I sign the same raw message (it's simply string like "TEST" for now) I get different signatures using web3js i web3j. The signature from web3js is valid (and web3j is not), I test it using solidity ecrecover function. It's worth to mention that hashes as you can see in the snippets are the same.
Java snippet:
Java result:
JS snippet:
JS result (testRPC 4.1.3 console):
The text was updated successfully, but these errors were encountered: