From f705721a6e05f0dd1ace4efb486a51eedbeb08fb Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Tue, 8 May 2018 02:24:27 +0200 Subject: [PATCH] reuse SecureRandom instances Initializing a new SecureRandom can block while waiting for entropy. Reuse existing instances instead, which will never block for the default provider (NativePRNG). SecureRandom is threadsafe, and no two threads will see the same state. --- modules/user/src/main/PasswordHasher.scala | 4 +-- modules/user/src/main/TotpSecret.scala | 4 ++- .../user/src/main/java/mindrot/BCrypt.java | 29 +++++-------------- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/modules/user/src/main/PasswordHasher.scala b/modules/user/src/main/PasswordHasher.scala index f663aacf28..3152f65681 100644 --- a/modules/user/src/main/PasswordHasher.scala +++ b/modules/user/src/main/PasswordHasher.scala @@ -54,14 +54,14 @@ private final class PasswordHasher( import org.mindrot.BCrypt import User.ClearPassword + private val prng = new SecureRandom() private val aes = new Aes(secret) private def bHash(salt: Array[Byte], p: ClearPassword) = hashTimer(BCrypt.hashpwRaw(p.value.sha512, 'a', logRounds, salt)) def hash(p: ClearPassword): HashedPassword = { val salt = new Array[Byte](16) - new SecureRandom().nextBytes(salt) - + prng.nextBytes(salt) HashedPassword(salt ++ aes.encrypt(Aes.iv(salt), bHash(salt, p))) } diff --git a/modules/user/src/main/TotpSecret.scala b/modules/user/src/main/TotpSecret.scala index f287656159..53f82ce2d4 100644 --- a/modules/user/src/main/TotpSecret.scala +++ b/modules/user/src/main/TotpSecret.scala @@ -45,11 +45,13 @@ object TotpSecret { // number of digits in token private val digits = 6 + private val secureRandom = new SecureRandom() + def apply(base32: String) = new TotpSecret(new Base32().decode(base32)) def random: TotpSecret = { val secret = new Array[Byte](10) - new SecureRandom().nextBytes(secret) + secureRandom.nextBytes(secret) apply(secret) } diff --git a/modules/user/src/main/java/mindrot/BCrypt.java b/modules/user/src/main/java/mindrot/BCrypt.java index 15df804701..29d96c6829 100644 --- a/modules/user/src/main/java/mindrot/BCrypt.java +++ b/modules/user/src/main/java/mindrot/BCrypt.java @@ -66,6 +66,8 @@ import java.util.Arrays; * @version 0.4 */ public final class BCrypt { + private static final SecureRandom PRNG = new SecureRandom(); + // BCrypt parameters private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10; private static final int BCRYPT_SALT_LEN = 16; @@ -724,12 +726,11 @@ public final class BCrypt { * @param log_rounds the log2 of the number of rounds of * hashing to apply - the work factor therefore increases as * 2**log_rounds. - * @param random an instance of SecureRandom to use * @return an encoded salt value */ - public static String gensalt(int log_rounds, SecureRandom random) { + public static String gensalt(int log_rounds) { StringBuilder rs = new StringBuilder(); - byte rnd[] = gensaltRaw(random); + byte rnd[] = gensaltRaw(); rs.append("$" + LATEST_VERSION + "$"); if (log_rounds < 10) @@ -744,26 +745,10 @@ public final class BCrypt { return rs.toString(); } - public static byte[] gensaltRaw(SecureRandom random) { - byte rnd[] = new byte[BCRYPT_SALT_LEN]; - random.nextBytes(rnd); - return rnd; - } - public static byte[] gensaltRaw() { - return gensaltRaw(new SecureRandom()); - } - - - /** - * Generate a salt for use with the BCrypt.hashpw() method - * @param log_rounds the log2 of the number of rounds of - * hashing to apply - the work factor therefore increases as - * 2**log_rounds. - * @return an encoded salt value - */ - public static String gensalt(int log_rounds) { - return gensalt(log_rounds, new SecureRandom()); + byte rnd[] = new byte[BCRYPT_SALT_LEN]; + PRNG.nextBytes(rnd); + return rnd; } /**