verify signatures immediately after signing as per recommendation in bip340

This commit is contained in:
Craig Raw 2022-09-02 11:27:12 +02:00
parent 311afd0409
commit 189ef88b08
2 changed files with 28 additions and 14 deletions

View file

@ -351,6 +351,25 @@ public class ECKey {
return pub.isCompressed();
}
public TransactionSignature sign(Sha256Hash input, SigHash sigHash, TransactionSignature.Type type) {
TransactionSignature transactionSignature;
if(type == TransactionSignature.Type.SCHNORR) {
SchnorrSignature schnorrSignature = signSchnorr(input);
transactionSignature = new TransactionSignature(schnorrSignature, sigHash);
} else {
ECDSASignature ecdsaSignature = signEcdsa(input);
transactionSignature = new TransactionSignature(ecdsaSignature, sigHash);
}
//Verify transaction signature immediately after signing as recommended in BIP340
if(!transactionSignature.verify(input.getBytes(), this)) {
throw new IllegalStateException("Generated signature failed verification");
}
return transactionSignature;
}
/**
* Signs the given hash and returns the R and S components as an ECDSASignature.
*/

View file

@ -2,9 +2,7 @@ package com.sparrowwallet.drongo.psbt;
import com.sparrowwallet.drongo.KeyDerivation;
import com.sparrowwallet.drongo.Utils;
import com.sparrowwallet.drongo.crypto.ECDSASignature;
import com.sparrowwallet.drongo.crypto.ECKey;
import com.sparrowwallet.drongo.crypto.SchnorrSignature;
import com.sparrowwallet.drongo.protocol.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -14,6 +12,7 @@ import java.util.*;
import java.util.stream.Collectors;
import static com.sparrowwallet.drongo.protocol.ScriptType.*;
import static com.sparrowwallet.drongo.protocol.TransactionSignature.Type.*;
import static com.sparrowwallet.drongo.psbt.PSBTEntry.*;
public class PSBTInput {
@ -136,7 +135,7 @@ public class PSBTInput {
break;
}
//TODO: Verify signature
TransactionSignature signature = TransactionSignature.decodeFromBitcoin(TransactionSignature.Type.ECDSA, entry.getData(), true);
TransactionSignature signature = TransactionSignature.decodeFromBitcoin(ECDSA, entry.getData(), true);
this.partialSignatures.put(sigPublicKey, signature);
log.debug("Found input partial signature with public key " + sigPublicKey + " signature " + Utils.bytesToHex(entry.getData()));
break;
@ -221,7 +220,7 @@ public class PSBTInput {
break;
case PSBT_IN_TAP_KEY_SIG:
entry.checkOneByteKey();
this.tapKeyPathSignature = TransactionSignature.decodeFromBitcoin(TransactionSignature.Type.SCHNORR, entry.getData(), true);
this.tapKeyPathSignature = TransactionSignature.decodeFromBitcoin(SCHNORR, entry.getData(), true);
log.debug("Found input taproot key path signature " + Utils.bytesToHex(entry.getData()));
break;
case PSBT_IN_TAP_BIP32_DERIVATION:
@ -529,23 +528,19 @@ public class PSBTInput {
Script signingScript = getSigningScript();
if(signingScript != null) {
Sha256Hash hash = getHashForSignature(signingScript, localSigHash);
TransactionSignature.Type type = isTaproot() ? SCHNORR : ECDSA;
TransactionSignature transactionSignature = privKey.sign(hash, localSigHash, type);
if(isTaproot()) {
SchnorrSignature schnorrSignature = privKey.signSchnorr(hash);
tapKeyPathSignature = new TransactionSignature(schnorrSignature, localSigHash);
return true;
if(type == SCHNORR) {
tapKeyPathSignature = transactionSignature;
} 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;
}