/** * t * * @param r - * @param s - * @return - */ private static ECDSASignature fromComponents(byte[] r, byte[] s) { return new ECDSASignature(new BigInteger(1, r), new BigInteger(1, s)); }
/** * Will automatically adjust the S component to be less than or equal to half the curve order, if necessary. * This is required because for every signature (r,s) the signature (r, -s (mod N)) is a valid signature of * the same message. However, we dislike the ability to modify the bits of a Ethereum transaction after it's * been signed, as that violates various assumed invariants. Thus in future only one of those forms will be * considered legal and the other will be banned. * * @return - */ public ECDSASignature toCanonicalised() { if (s.compareTo(HALF_CURVE_ORDER) > 0) { // The order of the curve is the number of valid points that exist on that curve. If S is in the upper // half of the number of valid points, then bring it back to the lower half. Otherwise, imagine that // N = 10 // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions. // 10 - 8 == 2, giving us always the latter solution, which is canonical. return new ECDSASignature(r, CURVE.getN().subtract(s)); } else { return this; } }
/** * Verify the signature with public key * * @param data signed data * @param signature signature * @param hashed whether hashed data or not * @param pubKey public key for verifying * @return verification result */ public static boolean verify(byte[] data, byte[] signature, boolean hashed, byte[] pubKey) { ECKey.ECDSASignature ecdsaSignature = new ECKey.ECDSASignature(signature); byte[] hashedData = hashed ? data : HashUtil.sha3(data); ECKey ecKeyPub; try { ecKeyPub = ECKey.signatureToKey(hashedData, ecdsaSignature); } catch (SignatureException e) { logger.debug("Invalid signature" + e.getMessage()); return false; } if (pubKey != null && !Arrays.equals(ecKeyPub.getPubKey(), pubKey)) { logger.debug("Invalid signature"); return false; } return ecKeyPub.verify(hashedData, ecdsaSignature); }
signer.init(true, privKeyParams); BigInteger[] components = signer.generateSignature(input); return new ECDSASignature(components[0], components[1]).toCanonicalised(); } else { try {
@Test public void testGetAddressWithSig() throws IOException, InvalidCipherTextException, SignatureException { Account account = new Account(); log.debug("Account: " + account.toString()); log.debug("Account.address: " + Hex.toHexString(account.getAddress())); log.debug("Account.pubKey: " + Hex.toHexString(account.getKey().getPubKey())); Wallet wallet = new Wallet(account.getKey(), "tmp/path", "nodePri.key", "Aa1234567890!"); log.debug("Wallet: " + wallet.toString()); log.debug("Wallet.address: " + Hex.toHexString(wallet.getAddress())); log.debug("Wallet.pubKey: " + Hex.toHexString(wallet.getPubicKey())); TransactionHusk txHusk1 = createTx(wallet); log.debug("Test Transaction1: " + txHusk1.toString()); log.debug("Test Transaction1 Address: " + txHusk1.getAddress()); assertThat(txHusk1.verify()).isTrue(); assertThat(wallet.getAddress()).isEqualTo(account.getAddress()); assertThat(wallet.getAddress()).isEqualTo(txHusk1.getAddress().getBytes()); byte[] hashedRawData = txHusk1.getHashForSigning().getBytes(); log.debug("hashedRawData: " + Hex.toHexString(hashedRawData)); byte[] signatureBin = txHusk1.getInstance().getSignature().toByteArray(); log.debug("signatureBin: " + Hex.toHexString(signatureBin)); ECKey.ECDSASignature ecdsaSignature = new ECKey.ECDSASignature(signatureBin); ECKey key = ECKey.signatureToKey(hashedRawData, ecdsaSignature); byte[] address = key.getAddress(); byte[] pubKey = key.getPubKey(); log.debug("address: " + Hex.toHexString(address)); log.debug("pubKey: " + Hex.toHexString(pubKey)); assertThat(account.getAddress()).isEqualTo(address); assertThat(account.getKey().getPubKey()).isEqualTo(pubKey); }
public static ECDSASignature decodeFromDER(byte[] bytes) { try (ASN1InputStream decoder = new ASN1InputStream(bytes)) { DLSequence seq = (DLSequence) decoder.readObject(); if (seq == null) { throw new RuntimeException("Reached past end of ASN.1 stream."); } ASN1Integer r, s; try { r = (ASN1Integer) seq.getObjectAt(0); s = (ASN1Integer) seq.getObjectAt(1); } catch (ClassCastException e) { throw new IllegalArgumentException(e); } // OpenSSL deviates from the DER spec by interpreting these values as unsigned, though they should not be // Thus, we always use the positive versions. See: http://r6.ca/blog/20111119T211504Z.html return new ECDSASignature(r.getPositiveValue(), s.getPositiveValue()); } catch (IOException e) { throw new RuntimeException(e); } // ignore }
@Test @SuppressWarnings("UnstableApiUsage") public void testSValue() throws Exception { // Check that we never generate an S value that is larger than half the curve order. This avoids a malleability // issue that can allow someone to change a transaction [hash] without invalidating the signature. final int ITERATIONS = 10; ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(ITERATIONS)); List<ListenableFuture<ECKey.ECDSASignature>> sigFutures = Lists.newArrayList(); final ECKey key = new ECKey(); for (byte i = 0; i < ITERATIONS; i++) { final byte[] hash = HashUtil.sha3(new byte[] {i}); sigFutures.add(executor.submit(() -> key.doSign(hash))); } List<ECKey.ECDSASignature> sigs = Futures.allAsList(sigFutures).get(); for (ECKey.ECDSASignature signature : sigs) { assertTrue(signature.s.compareTo(ECKey.HALF_CURVE_ORDER) <= 0); } final ECKey.ECDSASignature duplicate = new ECKey.ECDSASignature(sigs.get(0).r, sigs.get(0).s); assertEquals(sigs.get(0), duplicate); assertEquals(sigs.get(0).hashCode(), duplicate.hashCode()); }
/** * Verify a transaction.(data format & signing) * * @return true(success), false(fail) */ public boolean verify() { if (!this.verifyData()) { return false; } ECKey.ECDSASignature ecdsaSignature = new ECKey.ECDSASignature(this.signature); byte[] hashedHeader = this.header.getHashForSigning(); ECKey ecKeyPub; try { ecKeyPub = ECKey.signatureToKey(hashedHeader, ecdsaSignature); } catch (SignatureException e) { throw new InvalidSignatureException(e); } return ecKeyPub.verify(hashedHeader, ecdsaSignature); }
@Test public void testVerifySignature_Static() throws SignatureException { byte[] messageHash = Hex.decode("92e0d4290bba01aa0abbb4705360c751af13fdb1131b8f6f1e632c4621adac75"); byte[] signature = Hex.decode("1cca588a8eb84d5bf6741bc6e0ccfbe1fdb05b6c624b5fe72199fa1f2e501f876c5b5f11863323a998b79a0d27714fcc8825cf357903e863396f2e2e281220de31"); // get public key with messageHash, ECDSASignature ECKey.ECDSASignature sig = new ECKey.ECDSASignature(signature); ECKey keyFromSig = ECKey.signatureToKey(messageHash, sig); log.debug("address=" + Hex.toHexString(keyFromSig.getAddress())); byte[] pubKeyFromSig = keyFromSig.getPubKey(); log.debug("pubKey=" + Hex.toHexString(pubKeyFromSig)); assertArrayEquals(pubKeyFromSig, Hex.decode("0493fe448d38c77c212cce10c07ed37984c59bedac51219b70847429153063cfae0d2f42ba394ffe9d5d2d11b0c0f400ac04997c584c0ef6f2041cf20f8c2c446b")); // verify the sign message assertTrue(keyFromSig.verify(messageHash, sig)); }
public boolean verify() { if (!this.verifyData()) { return false; } ECKey.ECDSASignature ecdsaSignature = new ECKey.ECDSASignature(this.signature); byte[] hashedHeader = this.header.getHashForSigning(); ECKey ecKeyPub; try { ecKeyPub = ECKey.signatureToKey(hashedHeader, ecdsaSignature); } catch (SignatureException e) { throw new InvalidSignatureException(e); } return ecKeyPub.verify(hashedHeader, ecdsaSignature); }
public boolean verify() { ECKey.ECDSASignature ecdsaSignature = new ECKey.ECDSASignature(signature.getBytes()); try { ECKey ecKeyPub = ECKey.signatureToKey(rawForSign.getBytes(), ecdsaSignature); if (ecKeyPub.verify(rawForSign.getBytes(), ecdsaSignature)) { return new Address(ecKeyPub.getAddress()).equals(owner); } else { return false; } } catch (SignatureException e) { throw new InvalidSignatureException(e); } }
public byte[] getPubKey() { ECKey.ECDSASignature ecdsaSignature = new ECKey.ECDSASignature(this.signature); ECKey ecKeyPub = null; try { ecKeyPub = ECKey.signatureToKey(this.header.getHashForSigning(), ecdsaSignature); } catch (SignatureException e) { log.warn(e.getMessage()); throw new InvalidSignatureException(); } return ecKeyPub.getPubKey(); }
/** * Verify the signature with hashed data. * * @param hashedData hashed Data * @param signature signature * @return verification result */ boolean verifyHashedData(byte[] hashedData, byte[] signature) { ECKey.ECDSASignature sig = new ECKey.ECDSASignature(signature); return key.verify(hashedData, sig); }
/** * Get the public key. * * @return public key */ byte[] getPubKey() throws SignatureException { ECKey.ECDSASignature ecdsaSignature = new ECKey.ECDSASignature(this.signature); ECKey ecKeyPub = ECKey.signatureToKey(this.header.getHashForSigning(), ecdsaSignature); return ecKeyPub.getPubKey(); }
public static byte[] calculatePubKey(byte[] data, byte[] signature, boolean hashed) { ECKey.ECDSASignature ecdsaSignature = new ECKey.ECDSASignature(signature); byte[] hashedData = hashed ? data : HashUtil.sha3(data); ECKey ecKeyPub; try { ecKeyPub = ECKey.signatureToKey(hashedData, ecdsaSignature); } catch (SignatureException e) { logger.debug("Invalid signature" + e.getMessage()); return null; } return ecKeyPub.getPubKey(); }
/** * Verify the signature with plain data. * * @param data plain data for signed * @param signature signature * @return verification result */ public boolean verify(byte[] data, byte[] signature) { ECKey.ECDSASignature sig = new ECKey.ECDSASignature(signature); return key.verify(HashUtil.sha3(data), sig); }