Search in sources :

Example 6 with KeyDerivation

use of com.sparrowwallet.drongo.KeyDerivation in project sparrow by sparrowwallet.

the class ColdcardMultisig method getKeystore.

@Override
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException {
    InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
    ColdcardKeystore cck = JsonPersistence.getGson().fromJson(reader, ColdcardKeystore.class);
    Keystore keystore = new Keystore("Coldcard");
    keystore.setSource(KeystoreSource.HW_AIRGAPPED);
    keystore.setWalletModel(WalletModel.COLDCARD);
    try {
        if (cck.xpub != null && cck.path != null) {
            ExtendedKey.Header header = ExtendedKey.Header.fromExtendedKey(cck.xpub);
            if (header.getDefaultScriptType() != scriptType) {
                throw new ImportException("This wallet's script type (" + scriptType + ") does not match the " + getName() + " script type (" + header.getDefaultScriptType() + ")");
            }
            keystore.setKeyDerivation(new KeyDerivation(cck.xfp, cck.path));
            keystore.setExtendedPublicKey(ExtendedKey.fromDescriptor(cck.xpub));
        } else if (scriptType.equals(ScriptType.P2SH)) {
            keystore.setKeyDerivation(new KeyDerivation(cck.xfp, cck.p2sh_deriv));
            keystore.setExtendedPublicKey(ExtendedKey.fromDescriptor(cck.p2sh));
        } else if (scriptType.equals(ScriptType.P2SH_P2WSH)) {
            keystore.setKeyDerivation(new KeyDerivation(cck.xfp, cck.p2wsh_p2sh_deriv != null ? cck.p2wsh_p2sh_deriv : cck.p2sh_p2wsh_deriv));
            keystore.setExtendedPublicKey(ExtendedKey.fromDescriptor(cck.p2wsh_p2sh != null ? cck.p2wsh_p2sh : cck.p2sh_p2wsh));
        } else if (scriptType.equals(ScriptType.P2WSH)) {
            keystore.setKeyDerivation(new KeyDerivation(cck.xfp, cck.p2wsh_deriv));
            keystore.setExtendedPublicKey(ExtendedKey.fromDescriptor(cck.p2wsh));
        } else {
            throw new ImportException("Correct derivation not found for script type: " + scriptType);
        }
    } catch (NullPointerException e) {
        throw new ImportException("Correct derivation not found for script type: " + scriptType);
    }
    return keystore;
}
Also used : Keystore(com.sparrowwallet.drongo.wallet.Keystore) KeyDerivation(com.sparrowwallet.drongo.KeyDerivation) ExtendedKey(com.sparrowwallet.drongo.ExtendedKey)

Example 7 with KeyDerivation

use of com.sparrowwallet.drongo.KeyDerivation in project sparrow by sparrowwallet.

the class KeystoreMapper method map.

@Override
public Keystore map(ResultSet rs, StatementContext ctx) throws SQLException {
    Keystore keystore = new Keystore(rs.getString("keystore.label"));
    keystore.setId(rs.getLong("keystore.id"));
    keystore.setSource(KeystoreSource.values()[rs.getInt("keystore.source")]);
    keystore.setWalletModel(WalletModel.values()[rs.getInt("keystore.walletModel")]);
    keystore.setKeyDerivation(new KeyDerivation(rs.getString("keystore.masterFingerprint"), rs.getString("keystore.derivationPath")));
    keystore.setExtendedPublicKey(rs.getString("keystore.extendedPublicKey") == null ? null : ExtendedKey.fromDescriptor(rs.getString("keystore.extendedPublicKey")));
    keystore.setExternalPaymentCode(rs.getString("keystore.externalPaymentCode") == null ? null : PaymentCode.fromString(rs.getString("keystore.externalPaymentCode")));
    if (rs.getBytes("masterPrivateExtendedKey.privateKey") != null) {
        MasterPrivateExtendedKey masterPrivateExtendedKey = new MasterPrivateExtendedKey(rs.getBytes("masterPrivateExtendedKey.privateKey"), rs.getBytes("masterPrivateExtendedKey.chainCode"));
        masterPrivateExtendedKey.setId(rs.getLong("masterPrivateExtendedKey.id"));
        keystore.setMasterPrivateExtendedKey(masterPrivateExtendedKey);
    } else if (rs.getBytes("masterPrivateExtendedKey.encryptedBytes") != null) {
        EncryptedData encryptedData = new EncryptedData(rs.getBytes("masterPrivateExtendedKey.initialisationVector"), rs.getBytes("masterPrivateExtendedKey.encryptedBytes"), rs.getBytes("masterPrivateExtendedKey.keySalt"), EncryptionType.Deriver.values()[rs.getInt("masterPrivateExtendedKey.deriver")], EncryptionType.Crypter.values()[rs.getInt("masterPrivateExtendedKey.crypter")]);
        MasterPrivateExtendedKey masterPrivateExtendedKey = new MasterPrivateExtendedKey(encryptedData);
        masterPrivateExtendedKey.setId(rs.getLong("masterPrivateExtendedKey.id"));
        keystore.setMasterPrivateExtendedKey(masterPrivateExtendedKey);
    }
    if (rs.getString("seed.mnemonicString") != null) {
        List<String> mnemonicCode = Arrays.asList(rs.getString("seed.mnemonicString").split(" "));
        DeterministicSeed seed = new DeterministicSeed(mnemonicCode, rs.getBoolean("seed.needsPassphrase"), rs.getLong("seed.creationTimeSeconds"), DeterministicSeed.Type.values()[rs.getInt("seed.type")]);
        seed.setId(rs.getLong("seed.id"));
        keystore.setSeed(seed);
    } else if (rs.getBytes("seed.encryptedBytes") != null) {
        EncryptedData encryptedData = new EncryptedData(rs.getBytes("seed.initialisationVector"), rs.getBytes("seed.encryptedBytes"), rs.getBytes("seed.keySalt"), EncryptionType.Deriver.values()[rs.getInt("seed.deriver")], EncryptionType.Crypter.values()[rs.getInt("seed.crypter")]);
        DeterministicSeed seed = new DeterministicSeed(encryptedData, rs.getBoolean("seed.needsPassphrase"), rs.getLong("seed.creationTimeSeconds"), DeterministicSeed.Type.values()[rs.getInt("seed.type")]);
        seed.setId(rs.getLong("seed.id"));
        keystore.setSeed(seed);
    }
    return keystore;
}
Also used : KeyDerivation(com.sparrowwallet.drongo.KeyDerivation) EncryptedData(com.sparrowwallet.drongo.crypto.EncryptedData)

Example 8 with KeyDerivation

use of com.sparrowwallet.drongo.KeyDerivation in project sparrow by sparrowwallet.

the class KeystoreImportDialog method getWatchOnlyKeystore.

private Keystore getWatchOnlyKeystore() {
    this.keystore = new Keystore();
    keystore.setSource(KeystoreSource.SW_WATCH);
    keystore.setWalletModel(WalletModel.SPARROW);
    keystore.setKeyDerivation(new KeyDerivation("", ""));
    return keystore;
}
Also used : Keystore(com.sparrowwallet.drongo.wallet.Keystore) KeyDerivation(com.sparrowwallet.drongo.KeyDerivation)

Example 9 with KeyDerivation

use of com.sparrowwallet.drongo.KeyDerivation in project sparrow by sparrowwallet.

the class InputController method describeScriptChunk.

@Override
protected String describeScriptChunk(ScriptChunk chunk) {
    String chunkString = super.describeScriptChunk(chunk);
    ECKey pubKey = null;
    if (chunk.isSignature()) {
        if (inputForm.getPsbtInput() != null) {
            TransactionSignature signature = chunk.getSignature();
            pubKey = inputForm.getPsbtInput().getKeyForSignature(signature);
        }
    } else if (chunk.isPubKey()) {
        pubKey = chunk.getPubKey();
    }
    if (inputForm.getPsbtInput() != null) {
        KeyDerivation derivation = inputForm.getPsbtInput().getKeyDerivation(pubKey);
        if (derivation != null) {
            return "[" + derivation.toString() + "] " + chunkString;
        }
    }
    return chunkString;
}
Also used : KeyDerivation(com.sparrowwallet.drongo.KeyDerivation) ECKey(com.sparrowwallet.drongo.crypto.ECKey)

Example 10 with KeyDerivation

use of com.sparrowwallet.drongo.KeyDerivation in project sparrow by sparrowwallet.

the class Electrum method importWallet.

@Override
public Wallet importWallet(InputStream inputStream, String password) throws ImportException {
    Reader reader;
    if (password != null) {
        ECKey decryptionKey = Pbkdf2KeyDeriver.DEFAULT_INSTANCE.deriveECKey(password);
        reader = new InputStreamReader(new InflaterInputStream(new ECIESInputStream(inputStream, decryptionKey)), StandardCharsets.UTF_8);
    } else {
        reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
    }
    try {
        Gson gson = new Gson();
        Type stringStringMap = new TypeToken<Map<String, JsonElement>>() {
        }.getType();
        Map<String, JsonElement> map = gson.fromJson(reader, stringStringMap);
        ElectrumJsonWallet ew = new ElectrumJsonWallet();
        if (map.get("wallet_type") == null) {
            throw new ImportException("File was not a valid Electrum wallet");
        }
        ew.wallet_type = map.get("wallet_type").getAsString();
        for (String key : map.keySet()) {
            if (key.startsWith("x") || key.equals("keystore")) {
                ElectrumKeystore ek = gson.fromJson(map.get(key), ElectrumKeystore.class);
                if (ek.root_fingerprint == null && ek.ckcc_xfp != null) {
                    byte[] le = new byte[4];
                    Utils.uint32ToByteArrayLE(Long.parseLong(ek.ckcc_xfp), le, 0);
                    ek.root_fingerprint = Utils.bytesToHex(le).toUpperCase();
                }
                ew.keystores.put(key, ek);
            }
            if (key.equals("labels")) {
                JsonObject jsonObject = (JsonObject) map.get(key);
                for (String labelKey : jsonObject.keySet()) {
                    ew.labels.put(labelKey, jsonObject.get(labelKey).getAsString());
                }
            }
            if (key.equals("addresses")) {
                ew.addresses = gson.fromJson(map.get(key), ElectrumAddresses.class);
            }
            if (key.equals("verified_tx3")) {
                JsonObject jsonObject = (JsonObject) map.get(key);
                for (String txKey : jsonObject.keySet()) {
                    Sha256Hash txHash = Sha256Hash.wrap(txKey);
                    JsonArray array = jsonObject.getAsJsonArray(txKey);
                    if (array != null && array.size() > 3) {
                        int height = array.get(0).getAsInt();
                        Date date = new Date(array.get(1).getAsLong() * 1000);
                        long fee = array.get(2).getAsLong();
                        Sha256Hash blockHash = Sha256Hash.wrap(array.get(3).getAsString());
                        JsonObject transactions = (JsonObject) map.get("transactions");
                        if (transactions != null) {
                            String txhex = transactions.get(txKey).getAsString();
                            if (txhex != null) {
                                Transaction transaction = new Transaction(Utils.hexToBytes(txhex));
                                BlockTransaction blockTransaction = new BlockTransaction(txHash, height, date, fee, transaction, blockHash);
                                ew.transactions.put(txHash, blockTransaction);
                            }
                        }
                    }
                }
            }
        }
        Wallet wallet = new Wallet();
        ScriptType scriptType = null;
        for (ElectrumKeystore ek : ew.keystores.values()) {
            Keystore keystore = new Keystore();
            ExtendedKey xPub = ExtendedKey.fromDescriptor(ek.xpub);
            String derivationPath = ek.derivation;
            if (derivationPath == null) {
                derivationPath = "m/0";
            }
            String masterFingerprint = ek.root_fingerprint;
            if (masterFingerprint == null) {
                masterFingerprint = Utils.bytesToHex(xPub.getParentFingerprint());
            }
            if ("hardware".equals(ek.type)) {
                keystore.setSource(KeystoreSource.HW_USB);
                keystore.setWalletModel(WalletModel.fromType(ek.hw_type));
                if (keystore.getWalletModel() == null) {
                    throw new ImportException("Wallet has keystore of unknown hardware wallet type \"" + ek.hw_type + "\".");
                }
                if (keystore.getWalletModel().equals(WalletModel.TREZOR_1)) {
                    keystore.setWalletModel(WalletModel.TREZOR_T);
                }
            } else if ("bip32".equals(ek.type)) {
                if (ek.xprv != null && ek.seed == null) {
                    throw new ImportException("Electrum does not support exporting BIP39 derived seeds, as it does not store the mnemonic words. Only seeds created with its native Electrum Seed Version System are exportable. " + "If you have the mnemonic words, create a new wallet with a BIP39 keystore.");
                } else if (ek.seed != null) {
                    keystore.setSource(KeystoreSource.SW_SEED);
                    String mnemonic = ek.seed;
                    String passphrase = ek.passphrase;
                    if (password != null) {
                        mnemonic = decrypt(mnemonic, password);
                        passphrase = decrypt(passphrase, password);
                    }
                    keystore.setSeed(new DeterministicSeed(mnemonic, passphrase, 0, DeterministicSeed.Type.ELECTRUM));
                    // Ensure the derivation path from the seed matches the provided xpub
                    String[] possibleDerivations = { "m", "m/0", "m/0'" };
                    for (String possibleDerivation : possibleDerivations) {
                        List<ChildNumber> derivation = KeyDerivation.parsePath(possibleDerivation);
                        DeterministicKey derivedKey = keystore.getExtendedMasterPrivateKey().getKey(derivation);
                        DeterministicKey derivedKeyPublicOnly = derivedKey.dropPrivateBytes().dropParent();
                        ExtendedKey xpub = new ExtendedKey(derivedKeyPublicOnly, derivedKey.getParentFingerprint(), derivation.isEmpty() ? ChildNumber.ZERO : derivation.get(derivation.size() - 1));
                        if (xpub.equals(xPub)) {
                            derivationPath = possibleDerivation;
                            break;
                        }
                    }
                } else {
                    keystore.setSource(KeystoreSource.SW_WATCH);
                }
                keystore.setWalletModel(WalletModel.ELECTRUM);
            }
            keystore.setKeyDerivation(new KeyDerivation(masterFingerprint, derivationPath));
            keystore.setExtendedPublicKey(xPub);
            keystore.setLabel(ek.label != null ? ek.label : "Electrum");
            if (keystore.getLabel().length() > Keystore.MAX_LABEL_LENGTH) {
                keystore.setLabel(keystore.getLabel().substring(0, Keystore.MAX_LABEL_LENGTH));
            }
            wallet.getKeystores().add(keystore);
            ExtendedKey.Header xpubHeader = ExtendedKey.Header.fromExtendedKey(ek.xpub);
            scriptType = xpubHeader.getDefaultScriptType();
        }
        wallet.setScriptType(scriptType);
        if (ew.wallet_type.equals("standard")) {
            wallet.setPolicyType(PolicyType.SINGLE);
            wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, scriptType, wallet.getKeystores(), 1));
        } else if (ew.wallet_type.contains("of")) {
            wallet.setPolicyType(PolicyType.MULTI);
            String[] mOfn = ew.wallet_type.split("of");
            int threshold = Integer.parseInt(mOfn[0]);
            wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI, scriptType, wallet.getKeystores(), threshold));
        } else {
            throw new ImportException("Unknown Electrum wallet type of " + ew.wallet_type);
        }
        for (String key : ew.labels.keySet()) {
            try {
                Sha256Hash txHash = Sha256Hash.wrap(key);
                BlockTransaction blockTransaction = ew.transactions.get(txHash);
                if (blockTransaction != null) {
                    blockTransaction.setLabel(ew.labels.get(key));
                }
            } catch (Exception e) {
                // not a tx - try an address
                if (ew.addresses != null) {
                    try {
                        Address address = Address.fromString(key);
                        Map<KeyPurpose, List<String>> keyPurposes = Map.of(KeyPurpose.RECEIVE, ew.addresses.receiving, KeyPurpose.CHANGE, ew.addresses.change);
                        for (KeyPurpose keyPurpose : keyPurposes.keySet()) {
                            WalletNode purposeNode = wallet.getNode(keyPurpose);
                            purposeNode.fillToIndex(keyPurposes.get(keyPurpose).size() - 1);
                            for (WalletNode addressNode : purposeNode.getChildren()) {
                                if (address.equals(addressNode.getAddress())) {
                                    addressNode.setLabel(ew.labels.get(key));
                                }
                            }
                        }
                        for (BlockTransaction blkTx : ew.transactions.values()) {
                            if (blkTx.getLabel() == null) {
                                Transaction tx = blkTx.getTransaction();
                                for (TransactionOutput txOutput : tx.getOutputs()) {
                                    try {
                                        Address[] addresses = txOutput.getScript().getToAddresses();
                                        if (Arrays.asList(addresses).contains(address)) {
                                            blkTx.setLabel(ew.labels.get(key));
                                        }
                                    } catch (NonStandardScriptException ex) {
                                    // ignore
                                    }
                                }
                            }
                        }
                    } catch (Exception ex) {
                    // not an address
                    }
                }
            }
        }
        wallet.updateTransactions(ew.transactions);
        try {
            wallet.checkWallet();
        } catch (InvalidWalletException e) {
            throw new IllegalStateException("Imported Electrum wallet was invalid: " + e.getMessage());
        }
        return wallet;
    } catch (Exception e) {
        throw new ImportException("Error importing Electrum Wallet", e);
    }
}
Also used : Address(com.sparrowwallet.drongo.address.Address) KeyPurpose(com.sparrowwallet.drongo.KeyPurpose) InflaterInputStream(java.util.zip.InflaterInputStream) KeyDerivation(com.sparrowwallet.drongo.KeyDerivation) PolicyType(com.sparrowwallet.drongo.policy.PolicyType) Type(java.lang.reflect.Type) ExtendedKey(com.sparrowwallet.drongo.ExtendedKey)

Aggregations

KeyDerivation (com.sparrowwallet.drongo.KeyDerivation)17 ExtendedKey (com.sparrowwallet.drongo.ExtendedKey)8 ScriptType (com.sparrowwallet.drongo.protocol.ScriptType)4 Keystore (com.sparrowwallet.drongo.wallet.Keystore)4 InputStreamReader (java.io.InputStreamReader)4 PolicyType (com.sparrowwallet.drongo.policy.PolicyType)3 Test (org.junit.Test)3 Gson (com.google.gson.Gson)2 KeyPurpose (com.sparrowwallet.drongo.KeyPurpose)2 Wallet (com.sparrowwallet.drongo.wallet.Wallet)2 Type (java.lang.reflect.Type)2 ArrayList (java.util.ArrayList)2 JsonElement (com.google.gson.JsonElement)1 OutputDescriptor (com.sparrowwallet.drongo.OutputDescriptor)1 SecureString (com.sparrowwallet.drongo.SecureString)1 Utils (com.sparrowwallet.drongo.Utils)1 Address (com.sparrowwallet.drongo.address.Address)1 PaymentAddress (com.sparrowwallet.drongo.bip47.PaymentAddress)1 PaymentCode (com.sparrowwallet.drongo.bip47.PaymentCode)1 com.sparrowwallet.drongo.crypto (com.sparrowwallet.drongo.crypto)1