diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/ScryptKdf.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/ScryptKdf.java index 2b204e9ac..76ad68417 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/ScryptKdf.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/ScryptKdf.java @@ -9,14 +9,16 @@ import java.util.logging.Logger; import javax.inject.Inject; +import static java.lang.Math.min; import static java.util.logging.Level.INFO; +import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.now; class ScryptKdf implements PasswordBasedKdf { private static final Logger LOG = - Logger.getLogger(ScryptKdf.class.getName()); + getLogger(ScryptKdf.class.getName()); private static final int MIN_COST = 256; // Min parameter N private static final int MAX_COST = 1024 * 1024; // Max parameter N @@ -33,10 +35,20 @@ class ScryptKdf implements PasswordBasedKdf { @Override public int chooseCostParameter() { + // Scrypt uses at least 128 * N * r bytes of memory. Don't use more + // than half of the JVM's max heap size or we may run out of memory. + // https://blog.filippo.io/the-scrypt-parameters/ + long maxMemory = Runtime.getRuntime().maxMemory(); + long maxCost = min(MAX_COST, maxMemory / BLOCK_SIZE / 256); + if (LOG.isLoggable(INFO) && maxCost < MAX_COST) { + LOG.info("Max cost capped at " + maxCost + + " due to max heap size " + maxMemory); + } // Increase the cost from min to max while measuring performance int cost = MIN_COST; - while (cost * 2 <= MAX_COST && measureDuration(cost) * 2 <= TARGET_MS) + while (cost * 2 <= maxCost && measureDuration(cost) * 2 <= TARGET_MS) { cost *= 2; + } if (LOG.isLoggable(INFO)) LOG.info("KDF cost parameter " + cost); return cost;