/**
  * Encrypt database with new password
  *
  * @param oldPassword the old password
  * @param newPassword the new password
  * @param encrypt
  * @return re-encrypted database
  */
 boolean changeMasterPassword(String oldPassword, String newPassword, boolean encrypt) {
   if (!setMasterPassword(oldPassword)) {
     return false;
   }
   byte[] oldKey = key.get();
   byte[] newKey = EncryptionUtil.genPasswordKey(newPassword);
   ByteArrayWrapper testKey =
       new ByteArrayWrapper(
           EncryptionUtil.dbKey(oldKey, MasterKeyPasswordSafe.class, testKey(oldPassword)));
   HashMap<ByteArrayWrapper, byte[]> oldDb = new HashMap<ByteArrayWrapper, byte[]>();
   database.copyTo(oldDb);
   HashMap<ByteArrayWrapper, byte[]> newDb = new HashMap<ByteArrayWrapper, byte[]>();
   for (Map.Entry<ByteArrayWrapper, byte[]> e : oldDb.entrySet()) {
     if (testKey.equals(e.getKey())) {
       continue;
     }
     byte[] decryptedKey = EncryptionUtil.decryptKey(oldKey, e.getKey().unwrap());
     String decryptedText = EncryptionUtil.decryptText(oldKey, e.getValue());
     newDb.put(
         new ByteArrayWrapper(EncryptionUtil.encryptKey(newKey, decryptedKey)),
         EncryptionUtil.encryptText(newKey, decryptedText));
   }
   synchronized (database.getDbLock()) {
     resetMasterPassword(newPassword, encrypt);
     database.putAll(newDb);
   }
   return true;
 }
 /**
  * Reset password for the password safe (clears password database). The method is used from
  * plugin's UI.
  *
  * @param password the password to set
  * @param encrypt if the password should be encrypted an stored is master database
  */
 void resetMasterPassword(String password, boolean encrypt) {
   this.key.set(EncryptionUtil.genPasswordKey(password));
   database.clear();
   try {
     storePassword(null, MasterKeyPasswordSafe.class, testKey(password), TEST_PASSWORD_VALUE);
     if (encrypt) {
       database.setPasswordInfo(encryptPassword(password));
     } else {
       database.setPasswordInfo(new byte[0]);
     }
   } catch (PasswordSafeException e) {
     throw new IllegalStateException("There should be no problem with password at this point", e);
   }
 }
 /**
  * Set password to use (used from plugin's UI)
  *
  * @param password the password
  * @return true, if password is a correct one
  */
 boolean setMasterPassword(String password) {
   byte[] savedKey = this.key.get();
   this.key.set(EncryptionUtil.genPasswordKey(password));
   String rc;
   try {
     rc = getPassword(null, MasterKeyPasswordSafe.class, testKey(password));
   } catch (PasswordSafeException e) {
     throw new IllegalStateException("There should be no problem with password at this point", e);
   }
   if (!TEST_PASSWORD_VALUE.equals(rc)) {
     this.key.set(savedKey);
     return false;
   } else {
     return true;
   }
 }
 /**
  * Encrypt master password
  *
  * @param pw the password to encrypt
  * @return the encrypted password
  * @throws MasterPasswordUnavailableException if encryption fails
  */
 private static byte[] encryptPassword(String pw) throws MasterPasswordUnavailableException {
   assert SystemInfo.isWindows;
   return WindowsCryptUtils.protect(EncryptionUtil.getUTF8Bytes(pw));
 }