From 693d54a8835e81179946e49fb2d85387368860fa Mon Sep 17 00:00:00 2001 From: Syed Mohammed Nayyar Date: Tue, 30 Jun 2026 15:29:35 +0530 Subject: [PATCH] use SecureRandom for digest auth cnonce --- .../main/java/org/asynchttpclient/Realm.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/client/src/main/java/org/asynchttpclient/Realm.java b/client/src/main/java/org/asynchttpclient/Realm.java index 768a72f6a..cf770dafe 100644 --- a/client/src/main/java/org/asynchttpclient/Realm.java +++ b/client/src/main/java/org/asynchttpclient/Realm.java @@ -24,9 +24,8 @@ import java.nio.charset.Charset; import java.security.MessageDigest; -import java.util.Arrays; +import java.security.SecureRandom; import java.util.Map; -import java.util.concurrent.ThreadLocalRandom; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.UTF_8; @@ -283,6 +282,9 @@ public enum AuthScheme { */ public static class Builder { + // cnonce must be unpredictable (RFC 7616 section 3.3), like the NTLM and SCRAM nonces + private static final ThreadLocal CNONCE_RANDOM = ThreadLocal.withInitial(SecureRandom::new); + private final @Nullable String principal; private final @Nullable String password; private @Nullable AuthScheme scheme; @@ -608,13 +610,10 @@ public Builder parseProxyAuthenticateHeader(String headerLine) { return null; } - private void newCnonce(MessageDigest md) { + private void newCnonce() { byte[] b = new byte[8]; - ThreadLocalRandom.current().nextBytes(b); - byte[] full = md.digest(b); - // trim to first 8 bytes → 16 hex chars - byte[] small = Arrays.copyOf(full, Math.min(8, full.length)); - cnonce = toHexString(small); + CNONCE_RANDOM.get().nextBytes(b); + cnonce = toHexString(b); } private static byte[] digestFromRecycledStringBuilder(StringBuilder sb, MessageDigest md, Charset enc) { @@ -719,7 +718,7 @@ public Realm build() { // Defensive: if algorithm is null, default to MD5 String algo = (algorithm != null) ? algorithm : "MD5"; MessageDigest md = getDigestInstance(algo); - newCnonce(md); + newCnonce(); newResponse(md); }