use of com.sparrowwallet.drongo.crypto.ECKey in project drongo by sparrowwallet.
the class PSBTInput method getSigningKeys.
public Map<ECKey, TransactionSignature> getSigningKeys(Set<ECKey> availableKeys) {
Collection<TransactionSignature> signatures = getSignatures();
Script signingScript = getSigningScript();
Map<ECKey, TransactionSignature> signingKeys = new LinkedHashMap<>();
if (signingScript != null) {
Sha256Hash hash = getHashForSignature(signingScript, getSigHash() == null ? getDefaultSigHash() : getSigHash());
for (ECKey sigPublicKey : availableKeys) {
for (TransactionSignature signature : signatures) {
if (sigPublicKey.verify(hash, signature)) {
signingKeys.put(sigPublicKey, signature);
}
}
}
}
return signingKeys;
}
use of com.sparrowwallet.drongo.crypto.ECKey in project drongo by sparrowwallet.
the class PSBTInput method sign.
public boolean sign(ECKey privKey) {
SigHash localSigHash = getSigHash();
if (localSigHash == null) {
localSigHash = getDefaultSigHash();
}
if (getNonWitnessUtxo() != null || getWitnessUtxo() != null) {
Script signingScript = getSigningScript();
if (signingScript != null) {
Sha256Hash hash = getHashForSignature(signingScript, localSigHash);
if (isTaproot()) {
SchnorrSignature schnorrSignature = privKey.signSchnorr(hash);
tapKeyPathSignature = new TransactionSignature(schnorrSignature, localSigHash);
return true;
} else {
ECDSASignature ecdsaSignature = privKey.signEcdsa(hash);
TransactionSignature transactionSignature = new TransactionSignature(ecdsaSignature, localSigHash);
ECKey pubKey = ECKey.fromPublicOnly(privKey);
getPartialSignatures().put(pubKey, transactionSignature);
return true;
}
}
}
return false;
}
use of com.sparrowwallet.drongo.crypto.ECKey in project drongo by sparrowwallet.
the class PaymentCodeTest method testNotificationAddress.
@Test
public void testNotificationAddress() throws InvalidPaymentCodeException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, MnemonicException {
PaymentCode alicePaymentCode = new PaymentCode("PM8TJTLJbPRGxSbc8EJi42Wrr6QbNSaSSVJ5Y3E4pbCYiTHUskHg13935Ubb7q8tx9GVbh2UuRnBc3WSyJHhUrw8KhprKnn9eDznYGieTzFcwQRya4GA");
Address aliceNotificationAddress = alicePaymentCode.getNotificationAddress();
Assert.assertEquals("1JDdmqFLhpzcUwPeinhJbUPw4Co3aWLyzW", aliceNotificationAddress.toString());
ECKey alicePrivKey = DumpedPrivateKey.fromBase58("Kx983SRhAZpAhj7Aac1wUXMJ6XZeyJKqCxJJ49dxEbYCT4a1ozRD").getKey();
byte[] alicePayload = alicePaymentCode.getPayload();
Assert.assertEquals("010002b85034fb08a8bfefd22848238257b252721454bbbfba2c3667f168837ea2cdad671af9f65904632e2dcc0c6ad314e11d53fc82fa4c4ea27a4a14eccecc478fee00000000000000000000000000", Utils.bytesToHex(alicePayload));
PaymentCode paymentCodeBob = new PaymentCode("PM8TJS2JxQ5ztXUpBBRnpTbcUXbUHy2T1abfrb3KkAAtMEGNbey4oumH7Hc578WgQJhPjBxteQ5GHHToTYHE3A1w6p7tU6KSoFmWBVbFGjKPisZDbP97");
ECKey bobNotificationPubKey = paymentCodeBob.getNotificationKey();
Assert.assertEquals("024ce8e3b04ea205ff49f529950616c3db615b1e37753858cc60c1ce64d17e2ad8", Utils.bytesToHex(bobNotificationPubKey.getPubKey()));
TransactionOutPoint transactionOutPoint = new TransactionOutPoint(Sha256Hash.wrapReversed(Utils.hexToBytes("86f411ab1c8e70ae8a0795ab7a6757aea6e4d5ae1826fc7b8f00c597d500609c")), 1);
Assert.assertEquals("86f411ab1c8e70ae8a0795ab7a6757aea6e4d5ae1826fc7b8f00c597d500609c01000000", Utils.bytesToHex(transactionOutPoint.bitcoinSerialize()));
SecretPoint secretPoint = new SecretPoint(alicePrivKey.getPrivKeyBytes(), bobNotificationPubKey.getPubKey());
Assert.assertEquals("736a25d9250238ad64ed5da03450c6a3f4f8f4dcdf0b58d1ed69029d76ead48d", Utils.bytesToHex(secretPoint.ECDHSecretAsBytes()));
byte[] blindingMask = PaymentCode.getMask(secretPoint.ECDHSecretAsBytes(), transactionOutPoint.bitcoinSerialize());
Assert.assertEquals("be6e7a4256cac6f4d4ed4639b8c39c4cb8bece40010908e70d17ea9d77b4dc57f1da36f2d6641ccb37cf2b9f3146686462e0fa3161ae74f88c0afd4e307adbd5", Utils.bytesToHex(blindingMask));
byte[] blindedPaymentCode = PaymentCode.blind(alicePayload, blindingMask);
Assert.assertEquals("010002063e4eb95e62791b06c50e1a3a942e1ecaaa9afbbeb324d16ae6821e091611fa96c0cf048f607fe51a0327f5e2528979311c78cb2de0d682c61e1180fc3d543b00000000000000000000000000", Utils.bytesToHex(blindedPaymentCode));
Transaction transaction = new Transaction();
List<ScriptChunk> inputChunks = List.of(ScriptChunk.fromData(Utils.hexToBytes("3045022100ac8c6dbc482c79e86c18928a8b364923c774bfdbd852059f6b3778f2319b59a7022029d7cc5724e2f41ab1fcfc0ba5a0d4f57ca76f72f19530ba97c860c70a6bf0a801")), ScriptChunk.fromData(alicePrivKey.getPubKey()));
transaction.addInput(transactionOutPoint.getHash(), transactionOutPoint.getIndex(), new Script(inputChunks));
transaction.addOutput(10000, paymentCodeBob.getNotificationAddress());
List<ScriptChunk> opReturnChunks = List.of(ScriptChunk.fromOpcode(ScriptOpCodes.OP_RETURN), ScriptChunk.fromData(blindedPaymentCode));
transaction.addOutput(10000, new Script(opReturnChunks));
Assert.assertEquals("010000000186f411ab1c8e70ae8a0795ab7a6757aea6e4d5ae1826fc7b8f00c597d500609c010000006b483045022100ac8c6dbc482c79e86c18928a8b364923c774bfdb" + "d852059f6b3778f2319b59a7022029d7cc5724e2f41ab1fcfc0ba5a0d4f57ca76f72f19530ba97c860c70a6bf0a801210272d83d8a1fa323feab1c085157a0791b46eba34afb8bfbfaeb3a3fcc3f2" + "c9ad8ffffffff0210270000000000001976a9148066a8e7ee82e5c5b9b7dc1765038340dc5420a988ac1027000000000000536a4c50010002063e4eb95e62791b06c50e1a3a942e1ecaaa9afbbeb3" + "24d16ae6821e091611fa96c0cf048f607fe51a0327f5e2528979311c78cb2de0d682c61e1180fc3d543b0000000000000000000000000000000000", Utils.bytesToHex(transaction.bitcoinSerialize()));
Assert.assertEquals("9414f1681fb1255bd168a806254321a837008dd4480c02226063183deb100204", transaction.getTxId().toString());
ECKey alicePubKey = ECKey.fromPublicOnly(transaction.getInputs().get(0).getScriptSig().getChunks().get(1).data);
Assert.assertArrayEquals(alicePubKey.getPubKey(), alicePrivKey.getPubKey());
DeterministicSeed bobSeed = new DeterministicSeed("reward upper indicate eight swift arch injury crystal super wrestle already dentist", "", 0, DeterministicSeed.Type.BIP39);
Keystore bobKeystore = Keystore.fromSeed(bobSeed, List.of(new ChildNumber(47, true), ChildNumber.ZERO_HARDENED, ChildNumber.ZERO_HARDENED));
ECKey bobNotificationPrivKey = bobKeystore.getBip47ExtendedPrivateKey().getKey(List.of(ChildNumber.ZERO_HARDENED, new ChildNumber(0)));
SecretPoint bobSecretPoint = new SecretPoint(bobNotificationPrivKey.getPrivKeyBytes(), alicePubKey.getPubKey());
Assert.assertEquals("736a25d9250238ad64ed5da03450c6a3f4f8f4dcdf0b58d1ed69029d76ead48d", Utils.bytesToHex(bobSecretPoint.ECDHSecretAsBytes()));
byte[] bobBlindingMask = PaymentCode.getMask(secretPoint.ECDHSecretAsBytes(), transaction.getInputs().get(0).getOutpoint().bitcoinSerialize());
Assert.assertEquals("be6e7a4256cac6f4d4ed4639b8c39c4cb8bece40010908e70d17ea9d77b4dc57f1da36f2d6641ccb37cf2b9f3146686462e0fa3161ae74f88c0afd4e307adbd5", Utils.bytesToHex(bobBlindingMask));
PaymentCode unblindedPaymentCode = new PaymentCode(PaymentCode.blind(transaction.getOutputs().get(1).getScript().getChunks().get(1).data, blindingMask));
Assert.assertEquals(alicePaymentCode, unblindedPaymentCode);
PaymentCode unblindedPaymentCode2 = PaymentCode.getPaymentCode(transaction, bobKeystore);
Assert.assertEquals(alicePaymentCode, unblindedPaymentCode2);
}
use of com.sparrowwallet.drongo.crypto.ECKey in project drongo by sparrowwallet.
the class Wallet method sign.
public void sign(PSBT psbt) throws MnemonicException {
Map<PSBTInput, WalletNode> signingNodes = getSigningNodes(psbt);
for (Map.Entry<PSBTInput, WalletNode> signingEntry : signingNodes.entrySet()) {
Wallet signingWallet = signingEntry.getValue().getWallet();
for (Keystore keystore : signingWallet.getKeystores()) {
if (keystore.hasPrivateKey()) {
ECKey privKey = signingWallet.getScriptType().getOutputKey(keystore.getKey(signingEntry.getValue()));
PSBTInput psbtInput = signingEntry.getKey();
if (!psbtInput.isSigned()) {
psbtInput.sign(privKey);
}
}
}
}
}
use of com.sparrowwallet.drongo.crypto.ECKey in project drongo by sparrowwallet.
the class TransactionTest method signTaprootKeypath.
@Test
public void signTaprootKeypath() {
Transaction tx = new Transaction(Utils.hexToBytes("02000000000101786ed355f998b98f8ef8ef2acf461577325cf170a9133d48a17aba957eb97ff00000000000ffffffff0100e1f50500000000220020693a94699e6e41ab302fd623a9bf5a5b2d6606cbfb35c550d1cb4300451356a102473044022004cc317c20eb9e372cb0e640f51eb2b8311616125321b11dbaa5671db5a3ca2a02207ae3d2771b565be98ae56e21045b9629c94b6ca8f4e3932260e54d4f0e2016b30121032da1692a41a61ad14f3795b31d33431abf8d6ee161b997d004c26a37bc20083500000000"));
Transaction spendingTx = new Transaction(Utils.hexToBytes("01000000011af4dca4a6bc6da092edca5390355891da9bbe76d2be1c04d067ec9c3a3d22b10000000000000000000180f0fa0200000000160014a3bcb5f272025cc66dc42e7518a5846bd60a9c9600000000"));
Sha256Hash hash = spendingTx.hashForTaprootSignature(tx.getOutputs(), 0, false, null, SigHash.ALL_TAPROOT, null);
ECKey privateKey = ECKey.fromPrivate(Utils.hexToBytes("d9bc817b92916a24b87d25dc48ef466b4fcd6c89cf90afbc17cba40eb8b91330"));
SchnorrSignature sig = privateKey.signSchnorr(hash);
Assert.assertEquals("7b04f59bc8f5c2c33c9b8acbf94743de74cc25a6052b52ff61a516f7c5ca19cc68345ba99b354f22bfaf5c04de395b9223f3bf0a5c351fc1cc68c224f4e5b202", Utils.bytesToHex(sig.encode()));
ECKey pubKey = ECKey.fromPublicOnly(privateKey);
Assert.assertTrue(pubKey.verify(hash, new TransactionSignature(sig, SigHash.ALL_TAPROOT)));
}
Aggregations