예제 #1
0
 @Override
 public DeterministicKeyChain toDecrypted(KeyParameter aesKey) {
   checkState(getKeyCrypter() != null, "Key chain not encrypted");
   checkState(seed != null, "Can't decrypt a watching chain");
   checkState(seed.isEncrypted());
   String passphrase = DEFAULT_PASSPHRASE_FOR_MNEMONIC; // FIXME allow non-empty passphrase
   DeterministicSeed decSeed = seed.decrypt(getKeyCrypter(), passphrase, aesKey);
   DeterministicKeyChain chain = new DeterministicKeyChain(decSeed);
   // Now double check that the keys match to catch the case where the key is wrong but padding
   // didn't catch it.
   if (!chain.getWatchingKey().getPubKeyPoint().equals(getWatchingKey().getPubKeyPoint()))
     throw new KeyCrypterException("Provided AES key is wrong");
   chain.lookaheadSize = lookaheadSize;
   // Now copy the (pubkey only) leaf keys across to avoid rederiving them. The private key bytes
   // are missing
   // anyway so there's nothing to decrypt.
   for (ECKey eckey : basicKeyChain.getKeys()) {
     DeterministicKey key = (DeterministicKey) eckey;
     if (key.getPath().size() != 3) continue; // Not a leaf key.
     checkState(key.isEncrypted());
     DeterministicKey parent =
         chain.hierarchy.get(checkNotNull(key.getParent()).getPath(), false, false);
     // Clone the key to the new decrypted hierarchy.
     key = new DeterministicKey(key.getPubOnly(), parent);
     chain.hierarchy.putKey(key);
     chain.basicKeyChain.importKey(key);
   }
   chain.issuedExternalKeys = issuedExternalKeys;
   chain.issuedInternalKeys = issuedInternalKeys;
   return chain;
 }
예제 #2
0
  /**
   * Pre-generate enough keys to reach the lookahead size, but only if there are more than the
   * lookaheadThreshold to be generated, so that the Bloom filter does not have to be regenerated
   * that often.
   *
   * <p>The returned mutable list of keys must be inserted into the basic key chain.
   */
  private List<DeterministicKey> maybeLookAhead(
      DeterministicKey parent, int issued, int lookaheadSize, int lookaheadThreshold) {
    checkState(lock.isHeldByCurrentThread());
    final int numChildren = hierarchy.getNumChildren(parent.getPath());
    final int needed = issued + lookaheadSize + lookaheadThreshold - numChildren;

    if (needed <= lookaheadThreshold) return new ArrayList<DeterministicKey>();

    log.info(
        "{} keys needed for {} = {} issued + {} lookahead size + {} lookahead threshold - {} num children",
        needed,
        parent.getPathAsString(),
        issued,
        lookaheadSize,
        lookaheadThreshold,
        numChildren);

    List<DeterministicKey> result = new ArrayList<DeterministicKey>(needed);
    long now = System.currentTimeMillis();
    int nextChild = numChildren;
    for (int i = 0; i < needed; i++) {
      DeterministicKey key = HDKeyDerivation.deriveThisOrNextChildKey(parent, nextChild);
      key = key.getPubOnly();
      hierarchy.putKey(key);
      result.add(key);
      nextChild = key.getChildNumber().num() + 1;
    }
    log.info("Took {} msec", System.currentTimeMillis() - now);
    return result;
  }
예제 #3
0
  // For use in encryption.
  private DeterministicKeyChain(
      KeyCrypter crypter, KeyParameter aesKey, DeterministicKeyChain chain) {
    // Can't encrypt a watching chain.
    checkNotNull(chain.rootKey);
    checkNotNull(chain.seed);

    checkArgument(!chain.rootKey.isEncrypted(), "Chain already encrypted");

    this.issuedExternalKeys = chain.issuedExternalKeys;
    this.issuedInternalKeys = chain.issuedInternalKeys;

    this.lookaheadSize = chain.lookaheadSize;
    this.lookaheadThreshold = chain.lookaheadThreshold;

    this.seed = chain.seed.encrypt(crypter, aesKey);
    basicKeyChain = new BasicKeyChain(crypter);
    // The first number is the "account number" but we don't use that feature.
    rootKey = chain.rootKey.encrypt(crypter, aesKey, null);
    hierarchy = new DeterministicHierarchy(rootKey);
    basicKeyChain.importKey(rootKey);

    DeterministicKey account = encryptNonLeaf(aesKey, chain, rootKey, ACCOUNT_ZERO_PATH);
    externalKey = encryptNonLeaf(aesKey, chain, account, EXTERNAL_PATH);
    internalKey = encryptNonLeaf(aesKey, chain, account, INTERNAL_PATH);

    // Now copy the (pubkey only) leaf keys across to avoid rederiving them. The private key bytes
    // are missing
    // anyway so there's nothing to encrypt.
    for (ECKey eckey : chain.basicKeyChain.getKeys()) {
      DeterministicKey key = (DeterministicKey) eckey;
      if (key.getPath().size() != 3) continue; // Not a leaf key.
      DeterministicKey parent =
          hierarchy.get(checkNotNull(key.getParent()).getPath(), false, false);
      // Clone the key to the new encrypted hierarchy.
      key = new DeterministicKey(key.getPubOnly(), parent);
      hierarchy.putKey(key);
      basicKeyChain.importKey(key);
    }
  }