mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 05:06:45 +00:00
support bip 137 for message signing, but handle electrum approach as well when verifying
This commit is contained in:
parent
ec9534f8ae
commit
885efd7985
3 changed files with 47 additions and 20 deletions
|
@ -71,7 +71,7 @@ class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
NodeEntry nodeEntry = (NodeEntry)entry;
|
NodeEntry nodeEntry = (NodeEntry)entry;
|
||||||
Address address = nodeEntry.getAddress();
|
Address address = nodeEntry.getAddress();
|
||||||
setText(address.toString());
|
setText(address.toString());
|
||||||
setContextMenu(new AddressContextMenu(address, nodeEntry.getOutputDescriptor(), nodeEntry));
|
setContextMenu(new AddressContextMenu(address, nodeEntry.getOutputDescriptor(), null));
|
||||||
Tooltip tooltip = new Tooltip();
|
Tooltip tooltip = new Tooltip();
|
||||||
tooltip.setText(nodeEntry.getNode().getDerivationPath());
|
tooltip.setText(nodeEntry.getNode().getDerivationPath());
|
||||||
setTooltip(tooltip);
|
setTooltip(tooltip);
|
||||||
|
@ -98,6 +98,7 @@ class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
messageSignDialog.showAndWait();
|
messageSignDialog.showAndWait();
|
||||||
});
|
});
|
||||||
actionBox.getChildren().add(signMessageButton);
|
actionBox.getChildren().add(signMessageButton);
|
||||||
|
setContextMenu(new AddressContextMenu(address, nodeEntry.getOutputDescriptor(), nodeEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
setGraphic(actionBox);
|
setGraphic(actionBox);
|
||||||
|
|
|
@ -5,6 +5,8 @@ import com.sparrowwallet.drongo.SecureString;
|
||||||
import com.sparrowwallet.drongo.address.Address;
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
import com.sparrowwallet.drongo.address.InvalidAddressException;
|
import com.sparrowwallet.drongo.address.InvalidAddressException;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.drongo.wallet.WalletNode;
|
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||||
|
@ -221,7 +223,7 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
|
||||||
//Note we can expect a single keystore due to the check above
|
//Note we can expect a single keystore due to the check above
|
||||||
Keystore keystore = decryptedWallet.getKeystores().get(0);
|
Keystore keystore = decryptedWallet.getKeystores().get(0);
|
||||||
ECKey privKey = keystore.getKey(walletNode);
|
ECKey privKey = keystore.getKey(walletNode);
|
||||||
String signatureText = privKey.signMessage(message.getText(), null);
|
String signatureText = privKey.signMessage(message.getText().trim(), decryptedWallet.getScriptType(), null);
|
||||||
signature.clear();
|
signature.clear();
|
||||||
signature.appendText(signatureText);
|
signature.appendText(signatureText);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
|
@ -234,31 +236,55 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
|
||||||
try {
|
try {
|
||||||
//Find ECKey from message and signature
|
//Find ECKey from message and signature
|
||||||
//http://www.secg.org/download/aid-780/sec1-v2.pdf section 4.1.6
|
//http://www.secg.org/download/aid-780/sec1-v2.pdf section 4.1.6
|
||||||
|
boolean verified = false;
|
||||||
ECKey signedMessageKey = ECKey.signedMessageToKey(message.getText(), signature.getText());
|
try {
|
||||||
Address address = getAddress();
|
ECKey signedMessageKey = ECKey.signedMessageToKey(message.getText().trim(), signature.getText().trim(), false);
|
||||||
|
verified = verifyMessage(signedMessageKey);
|
||||||
byte[] pubKeyHash = address.getOutputScriptData();
|
} catch(SignatureException e) {
|
||||||
byte[] signedKeyHash = signedMessageKey.getPubKeyHash();
|
//ignore
|
||||||
|
|
||||||
if(!Arrays.equals(pubKeyHash, signedKeyHash)) {
|
|
||||||
throw new SignatureException("Address pubkey hash did not match signed pubkey hash");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!verified) {
|
||||||
|
try {
|
||||||
|
ECKey electrumSignedMessageKey = ECKey.signedMessageToKey(message.getText(), signature.getText(), true);
|
||||||
|
verified = verifyMessage(electrumSignedMessageKey);
|
||||||
|
} catch(SignatureException e) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(verified) {
|
||||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||||
setStageIcon(alert.getDialogPane().getScene().getWindow());
|
setStageIcon(alert.getDialogPane().getScene().getWindow());
|
||||||
alert.setTitle("Verification Succeeded");
|
alert.setTitle("Verification Succeeded");
|
||||||
alert.setHeaderText("Verification Succeeded");
|
alert.setHeaderText("Verification Succeeded");
|
||||||
alert.setContentText("The signature verified against the message.");
|
alert.setContentText("The signature verified against the message.");
|
||||||
alert.showAndWait();
|
alert.showAndWait();
|
||||||
} catch(SignatureException e) {
|
} else {
|
||||||
AppController.showErrorDialog("Verification failed", "The provided signature did not match the message for this address.");
|
AppController.showErrorDialog("Verification failed", "The provided signature did not match the message for this address.");
|
||||||
|
}
|
||||||
|
} catch(IllegalArgumentException e) {
|
||||||
|
AppController.showErrorDialog("Could not verify message", e.getMessage());
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
log.error("Could not verify message", e);
|
log.error("Could not verify message", e);
|
||||||
AppController.showErrorDialog("Could not verify message", e.getMessage());
|
AppController.showErrorDialog("Could not verify message", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean verifyMessage(ECKey signedMessageKey) throws InvalidAddressException, SignatureException {
|
||||||
|
Address providedAddress = getAddress();
|
||||||
|
ScriptType scriptType = providedAddress.getScriptType();
|
||||||
|
if(scriptType == ScriptType.P2SH) {
|
||||||
|
scriptType = ScriptType.P2SH_P2WPKH;
|
||||||
|
}
|
||||||
|
if(!ScriptType.getScriptTypesForPolicyType(PolicyType.SINGLE).contains(scriptType)) {
|
||||||
|
throw new IllegalArgumentException("Only single signature P2PKH, P2SH-P2WPKH or P2WPKH addresses can verify messages.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Address signedMessageAddress = scriptType.getAddress(signedMessageKey);
|
||||||
|
return providedAddress.equals(signedMessageAddress);
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void openWallets(OpenWalletsEvent event) {
|
public void openWallets(OpenWalletsEvent event) {
|
||||||
Storage storage = event.getStorage(wallet);
|
Storage storage = event.getStorage(wallet);
|
||||||
|
|
|
@ -269,7 +269,7 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayMnemonicCode() {
|
private void displayMnemonicCode() {
|
||||||
setDescription("Write down word list to confirm backup");
|
setDescription("Write down words before confirming");
|
||||||
showHideLink.setVisible(false);
|
showHideLink.setVisible(false);
|
||||||
|
|
||||||
calculateButton.setVisible(false);
|
calculateButton.setVisible(false);
|
||||||
|
|
Loading…
Reference in a new issue