Created
November 21, 2017 14:31
-
-
Save megamattron/94c05789e5ff410296e74dad3b528613 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.web3j.crypto.Keys; | |
import org.web3j.crypto.Sign; | |
import org.web3j.utils.Numeric; | |
import java.security.SignatureException; | |
public class SignUtil { | |
private static final String GETH_SIGN_PREFIX = "\u0019Ethereum Signed Message:\n32"; | |
/** | |
* This method is expecting the signed message to be a hash of the original message. The length of the message is | |
* then hardcoded to 32. Also, this might only work for messages signed by geth, not sure if other clients | |
* add the prefix to the signed message. | |
* @param signedHash | |
* @param originalMessageHashInHex | |
* @return | |
* @throws SignatureException | |
*/ | |
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; | |
} | |
} |
public static String ecRecover(String msg, String sig) {
byte[] signatureBytes = Numeric.hexStringToByteArray(sig);
Sign.SignatureData signatureData = sigFromByteArray(signatureBytes);
try {
BigInteger recoveredKey = Sign.signedPrefixedMessageToKey(msg.getBytes(), signatureData);
String address = "0x" + Keys.getAddress(recoveredKey);
return address.toLowerCase();
} catch (Exception e) {
log.error("SignatureException, msg:{}, sig:{}, nonce:{}: ", msg, sig, nonce, e.getMessage());
}
}
public static Sign.SignatureData sigFromByteArray(byte[] sig) {
if (sig.length < 64 || sig.length > 65) return null;
byte v = sig[64];
if (v < 27) v += 27;
byte[] r = Arrays.copyOfRange(sig, 0, 32);
byte[] s = Arrays.copyOfRange(sig, 32, 64);
return new Sign.SignatureData(v, r, v);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
One more cleaned-up gist to hopefully help the next person, with a runnable demo and detailed explanation: https://gist.github.com/djma/386c2dcf91fefc004b14e5044facd3a9