/** * Given a piece of text and a message signature encoded in binary, returns an ECKey * containing the public key that was used to sign it. This can then be compared to the expected public key to * determine if the signature was correct. * * @param messageHash a piece of human readable text that was signed * @param signatureEncoded The signature message in binary * @return - * @throws SignatureException If the public key could not be recovered or if there was a signature format error. */ public static byte[] signatureToKeyBytes(byte[] messageHash, byte[] signatureEncoded) throws SignatureException { // Parse the signature bytes into r/s and the selector value. if (signatureEncoded.length < 65) { throw new SignatureException("Signature truncated, expected 65 bytes and got " + signatureEncoded.length); } return signatureToKeyBytes( messageHash, ECDSASignature.fromComponents( Arrays.copyOfRange(signatureEncoded, 1, 33), Arrays.copyOfRange(signatureEncoded, 33, 65), (byte) (signatureEncoded[0] & 0xFF))); }
@Test public void testVerifySignature1() { ECKey key = ECKey.fromPublicOnly(pubKey); BigInteger r = new BigInteger("95350169487015575001444507567851457309689354890536757640816472151471942911739"); BigInteger s = new BigInteger("53263359985948886716508128220321578640585687230908938312863706887350789467339"); ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray(), (byte) 28); assertTrue(key.verify(HashUtil.sha3(exampleMessage.getBytes()), sig)); }
@Test // result is a point at infinity public void testVerifySignature4() throws SignatureException { byte[] hash = Hex.decode("6ee854b88dbf19846c58fd2beac582adcf28cfdd2b3a8427ac29d7b70153d35c"); BigInteger r = new BigInteger("95350169487015575001444507567851457309689354890536757640816472151471942911739"); BigInteger s = new BigInteger("53263359985948886716508128220321578640585687230908938312863706887350789467339"); ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray(), (byte) 28); ECKey key = ECKey.signatureToKey(hash, sig); assertTrue(key.verify(hash, sig)); }
/** * Given a piece of text and a message signature encoded in base64, returns an ECKey * containing the public key that was used to sign it. This can then be compared to the expected public key to * determine if the signature was correct. * * @param messageHash a piece of human readable text that was signed * @param signatureBase64 The Ethereum-format message signature in base64 * @return - * @throws SignatureException If the public key could not be recovered or if there was a signature format error. */ public static byte[] signatureToKeyBytes(byte[] messageHash, String signatureBase64) throws SignatureException { byte[] signatureEncoded; try { signatureEncoded = Base64.decode(signatureBase64); } catch (RuntimeException e) { // This is what you get back from Bouncy Castle if base64 doesn't decode :( throw new SignatureException("Could not decode base64", e); } // Parse the signature bytes into r/s and the selector value. if (signatureEncoded.length < 65) { throw new SignatureException("Signature truncated, expected 65 bytes and got " + signatureEncoded.length); } return signatureToKeyBytes( messageHash, ECDSASignature.fromComponents( Arrays.copyOfRange(signatureEncoded, 1, 33), Arrays.copyOfRange(signatureEncoded, 33, 65), (byte) (signatureEncoded[0] & 0xFF))); }
@Test public void testVerifySignature2() throws SignatureException { BigInteger r = new BigInteger("c52c114d4f5a3ba904a9b3036e5e118fe0dbb987fe3955da20f2cd8f6c21ab9c", 16); BigInteger s = new BigInteger("6ba4c2874299a55ad947dbc98a25ee895aabf6b625c26c435e84bfd70edf2f69", 16); ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray(), (byte) 0x1b); byte[] rawtx = Hex.decode("f82804881bc16d674ec8000094cd2a3d9f938e13cd947ec05abc7fe734df8dd8268609184e72a0006480"); byte[] rawHash = HashUtil.sha3(rawtx); byte[] address = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"); ECKey key = ECKey.signatureToKey(rawHash, sig); assertEquals(key, ECKey.signatureToKey(rawHash, sig.toBase64())); assertEquals(key, ECKey.recoverFromSignature(0, sig, rawHash)); assertArrayEquals(key.getPubKey(), ECKey.recoverPubBytesFromSignature(0, sig, rawHash)); assertArrayEquals(address, key.getAddress()); assertArrayEquals(address, ECKey.signatureToAddress(rawHash, sig)); assertArrayEquals(address, ECKey.signatureToAddress(rawHash, sig.toBase64())); assertArrayEquals(address, ECKey.recoverAddressFromSignature(0, sig, rawHash)); assertTrue(key.verify(rawHash, sig)); }
/** * @param r - * @param s - * @param v - * @return - */ public static ECDSASignature fromComponents(byte[] r, byte[] s, byte v) { ECDSASignature signature = fromComponents(r, s); signature.v = v; return signature; }