コード例 #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
  /**
   * Mark the DeterministicKey as used. Also correct the issued{Internal|External}Keys counter,
   * because all lower children seem to be requested already. If the counter was updated, we also
   * might trigger lookahead.
   */
  public DeterministicKey markKeyAsUsed(DeterministicKey k) {
    int numChildren = k.getChildNumber().i() + 1;

    if (k.getParent() == internalKey) {
      if (issuedInternalKeys < numChildren) {
        issuedInternalKeys = numChildren;
        maybeLookAhead();
      }
    } else if (k.getParent() == externalKey) {
      if (issuedExternalKeys < numChildren) {
        issuedExternalKeys = numChildren;
        maybeLookAhead();
      }
    }
    return k;
  }
コード例 #3
0
 private void checkForBitFlip(DeterministicKey k) {
   DeterministicKey parent = checkNotNull(k.getParent());
   byte[] rederived =
       HDKeyDerivation.deriveChildKeyBytesFromPublic(
               parent, k.getChildNumber(), HDKeyDerivation.PublicDeriveMode.WITH_INVERSION)
           .keyBytes;
   byte[] actual = k.getPubKey();
   if (!Arrays.equals(rederived, actual))
     throw new IllegalStateException(
         String.format(
             "Bit-flip check failed: %s vs %s",
             Arrays.toString(rederived), Arrays.toString(actual)));
 }
コード例 #4
0
 @Override
 public List<Protos.Key> serializeToProtobuf() {
   lock.lock();
   try {
     // Most of the serialization work is delegated to the basic key chain, which will serialize
     // the bulk of the
     // data (handling encryption along the way), and letting us patch it up with the extra data we
     // care about.
     LinkedList<Protos.Key> entries = newLinkedList();
     if (seed != null) {
       Protos.Key.Builder mnemonicEntry = BasicKeyChain.serializeEncryptableItem(seed);
       mnemonicEntry.setType(Protos.Key.Type.DETERMINISTIC_MNEMONIC);
       entries.add(mnemonicEntry.build());
     }
     Map<ECKey, Protos.Key.Builder> keys = basicKeyChain.serializeToEditableProtobufs();
     for (Map.Entry<ECKey, Protos.Key.Builder> entry : keys.entrySet()) {
       DeterministicKey key = (DeterministicKey) entry.getKey();
       Protos.Key.Builder proto = entry.getValue();
       proto.setType(Protos.Key.Type.DETERMINISTIC_KEY);
       final Protos.DeterministicKey.Builder detKey = proto.getDeterministicKeyBuilder();
       detKey.setChainCode(ByteString.copyFrom(key.getChainCode()));
       for (ChildNumber num : key.getPath()) detKey.addPath(num.i());
       if (key.equals(externalKey)) {
         detKey.setIssuedSubkeys(issuedExternalKeys);
         detKey.setLookaheadSize(lookaheadSize);
       } else if (key.equals(internalKey)) {
         detKey.setIssuedSubkeys(issuedInternalKeys);
         detKey.setLookaheadSize(lookaheadSize);
       }
       // Flag the very first key of following keychain.
       if (entries.isEmpty() && isFollowing()) {
         detKey.setIsFollowing(true);
       }
       if (key.getParent() != null) {
         // HD keys inherit the timestamp of their parent if they have one, so no need to serialize
         // it.
         proto.clearCreationTimestamp();
       }
       entries.add(proto.build());
     }
     return entries;
   } finally {
     lock.unlock();
   }
 }
コード例 #5
0
 // For internal usage only
 /* package */ List<ECKey> getKeys(boolean includeLookahead) {
   List<ECKey> keys = basicKeyChain.getKeys();
   if (!includeLookahead) {
     int treeSize = internalKey.getPath().size();
     List<ECKey> issuedKeys = new LinkedList<ECKey>();
     for (ECKey key : keys) {
       DeterministicKey detkey = (DeterministicKey) key;
       DeterministicKey parent = detkey.getParent();
       if (parent == null) continue;
       if (detkey.getPath().size() <= treeSize) continue;
       if (parent.equals(internalKey) && detkey.getChildNumber().i() > issuedInternalKeys)
         continue;
       if (parent.equals(externalKey) && detkey.getChildNumber().i() > issuedExternalKeys)
         continue;
       issuedKeys.add(detkey);
     }
     return issuedKeys;
   }
   return keys;
 }
コード例 #6
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);
    }
  }