mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 05:06:45 +00:00
satscard: retrieve private keys for previously used slots
This commit is contained in:
parent
73dcef9fd1
commit
0b980f6ab5
3 changed files with 65 additions and 18 deletions
|
@ -45,6 +45,7 @@ import org.slf4j.LoggerFactory;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class DevicePane extends TitledDescriptionPane {
|
||||
private static final Logger log = LoggerFactory.getLogger(DevicePane.class);
|
||||
|
@ -67,7 +68,7 @@ public class DevicePane extends TitledDescriptionPane {
|
|||
private Button displayAddressButton;
|
||||
private Button signMessageButton;
|
||||
private Button discoverKeystoresButton;
|
||||
private Button getPrivateKeyButton;
|
||||
private ButtonBase getPrivateKeyButton;
|
||||
private Button getAddressButton;
|
||||
|
||||
private final SimpleStringProperty passphrase = new SimpleStringProperty("");
|
||||
|
@ -218,7 +219,7 @@ public class DevicePane extends TitledDescriptionPane {
|
|||
setDefaultStatus();
|
||||
showHideLink.setVisible(false);
|
||||
|
||||
Button button;
|
||||
ButtonBase button;
|
||||
if(deviceOperation == DeviceOperation.GET_PRIVATE_KEY) {
|
||||
createGetPrivateKeyButton();
|
||||
button = getPrivateKeyButton;
|
||||
|
@ -382,12 +383,44 @@ public class DevicePane extends TitledDescriptionPane {
|
|||
}
|
||||
|
||||
private void createGetPrivateKeyButton() {
|
||||
getPrivateKeyButton = new Button("Get Private Key");
|
||||
int currentSlot = 0;
|
||||
boolean initialized = true;
|
||||
try {
|
||||
CardApi cardApi = CardApi.getCardApi(device.getModel(), null);
|
||||
currentSlot = cardApi.getCurrentSlot();
|
||||
initialized = cardApi.isInitialized();
|
||||
} catch(Exception e) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
getPrivateKeyButton = currentSlot > 0 ? new SplitMenuButton() : new Button();
|
||||
getPrivateKeyButton.setAlignment(Pos.CENTER_RIGHT);
|
||||
getPrivateKeyButton.setText("Get Private Key");
|
||||
getPrivateKeyButton.setOnAction(event -> {
|
||||
getPrivateKeyButton.setDisable(true);
|
||||
getPrivateKey();
|
||||
getPrivateKey(null);
|
||||
});
|
||||
|
||||
if(getPrivateKeyButton instanceof SplitMenuButton getPrivateKeyMenuButton) {
|
||||
int[] previousSlots = IntStream.range(0, currentSlot).toArray();
|
||||
for(int previousSlot : previousSlots) {
|
||||
MenuItem previousSlotItem = new MenuItem("Slot #" + previousSlot);
|
||||
previousSlotItem.setOnAction(event -> {
|
||||
getPrivateKeyButton.setDisable(true);
|
||||
getPrivateKey(previousSlot);
|
||||
});
|
||||
getPrivateKeyMenuButton.getItems().add(previousSlotItem);
|
||||
}
|
||||
if(initialized) {
|
||||
int finalSlot = currentSlot;
|
||||
MenuItem currentSlotItem = new MenuItem("Current Slot");
|
||||
currentSlotItem.setOnAction(event -> {
|
||||
getPrivateKeyButton.setDisable(true);
|
||||
getPrivateKey(finalSlot);
|
||||
});
|
||||
getPrivateKeyMenuButton.getItems().add(currentSlotItem);
|
||||
}
|
||||
}
|
||||
getPrivateKeyButton.managedProperty().bind(getPrivateKeyButton.visibleProperty());
|
||||
getPrivateKeyButton.setVisible(false);
|
||||
}
|
||||
|
@ -886,11 +919,11 @@ public class DevicePane extends TitledDescriptionPane {
|
|||
getXpubsService.start();
|
||||
}
|
||||
|
||||
private void getPrivateKey() {
|
||||
private void getPrivateKey(Integer slot) {
|
||||
if(device.isCard()) {
|
||||
try {
|
||||
CardApi cardApi = CardApi.getCardApi(device.getModel(), pin.get());
|
||||
Service<ECKey> privateKeyService = cardApi.getPrivateKeyService(messageProperty);
|
||||
Service<ECKey> privateKeyService = cardApi.getPrivateKeyService(slot, messageProperty);
|
||||
handleCardOperation(privateKeyService, getPrivateKeyButton, "Private Key", true, event -> {
|
||||
EventManager.get().post(new DeviceGetPrivateKeyEvent(privateKeyService.getValue(), cardApi.getDefaultScriptType()));
|
||||
});
|
||||
|
@ -962,7 +995,9 @@ public class DevicePane extends TitledDescriptionPane {
|
|||
discoverKeystoresButton.setVisible(true);
|
||||
showHideLink.setVisible(false);
|
||||
} else if(deviceOperation.equals(DeviceOperation.GET_PRIVATE_KEY)) {
|
||||
getPrivateKeyButton.setDefaultButton(defaultDevice);
|
||||
if(defaultDevice) {
|
||||
getPrivateKeyButton.getStyleClass().add("default-button");
|
||||
}
|
||||
getPrivateKeyButton.setVisible(true);
|
||||
showHideLink.setVisible(false);
|
||||
} else if(deviceOperation.equals(DeviceOperation.GET_ADDRESS)) {
|
||||
|
|
|
@ -53,6 +53,8 @@ public abstract class CardApi {
|
|||
|
||||
public abstract ScriptType getDefaultScriptType();
|
||||
|
||||
public abstract int getCurrentSlot() throws CardException;
|
||||
|
||||
public abstract Service<Void> getAuthDelayService() throws CardException;
|
||||
|
||||
public abstract boolean requiresBackup() throws CardException;
|
||||
|
@ -71,7 +73,7 @@ public abstract class CardApi {
|
|||
|
||||
public abstract Service<String> getSignMessageService(String message, ScriptType scriptType, List<ChildNumber> derivation, StringProperty messageProperty);
|
||||
|
||||
public abstract Service<ECKey> getPrivateKeyService(StringProperty messageProperty);
|
||||
public abstract Service<ECKey> getPrivateKeyService(Integer slot, StringProperty messageProperty);
|
||||
|
||||
public abstract Service<Address> getAddressService(StringProperty messageProperty);
|
||||
|
||||
|
|
|
@ -62,6 +62,12 @@ public class CkCardApi extends CardApi {
|
|||
return cardStatus.getCardType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentSlot() throws CardException {
|
||||
CardStatus cardStatus = getStatus();
|
||||
return cardStatus.getCurrentSlot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptType getDefaultScriptType() {
|
||||
return ScriptType.P2WPKH;
|
||||
|
@ -250,12 +256,12 @@ public class CkCardApi extends CardApi {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Service<ECKey> getPrivateKeyService(StringProperty messageProperty) {
|
||||
return new PrivateKeyService(messageProperty);
|
||||
public Service<ECKey> getPrivateKeyService(Integer slot, StringProperty messageProperty) {
|
||||
return new PrivateKeyService(slot, messageProperty);
|
||||
}
|
||||
|
||||
ECKey getPrivateKey(int slot, boolean unsealed) throws CardException {
|
||||
if(unsealed) {
|
||||
ECKey getPrivateKey(int slot, int currentSlot) throws CardException {
|
||||
if(slot != currentSlot) {
|
||||
CardAuthDump cardAuthDump = cardProtocol.dump(cvc, slot);
|
||||
return cardAuthDump.getPrivateKey();
|
||||
}
|
||||
|
@ -458,9 +464,11 @@ public class CkCardApi extends CardApi {
|
|||
}
|
||||
|
||||
public class PrivateKeyService extends Service<ECKey> {
|
||||
private Integer slot;
|
||||
private final StringProperty messageProperty;
|
||||
|
||||
public PrivateKeyService(StringProperty messageProperty) {
|
||||
public PrivateKeyService(Integer slot, StringProperty messageProperty) {
|
||||
this.slot = slot;
|
||||
this.messageProperty = messageProperty;
|
||||
}
|
||||
|
||||
|
@ -474,17 +482,19 @@ public class CkCardApi extends CardApi {
|
|||
throw new IllegalStateException("Please use a " + WalletModel.SATSCARD.toDisplayString() + " to retrieve a private key.");
|
||||
}
|
||||
|
||||
int slot = cardStatus.getCurrentSlot();
|
||||
boolean unsealed = false;
|
||||
if(!cardStatus.isInitialized()) {
|
||||
int currentSlot = cardStatus.getCurrentSlot();
|
||||
if(slot == null) {
|
||||
slot = currentSlot;
|
||||
}
|
||||
|
||||
if(slot == currentSlot && !cardStatus.isInitialized()) {
|
||||
//If card has been unsealed, but a new slot is not initialized, retrieve private key for previous slot
|
||||
slot = slot - 1;
|
||||
unsealed = true;
|
||||
}
|
||||
|
||||
checkWait(cardStatus, new SimpleIntegerProperty(), messageProperty);
|
||||
|
||||
return getPrivateKey(slot, unsealed);
|
||||
return getPrivateKey(slot, currentSlot);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue