예제 #1
0
 @Test
 public void deterministicUpgradeEncrypted() throws Exception {
   group = new KeyChainGroup(params);
   final ECKey key = new ECKey();
   group.importKeys(key);
   final KeyCrypterScrypt crypter = new KeyCrypterScrypt();
   final KeyParameter aesKey = crypter.deriveKey("abc");
   assertTrue(group.isDeterministicUpgradeRequired());
   group.encrypt(crypter, aesKey);
   assertTrue(group.isDeterministicUpgradeRequired());
   try {
     group.upgradeToDeterministic(0, null);
     fail();
   } catch (DeterministicUpgradeRequiresPassword e) {
     // Expected.
   }
   group.upgradeToDeterministic(0, aesKey);
   assertFalse(group.isDeterministicUpgradeRequired());
   final DeterministicSeed deterministicSeed = group.getActiveKeyChain().getSeed();
   assertNotNull(deterministicSeed);
   assertTrue(deterministicSeed.isEncrypted());
   byte[] entropy =
       checkNotNull(group.getActiveKeyChain().toDecrypted(aesKey).getSeed()).getEntropyBytes();
   // Check we used the right key: oldest non rotating.
   byte[] truncatedBytes = Arrays.copyOfRange(key.getSecretBytes(), 0, 16);
   assertArrayEquals(entropy, truncatedBytes);
 }
예제 #2
0
 public static ECKey getEncryptedECKey(String decrypted, String password) {
   try {
     ECKey key = new DumpedPrivateKey(MainNetParams.get(), decrypted).getKey();
     KeyCrypterScrypt crypter = new KeyCrypterScrypt();
     return key.encrypt(crypter, crypter.deriveKey(password));
   } catch (Exception e) {
     return null;
   }
 }
예제 #3
0
 public static String getPrivateKeyString(EncryptedPrivateKey key, KeyCrypter crypter) {
   String salt = "1";
   if (crypter instanceof KeyCrypterScrypt) {
     KeyCrypterScrypt scrypt = (KeyCrypterScrypt) crypter;
     salt = Utils.bytesToHexString(scrypt.getScryptParameters().getSalt().toByteArray());
   }
   return Utils.bytesToHexString(key.getEncryptedBytes())
       + StringUtil.QR_CODE_SPLIT
       + Utils.bytesToHexString(key.getInitialisationVector())
       + StringUtil.QR_CODE_SPLIT
       + salt;
 }
예제 #4
0
 @Test
 public void encryptionWhilstEmpty() throws Exception {
   group = new KeyChainGroup(params);
   group.setLookaheadSize(5);
   KeyCrypterScrypt scrypt = new KeyCrypterScrypt(2);
   final KeyParameter aesKey = scrypt.deriveKey("password");
   group.encrypt(scrypt, aesKey);
   assertTrue(group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS).isEncrypted());
   final ECKey key = group.currentKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
   group.decrypt(aesKey);
   assertFalse(checkNotNull(group.findKeyFromPubKey(key.getPubKey())).isEncrypted());
 }
예제 #5
0
  @Test
  public void serialization() throws Exception {
    assertEquals(INITIAL_KEYS + 1 /* for the seed */, group.serializeToProtobuf().size());
    group = KeyChainGroup.fromProtobufUnencrypted(params, group.serializeToProtobuf());
    group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
    DeterministicKey key1 = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
    DeterministicKey key2 = group.freshKey(KeyChain.KeyPurpose.CHANGE);
    group.getBloomFilterElementCount();
    List<Protos.Key> protoKeys1 = group.serializeToProtobuf();
    assertEquals(
        INITIAL_KEYS + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 1, protoKeys1.size());
    group.importKeys(new ECKey());
    List<Protos.Key> protoKeys2 = group.serializeToProtobuf();
    assertEquals(
        INITIAL_KEYS + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 2, protoKeys2.size());

    group = KeyChainGroup.fromProtobufUnencrypted(params, protoKeys1);
    assertEquals(
        INITIAL_KEYS + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 1, protoKeys1.size());
    assertTrue(group.hasKey(key1));
    assertTrue(group.hasKey(key2));
    assertEquals(key2, group.currentKey(KeyChain.KeyPurpose.CHANGE));
    assertEquals(key1, group.currentKey(KeyChain.KeyPurpose.RECEIVE_FUNDS));
    group = KeyChainGroup.fromProtobufUnencrypted(params, protoKeys2);
    assertEquals(
        INITIAL_KEYS + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 2, protoKeys2.size());
    assertTrue(group.hasKey(key1));
    assertTrue(group.hasKey(key2));

    KeyCrypterScrypt scrypt = new KeyCrypterScrypt(2);
    final KeyParameter aesKey = scrypt.deriveKey("password");
    group.encrypt(scrypt, aesKey);
    List<Protos.Key> protoKeys3 = group.serializeToProtobuf();
    group = KeyChainGroup.fromProtobufEncrypted(params, protoKeys3, scrypt);
    assertTrue(group.isEncrypted());
    assertTrue(group.checkPassword("password"));
    group.decrypt(aesKey);

    // No need for extensive contents testing here, as that's done in the keychain class tests.
  }
예제 #6
0
 public static ECKey getECKeyFromSingleString(String str, String password) {
   String[] strs = str.split(StringUtil.QR_CODE_SPLIT);
   if (strs.length != 3) {
     Log.e("Backup", "PrivateKeyFromString format error");
     return null;
   }
   EncryptedPrivateKey epk =
       new EncryptedPrivateKey(
           StringUtil.hexStringToByteArray(strs[1]), StringUtil.hexStringToByteArray(strs[0]));
   byte[] salt = StringUtil.hexStringToByteArray(strs[2]);
   KeyCrypterScrypt crypter =
       new KeyCrypterScrypt(
           ScryptParameters.newBuilder().setSalt(ByteString.copyFrom(salt)).build());
   try {
     byte[] pub =
         ECKey.publicKeyFromPrivate(
             new BigInteger(1, crypter.decrypt(epk, crypter.deriveKey(password))), true);
     return new ECKey(epk, pub, crypter);
   } catch (Exception e) {
     e.printStackTrace();
     return null;
   }
 }
  /**
   * Converts the given wallet to the object representation of the protocol buffers. This can be
   * modified, or additional data fields set, before serialization takes place.
   */
  public Protos.Wallet walletToProto(Wallet wallet) {
    Protos.Wallet.Builder walletBuilder = Protos.Wallet.newBuilder();
    walletBuilder.setNetworkIdentifier(wallet.getNetworkParameters().getId());
    if (wallet.getDescription() != null) {
      walletBuilder.setDescription(wallet.getDescription());
    }

    for (WalletTransaction wtx : wallet.getWalletTransactions()) {
      Protos.Transaction txProto = makeTxProto(wtx);
      walletBuilder.addTransaction(txProto);
    }

    for (ECKey key : wallet.getKeys()) {
      Protos.Key.Builder keyBuilder =
          Protos.Key.newBuilder()
              .setCreationTimestamp(key.getCreationTimeSeconds() * 1000)
              // .setLabel() TODO
              .setType(Protos.Key.Type.ORIGINAL);
      if (key.getPrivKeyBytes() != null)
        keyBuilder.setPrivateKey(ByteString.copyFrom(key.getPrivKeyBytes()));

      EncryptedPrivateKey encryptedPrivateKey = key.getEncryptedPrivateKey();
      if (encryptedPrivateKey != null) {
        // Key is encrypted.
        Protos.EncryptedPrivateKey.Builder encryptedKeyBuilder =
            Protos.EncryptedPrivateKey.newBuilder()
                .setEncryptedPrivateKey(
                    ByteString.copyFrom(encryptedPrivateKey.getEncryptedBytes()))
                .setInitialisationVector(
                    ByteString.copyFrom(encryptedPrivateKey.getInitialisationVector()));

        if (key.getKeyCrypter() == null) {
          throw new IllegalStateException(
              "The encrypted key " + key.toString() + " has no KeyCrypter.");
        } else {
          // If it is a Scrypt + AES encrypted key, set the persisted key type.
          if (key.getKeyCrypter().getUnderstoodEncryptionType()
              == Protos.Wallet.EncryptionType.ENCRYPTED_SCRYPT_AES) {
            keyBuilder.setType(Protos.Key.Type.ENCRYPTED_SCRYPT_AES);
          } else {
            throw new IllegalArgumentException(
                "The key "
                    + key.toString()
                    + " is encrypted with a KeyCrypter of type "
                    + key.getKeyCrypter().getUnderstoodEncryptionType()
                    + ". This WalletProtobufSerialiser does not understand that type of encryption.");
          }
        }
        keyBuilder.setEncryptedPrivateKey(encryptedKeyBuilder);
      }

      // We serialize the public key even if the private key is present for speed reasons: we don't
      // want to do
      // lots of slow EC math to load the wallet, we prefer to store the redundant data instead. It
      // matters more
      // on mobile platforms.
      keyBuilder.setPublicKey(ByteString.copyFrom(key.getPubKey()));
      walletBuilder.addKey(keyBuilder);
    }

    // Populate the lastSeenBlockHash field.
    Sha256Hash lastSeenBlockHash = wallet.getLastBlockSeenHash();
    if (lastSeenBlockHash != null) {
      walletBuilder.setLastSeenBlockHash(hashToByteString(lastSeenBlockHash));
      walletBuilder.setLastSeenBlockHeight(wallet.getLastBlockSeenHeight());
    }

    // Populate the scrypt parameters.
    KeyCrypter keyCrypter = wallet.getKeyCrypter();
    if (keyCrypter == null) {
      // The wallet is unencrypted.
      walletBuilder.setEncryptionType(EncryptionType.UNENCRYPTED);
    } else {
      // The wallet is encrypted.
      walletBuilder.setEncryptionType(keyCrypter.getUnderstoodEncryptionType());
      if (keyCrypter instanceof KeyCrypterScrypt) {
        KeyCrypterScrypt keyCrypterScrypt = (KeyCrypterScrypt) keyCrypter;
        walletBuilder.setEncryptionParameters(keyCrypterScrypt.getScryptParameters());
      } else {
        // Some other form of encryption has been specified that we do not know how to persist.
        throw new RuntimeException(
            "The wallet has encryption of type '"
                + keyCrypter.getUnderstoodEncryptionType()
                + "' but this WalletProtobufSerializer does not know how to persist this.");
      }
    }

    populateExtensions(wallet, walletBuilder);

    // Populate the wallet version.
    walletBuilder.setVersion(wallet.getVersion());

    return walletBuilder.build();
  }
예제 #8
0
  public void encryption(boolean withImported) throws Exception {
    Utils.rollMockClock(0);
    long now = Utils.currentTimeSeconds();
    ECKey a = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
    assertEquals(now, group.getEarliestKeyCreationTime());
    Utils.rollMockClock(-86400);
    long yesterday = Utils.currentTimeSeconds();
    ECKey b = new ECKey();

    assertFalse(group.isEncrypted());
    try {
      group.checkPassword("foo"); // Cannot check password of an unencrypted group.
      fail();
    } catch (IllegalStateException e) {
    }
    if (withImported) {
      assertEquals(now, group.getEarliestKeyCreationTime());
      group.importKeys(b);
      assertEquals(yesterday, group.getEarliestKeyCreationTime());
    }
    KeyCrypterScrypt scrypt = new KeyCrypterScrypt(2);
    final KeyParameter aesKey = scrypt.deriveKey("password");
    group.encrypt(scrypt, aesKey);
    assertTrue(group.isEncrypted());
    assertTrue(group.checkPassword("password"));
    assertFalse(group.checkPassword("wrong password"));
    final ECKey ea = group.findKeyFromPubKey(a.getPubKey());
    assertTrue(checkNotNull(ea).isEncrypted());
    if (withImported) {
      assertTrue(checkNotNull(group.findKeyFromPubKey(b.getPubKey())).isEncrypted());
      assertEquals(yesterday, group.getEarliestKeyCreationTime());
    } else {
      assertEquals(now, group.getEarliestKeyCreationTime());
    }
    try {
      ea.sign(Sha256Hash.ZERO_HASH);
      fail();
    } catch (ECKey.KeyIsEncryptedException e) {
      // Ignored.
    }
    if (withImported) {
      ECKey c = new ECKey();
      try {
        group.importKeys(c);
        fail();
      } catch (KeyCrypterException e) {
      }
      group.importKeysAndEncrypt(ImmutableList.of(c), aesKey);
      ECKey ec = group.findKeyFromPubKey(c.getPubKey());
      try {
        group.importKeysAndEncrypt(ImmutableList.of(ec), aesKey);
        fail();
      } catch (IllegalArgumentException e) {
      }
    }

    try {
      group.decrypt(scrypt.deriveKey("WRONG PASSWORD"));
      fail();
    } catch (KeyCrypterException e) {
    }

    group.decrypt(aesKey);
    assertFalse(group.isEncrypted());
    assertFalse(checkNotNull(group.findKeyFromPubKey(a.getPubKey())).isEncrypted());
    if (withImported) {
      assertFalse(checkNotNull(group.findKeyFromPubKey(b.getPubKey())).isEncrypted());
      assertEquals(yesterday, group.getEarliestKeyCreationTime());
    } else {
      assertEquals(now, group.getEarliestKeyCreationTime());
    }
  }