@Override public void onClick(View v) { StrictMode.noteSlowCall("fireSlowCall"); } });
@TargetApi(Build.VERSION_CODES.HONEYCOMB) private void fireSlowCall() { StrictMode.noteSlowCall("fireSlowCall"); }
/** * Computes the PBKDF2 hash of a password. * * @param password the password to hash. * @param salt the salt * @param iterations the iteration count (slowness factor) * @param outBytes the length of the hash to compute in bytes * @return the PBDKF2 hash of the password */ private static byte[] pbkdf2(Provider provider, char[] password, byte[] salt, int iterations, int outBytes) throws NoSuchAlgorithmException, InvalidKeySpecException { StrictMode.noteSlowCall("pbkdf2 is a very expensive call and should not be done on the main thread"); PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, outBytes * 8); SecretKeyFactory skf = provider != null ? SecretKeyFactory.getInstance(PBKDF2_ALGORITHM, provider) : SecretKeyFactory.getInstance(PBKDF2_ALGORITHM); return skf.generateSecret(spec).getEncoded(); } }
@Override public boolean isValidPassword() { StrictMode.noteSlowCall("checking password should only be done in a background thread"); if (!supportVerifyPassword) { throw new UnsupportedOperationException("support verify password is not enabled"); } try { String storedValue = getString(PASSWORD_VALIDATION_KEY, null); return storedValue != null && Bytes.parseBase64(storedValue).equalsConstantTime(preferencesSalt); } catch (SecureSharedPreferenceCryptoException e) { return false; } }
@SuppressLint("ApplySharedPref") @Override public void changePassword(@Nullable char[] newPassword, @Nullable KeyStretchingFunction newKsFunction) { StrictMode.noteSlowCall("changing password should only be done in a background thread"); newPassword = newPassword == null || newPassword.length == 0 ? null : newPassword; SharedPreferences.Editor editor = this.edit(); KeyStretchingFunction currentFunction = encryptionProtocol.getKeyStretchingFunction(); for (String keyHash : getAll().keySet()) { encryptionProtocol.setKeyStretchingFunction(currentFunction); if (!reencryptStringType(newPassword, (Editor) editor, keyHash, newKsFunction)) { reencryptStringSetType(newPassword, (Editor) editor, keyHash, newKsFunction); } } editor.commit(); if (newKsFunction != null) { encryptionProtocol.setKeyStretchingFunction(newKsFunction); } if (password != null) { password.wipe(); } password = encryptionProtocol.obfuscatePassword(newPassword); }
/** * Computes the Bcrypt hash of a password. * * @param password the password to hash. * @param salt the salt * @param logRounds log2(Iterations). e.g. 12 ==> 2^12 = 4,096 iterations * @return the Bcrypt hash of the password */ private static byte[] bcrypt(char[] password, byte[] salt, int logRounds) { StrictMode.noteSlowCall("bcrypt is a very expensive call and should not be done on the main thread"); return BCrypt.with(CUSTOM_LEGACY_VERSION, new SecureRandom(), rawPassword -> Bytes.wrapNullSafe(rawPassword).copy().array()).hash(logRounds, createLegacySalt(salt), createLegacyPassword(password, salt)); }
/** * Computes the Bcrypt hash of a password. * * @param password the password to hash. * @param salt the salt * @param logRounds log2(Iterations). e.g. 12 ==> 2^12 = 4,096 iterations * @return the Bcrypt hash of the password */ private static byte[] bcrypt(byte[] salt, char[] password, int logRounds) { StrictMode.noteSlowCall("bcrypt is a very expensive call and should not be done on the main thread"); Bytes passwordBytes = Bytes.empty(); try { passwordBytes = Bytes.from(password); return BCrypt.with(BCrypt.Version.VERSION_2A).hashRaw(logRounds, HKDF.fromHmacSha256().expand(salt, "bcrypt-salt".getBytes(), 16), HKDF.fromHmacSha256().expand(passwordBytes.array(), "bcrypt-pw".getBytes(), 71)).rawHash; } finally { passwordBytes.mutable().secureWipe(); } } }
/** * Computes the Bcrypt hash of a password. * * @param password the password to hash. * @param salt the salt * @param logRounds log2(Iterations). e.g. 12 ==> 2^12 = 4,096 iterations * @return the Bcrypt hash of the password */ private static byte[] bcrypt(char[] password, byte[] salt, int logRounds) { StrictMode.noteSlowCall("bcrypt is a very expensive call and should not be done on the main thread"); return Bytes.from(BCrypt.hashpw(String.valueOf(password) + Bytes.wrap(salt).encodeHex(), generateSalt(salt, logRounds))).array(); }