/** * Returns a new BasicKeyChain that contains all basic, ORIGINAL type keys extracted from the list. Unrecognised * key types are ignored. */ public static BasicKeyChain fromProtobufUnencrypted(List<Protos.Key> keys) throws UnreadableWalletException { BasicKeyChain chain = new BasicKeyChain(); chain.deserializeFromProtobuf(keys); return chain; }
@Override public void addEventListener(KeyChainEventListener listener, Executor executor) { basicKeyChain.addEventListener(listener, executor); }
public DeterministicKey findKeyFromPubHash(byte[] pubkeyHash) { lock.lock(); try { return (DeterministicKey) basicKeyChain.findKeyFromPubHash(pubkeyHash); } finally { lock.unlock(); } }
@Override public BasicKeyChain toDecrypted(KeyParameter aesKey) { lock.lock(); try { checkState(keyCrypter != null, "Wallet is already decrypted"); // Do an up-front check. if (numKeys() > 0 && !checkAESKey(aesKey)) throw new KeyCrypterException("Password/key was incorrect."); BasicKeyChain decrypted = new BasicKeyChain(); for (ECKey key : hashToKeys.values()) { decrypted.importKeyLocked(key.decrypt(aesKey)); } return decrypted; } finally { lock.unlock(); } }
@Test public void serializationEncrypted() throws UnreadableWalletException { ECKey key1 = new ECKey(); chain.importKeys(key1); chain = chain.toEncrypted("foo bar"); key1 = chain.getKeys().get(0); List<Protos.Key> keys = chain.serializeToProtobuf(); assertEquals(1, keys.size()); assertArrayEquals(key1.getPubKey(), keys.get(0).getPublicKey().toByteArray()); assertFalse(keys.get(0).hasSecretBytes()); assertTrue(keys.get(0).hasEncryptedData()); chain = BasicKeyChain.fromProtobufEncrypted(keys, checkNotNull(chain.getKeyCrypter())); assertEquals(key1.getEncryptedPrivateKey(), chain.getKeys().get(0).getEncryptedPrivateKey()); assertTrue(chain.checkPassword("foo bar")); }
@Test public void importKeys() { long now = Utils.currentTimeSeconds(); Utils.setMockClock(now); final ECKey key1 = new ECKey(); Utils.rollMockClock(86400); final ECKey key2 = new ECKey(); final ArrayList<ECKey> keys = Lists.newArrayList(key1, key2); // Import two keys, check the event is correct. assertEquals(2, chain.importKeys(keys)); assertEquals(2, chain.numKeys()); assertTrue(onKeysAddedRan.getAndSet(false)); assertArrayEquals(keys.toArray(), onKeysAdded.get().toArray()); assertEquals(now, chain.getEarliestKeyCreationTime()); // Check we ignore duplicates. final ECKey newKey = new ECKey(); keys.add(newKey); assertEquals(1, chain.importKeys(keys)); assertTrue(onKeysAddedRan.getAndSet(false)); assertEquals(newKey, onKeysAdded.getAndSet(null).get(0)); assertEquals(0, chain.importKeys(keys)); assertFalse(onKeysAddedRan.getAndSet(false)); assertNull(onKeysAdded.get()); assertTrue(chain.hasKey(key1)); assertTrue(chain.hasKey(key2)); assertEquals(key1, chain.findKeyFromPubHash(key1.getPubKeyHash())); assertEquals(key2, chain.findKeyFromPubKey(key2.getPubKey())); assertNull(chain.findKeyFromPubKey(key2.getPubKeyHash())); }
@Test public void watching() throws UnreadableWalletException { ECKey key1 = new ECKey(); ECKey pub = ECKey.fromPublicOnly(key1.getPubKeyPoint()); chain.importKeys(pub); assertEquals(1, chain.numKeys()); List<Protos.Key> keys = chain.serializeToProtobuf(); assertEquals(1, keys.size()); assertTrue(keys.get(0).hasPublicKey()); assertFalse(keys.get(0).hasSecretBytes()); chain = BasicKeyChain.fromProtobufUnencrypted(keys); assertEquals(1, chain.numKeys()); assertFalse(chain.findKeyFromPubKey(pub.getPubKey()).hasPrivKey()); }
checkState(basic.numKeys() > 0); checkArgument(keyRotationTimeSecs >= 0); ECKey keyToUse = basic.findOldestKeyAfter(keyRotationTimeSecs - 1); if (keyToUse == null) throw new AllRandomKeysRotating(); DeterministicKeyChain chain = new DeterministicKeyChain(entropy, passphrase, keyToUse.getCreationTimeSeconds()); if (aesKey != null) { chain = chain.toEncrypted(checkNotNull(basic.getKeyCrypter()), aesKey);
@Test public void encryptDecrypt() { final ECKey key1 = new ECKey(); chain.importKeys(key1, new ECKey()); final String PASSWORD = "foobar"; chain = chain.toEncrypted(PASSWORD); final KeyCrypter keyCrypter = chain.getKeyCrypter(); assertNotNull(keyCrypter); assertTrue(keyCrypter instanceof KeyCrypterScrypt); assertTrue(chain.checkPassword(PASSWORD)); assertFalse(chain.checkPassword("wrong")); ECKey key = chain.findKeyFromPubKey(key1.getPubKey()); assertTrue(key.isEncrypted()); assertTrue(key.isPubKeyOnly()); chain.importKeys(new ECKey()); fail(); } catch (KeyCrypterException e) { chain.toDecrypted(keyCrypter.deriveKey("wrong")); fail(); } catch (KeyCrypterException e) {} chain = chain.toDecrypted(PASSWORD); key = chain.findKeyFromPubKey(key1.getPubKey()); assertFalse(key.isEncrypted()); assertFalse(key.isPubKeyOnly());
@Test public void serializationUnencrypted() throws UnreadableWalletException { Utils.setMockClock(); Date now = Utils.now(); final ECKey key1 = new ECKey(); Utils.rollMockClock(5000); final ECKey key2 = new ECKey(); chain.importKeys(ImmutableList.of(key1, key2)); List<Protos.Key> keys = chain.serializeToProtobuf(); assertEquals(2, keys.size()); assertArrayEquals(key1.getPubKey(), keys.get(0).getPublicKey().toByteArray()); assertArrayEquals(key2.getPubKey(), keys.get(1).getPublicKey().toByteArray()); assertArrayEquals(key1.getPrivKeyBytes(), keys.get(0).getSecretBytes().toByteArray()); assertArrayEquals(key2.getPrivKeyBytes(), keys.get(1).getSecretBytes().toByteArray()); long normTime = (long) (Math.floor(now.getTime() / 1000) * 1000); assertEquals(normTime, keys.get(0).getCreationTimestamp()); assertEquals(normTime + 5000 * 1000, keys.get(1).getCreationTimestamp()); chain = BasicKeyChain.fromProtobufUnencrypted(keys); assertEquals(2, chain.getKeys().size()); assertEquals(key1, chain.getKeys().get(0)); assertEquals(key2, chain.getKeys().get(1)); }
@Test(expected = KeyCrypterException.class) public void cannotImportEncryptedKey() { final ECKey key1 = new ECKey(); chain.importKeys(ImmutableList.of(key1)); chain = chain.toEncrypted("foobar"); ECKey encryptedKey = chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); assertTrue(encryptedKey.isEncrypted()); BasicKeyChain chain2 = new BasicKeyChain(); chain2.importKeys(ImmutableList.of(encryptedKey)); }
@Test public void bloom() throws Exception { ECKey key1 = new ECKey(); ECKey key2 = new ECKey(); chain.importKeys(key1, key2); assertEquals(2, chain.numKeys()); assertEquals(4, chain.numBloomFilterEntries()); BloomFilter filter = chain.getFilter(4, 0.001, 100); assertTrue(filter.contains(key1.getPubKey())); assertTrue(filter.contains(key1.getPubKeyHash())); assertTrue(filter.contains(key2.getPubKey())); assertTrue(filter.contains(key2.getPubKeyHash())); ECKey key3 = new ECKey(); assertFalse(filter.contains(key3.getPubKey())); }
public BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak) { BloomFilter filter = new BloomFilter(size, falsePositiveRate, nTweak); if (basic.numKeys() > 0) filter.merge(basic.getFilter(size, falsePositiveRate, nTweak)); for (DeterministicKeyChain chain : chains) { filter.merge(chain.getFilter(size, falsePositiveRate, nTweak)); } return filter; }
public DeterministicKey findKeyFromPubKey(byte[] pubkey) { lock.lock(); try { return (DeterministicKey) basicKeyChain.findKeyFromPubKey(pubkey); } finally { lock.unlock(); } }
private DeterministicKey encryptNonLeaf(KeyParameter aesKey, DeterministicKeyChain chain, DeterministicKey parent, ImmutableList<ChildNumber> path) { DeterministicKey key = chain.hierarchy.get(path, false, false); key = key.encrypt(checkNotNull(basicKeyChain.getKeyCrypter()), aesKey, parent); hierarchy.putKey(key); basicKeyChain.importKey(key); return key; }
@Before public void setup() { chain = new BasicKeyChain(); onKeysAdded = new AtomicReference<>(); onKeysAddedRan = new AtomicBoolean(); chain.addEventListener(new AbstractKeyChainEventListener() { @Override public void onKeysAdded(List<ECKey> keys2) { onKeysAdded.set(keys2); onKeysAddedRan.set(true); } }, Threading.SAME_THREAD); }
@Test public void keysBeforeAndAfter() throws Exception { Utils.setMockClock(); long now = Utils.currentTimeSeconds(); final ECKey key1 = new ECKey(); Utils.rollMockClock(86400); final ECKey key2 = new ECKey(); final List<ECKey> keys = Lists.newArrayList(key1, key2); assertEquals(2, chain.importKeys(keys)); assertNull(chain.findOldestKeyAfter(now + 86400 * 2)); assertEquals(key1, chain.findOldestKeyAfter(now - 1)); assertEquals(key2, chain.findOldestKeyAfter(now + 86400 - 1)); assertEquals(2, chain.findKeysBefore(now + 86400 * 2).size()); assertEquals(1, chain.findKeysBefore(now + 1).size()); assertEquals(0, chain.findKeysBefore(now - 1).size()); } }
/** * Creates a deterministic key chain that watches the given (public only) root key. You can use this to calculate * balances and generally follow along, but spending is not possible with such a chain. Currently you can't use * this method to watch an arbitrary fragment of some other tree, this limitation may be removed in future. */ public DeterministicKeyChain(DeterministicKey watchingKey) { checkArgument(watchingKey.isPubKeyOnly(), "Private subtrees not currently supported: if you got this key from DKC.getWatchingKey() then use .dropPrivate().dropParent() on it first."); checkArgument(watchingKey.getPath().size() == getAccountPath().size(), "You can only watch an account key currently"); basicKeyChain = new BasicKeyChain(); this.seed = null; this.rootKey = null; basicKeyChain.importKey(watchingKey); hierarchy = new DeterministicHierarchy(watchingKey); initializeHierarchyUnencrypted(watchingKey); }
@Nullable @Override public KeyCrypter getKeyCrypter() { return basicKeyChain.getKeyCrypter(); }
public long getEarliestKeyCreationTime() { long time = basic.getEarliestKeyCreationTime(); // Long.MAX_VALUE if empty. for (DeterministicKeyChain chain : chains) time = Math.min(time, chain.getEarliestKeyCreationTime()); return time; }