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