mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 05:06:45 +00:00
keycrypter changes
This commit is contained in:
parent
9241f4381f
commit
d7c6f5d587
13 changed files with 46 additions and 16 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
||||||
Subproject commit c675e395dbbf386d2371ac3819b2a4539bf25e95
|
Subproject commit 242c83735a24456a4bd23fd556a56122c9b259ab
|
|
@ -1,7 +1,7 @@
|
||||||
package com.sparrowwallet.sparrow.control;
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECIESKeyCrypter;
|
||||||
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.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
|
@ -83,7 +83,7 @@ public class FileKeystoreImportPane extends KeystoreImportPane {
|
||||||
if(e.getCause() != null && e.getCause().getMessage() != null && !e.getCause().getMessage().isEmpty()) {
|
if(e.getCause() != null && e.getCause().getMessage() != null && !e.getCause().getMessage().isEmpty()) {
|
||||||
errorMessage = e.getCause().getMessage();
|
errorMessage = e.getCause().getMessage();
|
||||||
}
|
}
|
||||||
if(e instanceof ECKey.InvalidPasswordException || e.getCause() instanceof ECKey.InvalidPasswordException) {
|
if(e instanceof ECIESKeyCrypter.InvalidPasswordException || e.getCause() instanceof ECIESKeyCrypter.InvalidPasswordException) {
|
||||||
errorMessage = "Invalid wallet password";
|
errorMessage = "Invalid wallet password";
|
||||||
}
|
}
|
||||||
if(e instanceof JsonParseException || e.getCause() instanceof JsonParseException) {
|
if(e instanceof JsonParseException || e.getCause() instanceof JsonParseException) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.crypto.ChildNumber;
|
import com.sparrowwallet.drongo.crypto.ChildNumber;
|
||||||
import com.sparrowwallet.drongo.wallet.Bip39MnemonicCode;
|
import com.sparrowwallet.drongo.wallet.Bip39MnemonicCode;
|
||||||
|
import com.sparrowwallet.drongo.wallet.DeterministicSeed;
|
||||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
import com.sparrowwallet.drongo.wallet.WalletModel;
|
import com.sparrowwallet.drongo.wallet.WalletModel;
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ public class Bip39 implements KeystoreMnemonicImport {
|
||||||
public Keystore getKeystore(List<ChildNumber> derivation, List<String> mnemonicWords, String passphrase) throws ImportException {
|
public Keystore getKeystore(List<ChildNumber> derivation, List<String> mnemonicWords, String passphrase) throws ImportException {
|
||||||
try {
|
try {
|
||||||
Bip39MnemonicCode.INSTANCE.check(mnemonicWords);
|
Bip39MnemonicCode.INSTANCE.check(mnemonicWords);
|
||||||
byte[] seed = Bip39MnemonicCode.toSeed(mnemonicWords, passphrase);
|
DeterministicSeed seed = new DeterministicSeed(mnemonicWords, null, passphrase, System.currentTimeMillis());
|
||||||
return Keystore.fromSeed(seed, derivation);
|
return Keystore.fromSeed(seed, derivation);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ImportException(e);
|
throw new ImportException(e);
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package com.sparrowwallet.sparrow.io;
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.sparrowwallet.drongo.crypto.ECIESKeyCrypter;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
|
import com.sparrowwallet.drongo.crypto.EncryptedData;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
@ -38,9 +40,11 @@ public class ECIESInputStream extends FilterInputStream {
|
||||||
|
|
||||||
private synchronized void ensureDecrypted() throws IOException {
|
private synchronized void ensureDecrypted() throws IOException {
|
||||||
if(!decrypted) {
|
if(!decrypted) {
|
||||||
byte[] encrypted = ByteStreams.toByteArray(in);
|
byte[] encryptedBytes = ByteStreams.toByteArray(in);
|
||||||
in.close();
|
in.close();
|
||||||
in = new ByteArrayInputStream(decryptionKey.decryptEcies(encrypted, encryptionMagic));
|
ECIESKeyCrypter keyCrypter = new ECIESKeyCrypter();
|
||||||
|
byte[] decryptedBytes = keyCrypter.decrypt(new EncryptedData(encryptionMagic, encryptedBytes), decryptionKey);
|
||||||
|
in = new ByteArrayInputStream(decryptedBytes);
|
||||||
decrypted = true;
|
decrypted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package com.sparrowwallet.sparrow.io;
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.sparrowwallet.drongo.crypto.ECIESKeyCrypter;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
|
import com.sparrowwallet.drongo.crypto.EncryptedData;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
@ -32,8 +34,9 @@ public class ECIESOutputStream extends FilterOutputStream {
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
super.close();
|
super.close();
|
||||||
byte[] unencrypted = ((ByteArrayOutputStream)out).toByteArray();
|
byte[] unencrypted = ((ByteArrayOutputStream)out).toByteArray();
|
||||||
byte[] encryptedWallet = encryptionKey.encryptEcies(unencrypted, encryptionMagic);
|
ECIESKeyCrypter keyCrypter = new ECIESKeyCrypter();
|
||||||
ByteStreams.copy(new ByteArrayInputStream(encryptedWallet), encryptedStream);
|
EncryptedData encryptedData = keyCrypter.encrypt(unencrypted, encryptionMagic, encryptionKey);
|
||||||
|
ByteStreams.copy(new ByteArrayInputStream(encryptedData.getEncryptedBytes()), encryptedStream);
|
||||||
encryptedStream.flush();
|
encryptedStream.flush();
|
||||||
encryptedStream.close();
|
encryptedStream.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.google.gson.reflect.TypeToken;
|
||||||
import com.sparrowwallet.drongo.ExtendedKey;
|
import com.sparrowwallet.drongo.ExtendedKey;
|
||||||
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.ECIESKeyCrypter;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
import com.sparrowwallet.drongo.policy.Policy;
|
import com.sparrowwallet.drongo.policy.Policy;
|
||||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
|
@ -57,7 +58,7 @@ public class Electrum implements KeystoreFileImport, SinglesigWalletImport, Mult
|
||||||
public Wallet importWallet(InputStream inputStream, String password) throws ImportException {
|
public Wallet importWallet(InputStream inputStream, String password) throws ImportException {
|
||||||
Reader reader;
|
Reader reader;
|
||||||
if(password != null) {
|
if(password != null) {
|
||||||
ECKey decryptionKey = ECKey.createKeyPbkdf2HmacSha512(password);
|
ECKey decryptionKey = ECIESKeyCrypter.deriveECKey(password);
|
||||||
reader = new InputStreamReader(new InflaterInputStream(new ECIESInputStream(inputStream, decryptionKey)));
|
reader = new InputStreamReader(new InflaterInputStream(new ECIESInputStream(inputStream, decryptionKey)));
|
||||||
} else {
|
} else {
|
||||||
reader = new InputStreamReader(inputStream);
|
reader = new InputStreamReader(inputStream);
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class Storage {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] getEncryptionMagic() {
|
private static byte[] getEncryptionMagic() {
|
||||||
return "SPRW1".getBytes(StandardCharsets.UTF_8);
|
return "BIE1".getBytes(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getWalletFile(String walletName) {
|
public File getWalletFile(String walletName) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.sparrowwallet.sparrow.wallet;
|
package com.sparrowwallet.sparrow.wallet;
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import com.sparrowwallet.drongo.crypto.ECIESKeyCrypter;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
import com.sparrowwallet.drongo.policy.Policy;
|
import com.sparrowwallet.drongo.policy.Policy;
|
||||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
|
@ -279,7 +280,7 @@ public class SettingsController extends WalletFormController implements Initiali
|
||||||
return Optional.of(WalletForm.NO_PASSWORD_KEY);
|
return Optional.of(WalletForm.NO_PASSWORD_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
ECKey encryptionFullKey = ECKey.createKeyPbkdf2HmacSha512(password.get());
|
ECKey encryptionFullKey = ECIESKeyCrypter.deriveECKey(password.get());
|
||||||
ECKey encryptionPubKey = ECKey.fromPublicOnly(encryptionFullKey);
|
ECKey encryptionPubKey = ECKey.fromPublicOnly(encryptionFullKey);
|
||||||
if(existingPubKey != null) {
|
if(existingPubKey != null) {
|
||||||
if(WalletForm.NO_PASSWORD_KEY.equals(existingPubKey) || existingPubKey.equals(encryptionPubKey)) {
|
if(WalletForm.NO_PASSWORD_KEY.equals(existingPubKey) || existingPubKey.equals(encryptionPubKey)) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.sparrowwallet.sparrow.wallet;
|
package com.sparrowwallet.sparrow.wallet;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.crypto.ECIESKeyCrypter;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.sparrow.io.Storage;
|
import com.sparrowwallet.sparrow.io.Storage;
|
||||||
|
@ -8,7 +9,7 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class WalletForm {
|
public class WalletForm {
|
||||||
public static final ECKey NO_PASSWORD_KEY = ECKey.fromPublicOnly(ECKey.createKeyPbkdf2HmacSha512(""));
|
public static final ECKey NO_PASSWORD_KEY = ECKey.fromPublicOnly(ECIESKeyCrypter.deriveECKey(""));
|
||||||
|
|
||||||
private File walletFile;
|
private File walletFile;
|
||||||
private ECKey encryptionPubKey;
|
private ECKey encryptionPubKey;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.sparrowwallet.sparrow.io;
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.crypto.ECIESKeyCrypter;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
@ -13,7 +14,7 @@ public class ECIESInputStreamTest extends IoTest {
|
||||||
@Test
|
@Test
|
||||||
public void decrypt() throws ImportException {
|
public void decrypt() throws ImportException {
|
||||||
Electrum electrum = new Electrum();
|
Electrum electrum = new Electrum();
|
||||||
ECKey decryptionKey = ECKey.createKeyPbkdf2HmacSha512("pass");
|
ECKey decryptionKey = ECIESKeyCrypter.deriveECKey("pass");
|
||||||
Wallet wallet = electrum.importWallet(new InflaterInputStream(new ECIESInputStream(getInputStream("electrum-encrypted"), decryptionKey)), null);
|
Wallet wallet = electrum.importWallet(new InflaterInputStream(new ECIESInputStream(getInputStream("electrum-encrypted"), decryptionKey)), null);
|
||||||
|
|
||||||
Assert.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
|
Assert.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.sparrowwallet.sparrow.io;
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.crypto.ECIESKeyCrypter;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
@ -16,7 +17,7 @@ public class ECIESOutputStreamTest extends IoTest {
|
||||||
@Test
|
@Test
|
||||||
public void encrypt() throws ImportException, ExportException {
|
public void encrypt() throws ImportException, ExportException {
|
||||||
Electrum electrum = new Electrum();
|
Electrum electrum = new Electrum();
|
||||||
ECKey decryptionKey = ECKey.createKeyPbkdf2HmacSha512("pass");
|
ECKey decryptionKey = ECIESKeyCrypter.deriveECKey("pass");
|
||||||
Wallet wallet = electrum.importWallet(new InflaterInputStream(new ECIESInputStream(getInputStream("electrum-encrypted"), decryptionKey)), null);
|
Wallet wallet = electrum.importWallet(new InflaterInputStream(new ECIESInputStream(getInputStream("electrum-encrypted"), decryptionKey)), null);
|
||||||
|
|
||||||
ECKey encyptionKey = ECKey.fromPublicOnly(decryptionKey);
|
ECKey encyptionKey = ECKey.fromPublicOnly(decryptionKey);
|
||||||
|
|
|
@ -83,4 +83,20 @@ public class ElectrumTest extends IoTest {
|
||||||
Assert.assertEquals("7bb026be", wallet.getKeystores().get(2).getKeyDerivation().getMasterFingerprint());
|
Assert.assertEquals("7bb026be", wallet.getKeystores().get(2).getKeyDerivation().getMasterFingerprint());
|
||||||
Assert.assertEquals("m/48'/1'/0'/1'", wallet.getKeystores().get(2).getKeyDerivation().getDerivationPath());
|
Assert.assertEquals("m/48'/1'/0'/1'", wallet.getKeystores().get(2).getKeyDerivation().getDerivationPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncryptedImport() throws ImportException, IOException {
|
||||||
|
Electrum electrum = new Electrum();
|
||||||
|
byte[] walletBytes = ByteStreams.toByteArray(getInputStream("electrum-encrypted"));
|
||||||
|
Wallet wallet = electrum.importWallet(new ByteArrayInputStream(walletBytes), "pass");
|
||||||
|
|
||||||
|
Assert.assertTrue(wallet.isValid());
|
||||||
|
Assert.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
|
||||||
|
Assert.assertEquals(ScriptType.P2WPKH, wallet.getScriptType());
|
||||||
|
Assert.assertEquals(1, wallet.getDefaultPolicy().getNumSignaturesRequired());
|
||||||
|
Assert.assertEquals("pkh(electrum05aba071)", wallet.getDefaultPolicy().getMiniscript().getScript());
|
||||||
|
Assert.assertEquals("05aba071", wallet.getKeystores().get(0).getKeyDerivation().getMasterFingerprint());
|
||||||
|
Assert.assertEquals("m/0'", wallet.getKeystores().get(0).getKeyDerivation().getDerivationPath());
|
||||||
|
Assert.assertEquals("xpub67vv394epQsLhdjNGx7dfgURicP7XwBMuHPTVAMdXcXhDuC9VP8SqVvh2cYqKWm9xoUd6YynWK8JzRcXpmeuZFRH7i1kt8fR9GXoJSiHk1E", wallet.getKeystores().get(0).getExtendedPublicKey().toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.sparrowwallet.sparrow.io;
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.crypto.ECIESKeyCrypter;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -12,14 +13,14 @@ import java.io.IOException;
|
||||||
public class StorageTest extends IoTest {
|
public class StorageTest extends IoTest {
|
||||||
@Test
|
@Test
|
||||||
public void loadWallet() throws IOException {
|
public void loadWallet() throws IOException {
|
||||||
ECKey decryptionKey = ECKey.createKeyPbkdf2HmacSha512("pass");
|
ECKey decryptionKey = ECIESKeyCrypter.deriveECKey("pass");
|
||||||
Wallet wallet = Storage.getStorage().loadWallet(getFile("sparrow-single-wallet"), decryptionKey);
|
Wallet wallet = Storage.getStorage().loadWallet(getFile("sparrow-single-wallet"), decryptionKey);
|
||||||
Assert.assertTrue(wallet.isValid());
|
Assert.assertTrue(wallet.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void saveWallet() throws IOException {
|
public void saveWallet() throws IOException {
|
||||||
ECKey decryptionKey = ECKey.createKeyPbkdf2HmacSha512("pass");
|
ECKey decryptionKey = ECIESKeyCrypter.deriveECKey("pass");
|
||||||
Wallet wallet = Storage.getStorage().loadWallet(getFile("sparrow-single-wallet"), decryptionKey);
|
Wallet wallet = Storage.getStorage().loadWallet(getFile("sparrow-single-wallet"), decryptionKey);
|
||||||
Assert.assertTrue(wallet.isValid());
|
Assert.assertTrue(wallet.isValid());
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue