/** * 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)); }