This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/main by this push:
new b0196449b35 Use a properly random source to generate digest client
nonces (#3423)
b0196449b35 is described below
commit b0196449b3561b29924b219ed331a8e85f237f73
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Tue Sep 1 08:27:49 2026 +0100
Use a properly random source to generate digest client nonces (#3423)
---
.../apache/cxf/transport/http/auth/DigestAuthSupplier.java | 12 +++++++++++-
.../cxf/transport/http/auth/DigestAuthSupplierTest.java | 14 ++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git
a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/DigestAuthSupplier.java
b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/DigestAuthSupplier.java
index b076ae3fd7b..6ab3931f90d 100644
---
a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/DigestAuthSupplier.java
+++
b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/DigestAuthSupplier.java
@@ -22,6 +22,7 @@ package org.apache.cxf.transport.http.auth;
import java.net.URI;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
+import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -36,6 +37,7 @@ import static java.nio.charset.StandardCharsets.US_ASCII;
*
*/
public class DigestAuthSupplier implements HttpAuthSupplier {
+ private static final SecureRandom CNONCE_GENERATOR = new SecureRandom();
Map<URI, DigestInfo> authInfo = new ConcurrentHashMap<>();
@@ -107,8 +109,16 @@ public class DigestAuthSupplier implements
HttpAuthSupplier {
return authURI;
}
+ /**
+ * Creates the client nonce. RFC 7616 relies on the cnonce being
unpredictable so
+ * that a hostile or spoofed server controlling the challenge nonce cannot
steer
+ * the client into computing a digest over fully attacker-chosen input; a
+ * timestamp is guessable and must not be used here.
+ */
public String createCnonce() {
- return Long.toString(System.currentTimeMillis());
+ byte[] bytes = new byte[16];
+ CNONCE_GENERATOR.nextBytes(bytes);
+ return StringUtils.toHexString(bytes);
}
class DigestInfo {
diff --git
a/rt/transports/http/src/test/java/org/apache/cxf/transport/http/auth/DigestAuthSupplierTest.java
b/rt/transports/http/src/test/java/org/apache/cxf/transport/http/auth/DigestAuthSupplierTest.java
index 127b88b8856..81e20e4c878 100644
---
a/rt/transports/http/src/test/java/org/apache/cxf/transport/http/auth/DigestAuthSupplierTest.java
+++
b/rt/transports/http/src/test/java/org/apache/cxf/transport/http/auth/DigestAuthSupplierTest.java
@@ -29,6 +29,7 @@ import org.apache.cxf.message.MessageImpl;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
public class DigestAuthSupplierTest {
@@ -92,6 +93,19 @@ public class DigestAuthSupplierTest {
assertEquals(expectedParams, params);
}
+ @Test
+ public void testCnonceIsUnpredictable() throws Exception {
+ DigestAuthSupplier authSupplier = new DigestAuthSupplier();
+ String cnonce1 = authSupplier.createCnonce();
+ String cnonce2 = authSupplier.createCnonce();
+ // 16 random bytes, hex encoded
+ assertEquals(32, cnonce1.length());
+ assertTrue(cnonce1.matches("[0-9a-fA-F]+"));
+ assertNotEquals(cnonce1, cnonce2);
+ // must not be an epoch-millis timestamp
+ assertNotEquals(Long.toString(System.currentTimeMillis()).length(),
cnonce1.length());
+ }
+
@Test
public void testUrlEncodedUri() throws Exception {
AuthorizationPolicy authPolicy = new AuthorizationPolicy();