mirror of
https://github.com/sparrowwallet/drongo.git
synced 2024-12-25 09:36:44 +00:00
add script type checks to bip322 implementation
This commit is contained in:
parent
c0555c3fb0
commit
e965a9ddd7
2 changed files with 69 additions and 17 deletions
|
@ -2,6 +2,7 @@ package com.sparrowwallet.drongo.crypto;
|
|||
|
||||
import com.sparrowwallet.drongo.Utils;
|
||||
import com.sparrowwallet.drongo.address.Address;
|
||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||
import com.sparrowwallet.drongo.protocol.*;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTInput;
|
||||
|
@ -15,7 +16,9 @@ import java.util.*;
|
|||
import static com.sparrowwallet.drongo.protocol.ScriptType.P2TR;
|
||||
|
||||
public class Bip322 {
|
||||
public static String signMessageBip322(Address address, String message, PSBTInputSigner psbtInputSigner) {
|
||||
public static String signMessageBip322(ScriptType scriptType, Address address, String message, PSBTInputSigner psbtInputSigner) {
|
||||
checkScriptType(scriptType);
|
||||
|
||||
Transaction toSpend = getBip322ToSpend(address, message);
|
||||
Transaction toSign = getBip322ToSign(toSpend);
|
||||
|
||||
|
@ -31,12 +34,14 @@ public class Bip322 {
|
|||
TransactionSignature signature = psbtInput.isTaproot() ? psbtInput.getTapKeyPathSignature() : psbtInput.getPartialSignature(pubKey);
|
||||
|
||||
Transaction finalizeTransaction = new Transaction();
|
||||
TransactionInput finalizedTxInput = address.getScriptType().addSpendingInput(finalizeTransaction, utxoOutput, pubKey, signature);
|
||||
TransactionInput finalizedTxInput = scriptType.addSpendingInput(finalizeTransaction, utxoOutput, pubKey, signature);
|
||||
|
||||
return Base64.getEncoder().encodeToString(finalizedTxInput.getWitness().toByteArray());
|
||||
}
|
||||
|
||||
public static void verifyMessageBip322(Address address, String message, String signatureBase64) throws SignatureException {
|
||||
public static void verifyMessageBip322(ScriptType scriptType, Address address, String message, String signatureBase64) throws SignatureException {
|
||||
checkScriptType(scriptType);
|
||||
|
||||
byte[] signatureEncoded;
|
||||
try {
|
||||
signatureEncoded = Base64.getDecoder().decode(signatureBase64);
|
||||
|
@ -52,14 +57,14 @@ public class Bip322 {
|
|||
signature = witness.getSignatures().get(0);
|
||||
pubKey = ECKey.fromPublicOnly(witness.getPushes().get(1));
|
||||
|
||||
if(!address.equals(address.getScriptType().getAddress(pubKey))) {
|
||||
if(!address.equals(scriptType.getAddress(pubKey))) {
|
||||
throw new SignatureException("Provided address does not match pubkey in signature");
|
||||
}
|
||||
} else if(address.getScriptType() == ScriptType.P2TR) {
|
||||
} else if(scriptType == ScriptType.P2TR) {
|
||||
signature = witness.getSignatures().get(0);
|
||||
pubKey = P2TR.getPublicKeyFromScript(address.getOutputScript());
|
||||
} else {
|
||||
throw new IllegalArgumentException(address.getScriptType() + " addresses are not supported");
|
||||
throw new IllegalArgumentException(scriptType + " addresses are not supported");
|
||||
}
|
||||
|
||||
Transaction toSpend = getBip322ToSpend(address, message);
|
||||
|
@ -70,10 +75,10 @@ public class Bip322 {
|
|||
psbtInput.setWitnessUtxo(toSpend.getOutputs().get(0));
|
||||
psbtInput.setSigHash(SigHash.ALL);
|
||||
|
||||
if(address.getScriptType() == ScriptType.P2WPKH) {
|
||||
psbtInput.getPartialSignatures().put(pubKey, signature);
|
||||
} else if(address.getScriptType() == ScriptType.P2TR) {
|
||||
if(scriptType == ScriptType.P2TR) {
|
||||
psbtInput.setTapKeyPathSignature(signature);
|
||||
} else {
|
||||
psbtInput.getPartialSignatures().put(pubKey, signature);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -83,6 +88,20 @@ public class Bip322 {
|
|||
}
|
||||
}
|
||||
|
||||
private static void checkScriptType(ScriptType scriptType) {
|
||||
if(!scriptType.isAllowed(PolicyType.SINGLE)) {
|
||||
throw new UnsupportedOperationException("Only singlesig addresses are currently supported");
|
||||
}
|
||||
|
||||
if(!Arrays.asList(ScriptType.WITNESS_TYPES).contains(scriptType)) {
|
||||
throw new UnsupportedOperationException("Legacy addresses are not supported for BIP322 simple signatures");
|
||||
}
|
||||
|
||||
if(scriptType == ScriptType.P2SH_P2WPKH) {
|
||||
throw new UnsupportedOperationException("The P2SH-P2WPKH script type is not currently supported");
|
||||
}
|
||||
}
|
||||
|
||||
public static Transaction getBip322ToSpend(Address address, String message) {
|
||||
Transaction toSpend = new Transaction();
|
||||
toSpend.setVersion(0);
|
||||
|
|
|
@ -29,7 +29,7 @@ public class Bip322Test {
|
|||
Address address = ScriptType.P2WPKH.getAddress(privKey);
|
||||
Assert.assertEquals("bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l", address.toString());
|
||||
|
||||
String signature = Bip322.signMessageBip322(address, "", new PSBTInputSigner() {
|
||||
String signature = Bip322.signMessageBip322(ScriptType.P2WPKH, address, "", new PSBTInputSigner() {
|
||||
@Override
|
||||
public TransactionSignature sign(Sha256Hash hash, SigHash sigHash, TransactionSignature.Type signatureType) {
|
||||
return privKey.sign(hash, sigHash, signatureType);
|
||||
|
@ -43,7 +43,7 @@ public class Bip322Test {
|
|||
|
||||
Assert.assertEquals("AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=", signature);
|
||||
|
||||
String signature2 = Bip322.signMessageBip322(address, "Hello World", new PSBTInputSigner() {
|
||||
String signature2 = Bip322.signMessageBip322(ScriptType.P2WPKH, address, "Hello World", new PSBTInputSigner() {
|
||||
@Override
|
||||
public TransactionSignature sign(Sha256Hash hash, SigHash sigHash, TransactionSignature.Type signatureType) {
|
||||
return privKey.sign(hash, sigHash, signatureType);
|
||||
|
@ -64,7 +64,7 @@ public class Bip322Test {
|
|||
String message1 = "";
|
||||
String signature2 = "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=";
|
||||
|
||||
Bip322.verifyMessageBip322(address, message1, signature2);
|
||||
Bip322.verifyMessageBip322(ScriptType.P2WPKH, address, message1, signature2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -73,14 +73,14 @@ public class Bip322Test {
|
|||
String message1 = "";
|
||||
String signature1 = "AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=";
|
||||
|
||||
Bip322.verifyMessageBip322(address, message1, signature1);
|
||||
Bip322.verifyMessageBip322(ScriptType.P2WPKH, address, message1, signature1);
|
||||
|
||||
String message2 = "Hello World";
|
||||
String signature2 = "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=";
|
||||
Bip322.verifyMessageBip322(address, message2, signature2);
|
||||
Bip322.verifyMessageBip322(ScriptType.P2WPKH, address, message2, signature2);
|
||||
|
||||
String signature3 = "AkgwRQIhAOzyynlqt93lOKJr+wmmxIens//zPzl9tqIOua93wO6MAiBi5n5EyAcPScOjf1lAqIUIQtr3zKNeavYabHyR8eGhowEhAsfxIAMZZEKUPYWI4BruhAQjzFT8FSFSajuFwrDL1Yhy";
|
||||
Bip322.verifyMessageBip322(address, message2, signature3);
|
||||
Bip322.verifyMessageBip322(ScriptType.P2WPKH, address, message2, signature3);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -89,7 +89,7 @@ public class Bip322Test {
|
|||
Address address = ScriptType.P2TR.getAddress(privKey);
|
||||
Assert.assertEquals("bc1ppv609nr0vr25u07u95waq5lucwfm6tde4nydujnu8npg4q75mr5sxq8lt3", address.toString());
|
||||
|
||||
String signature = Bip322.signMessageBip322(address, "Hello World", new PSBTInputSigner() {
|
||||
String signature = Bip322.signMessageBip322(ScriptType.P2TR, address, "Hello World", new PSBTInputSigner() {
|
||||
@Override
|
||||
public TransactionSignature sign(Sha256Hash hash, SigHash sigHash, TransactionSignature.Type signatureType) {
|
||||
return address.getScriptType().getOutputKey(privKey).sign(hash, sigHash, signatureType);
|
||||
|
@ -113,6 +113,39 @@ public class Bip322Test {
|
|||
String message1 = "Hello World";
|
||||
String signature1 = "AUHd69PrJQEv+oKTfZ8l+WROBHuy9HKrbFCJu7U1iK2iiEy1vMU5EfMtjc+VSHM7aU0SDbak5IUZRVno2P5mjSafAQ==";
|
||||
|
||||
Bip322.verifyMessageBip322(address, message1, signature1);
|
||||
Bip322.verifyMessageBip322(ScriptType.P2TR, address, message1, signature1);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void signMessageBip322NestedSegwit() {
|
||||
ECKey privKey = DumpedPrivateKey.fromBase58("L3VFeEujGtevx9w18HD1fhRbCH67Az2dpCymeRE1SoPK6XQtaN2k").getKey();
|
||||
Address address = ScriptType.P2SH_P2WPKH.getAddress(privKey);
|
||||
Assert.assertEquals("37qyp7jQAzqb2rCBpMvVtLDuuzKAUCVnJb", address.toString());
|
||||
|
||||
String signature = Bip322.signMessageBip322(ScriptType.P2SH_P2WPKH, address, "Hello World", new PSBTInputSigner() {
|
||||
@Override
|
||||
public TransactionSignature sign(Sha256Hash hash, SigHash sigHash, TransactionSignature.Type signatureType) {
|
||||
return address.getScriptType().getOutputKey(privKey).sign(hash, sigHash, signatureType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ECKey getPubKey() {
|
||||
return ECKey.fromPublicOnly(privKey);
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertEquals("AkcwRAIgHx821fcP3D4R6RsXHF8kXza4d/SqpKGaGu++AEQjJz0CIH9cN5XGDkgkqqF9OMTbYvhgI7Yp9NoHXEgLstjqDOqDASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=", signature);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void verifyMessageBip322NestedSegwit() throws SignatureException {
|
||||
ECKey privKey = DumpedPrivateKey.fromBase58("L3VFeEujGtevx9w18HD1fhRbCH67Az2dpCymeRE1SoPK6XQtaN2k").getKey();
|
||||
Address address = ScriptType.P2SH_P2WPKH.getAddress(privKey);
|
||||
Assert.assertEquals("37qyp7jQAzqb2rCBpMvVtLDuuzKAUCVnJb", address.toString());
|
||||
|
||||
String message1 = "Hello World";
|
||||
String signature1 = "AkcwRAIgHx821fcP3D4R6RsXHF8kXza4d/SqpKGaGu++AEQjJz0CIH9cN5XGDkgkqqF9OMTbYvhgI7Yp9NoHXEgLstjqDOqDASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=";
|
||||
|
||||
Bip322.verifyMessageBip322(ScriptType.P2SH_P2WPKH, address, message1, signature1);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue