Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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;
Expand All @@ -36,6 +37,7 @@
*
*/
public class DigestAuthSupplier implements HttpAuthSupplier {
private static final SecureRandom CNONCE_GENERATOR = new SecureRandom();

Map<URI, DigestInfo> authInfo = new ConcurrentHashMap<>();

Expand Down Expand Up @@ -107,8 +109,16 @@ private static String getAuthURI(URI currentURI) {
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
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 {
Expand Down Expand Up @@ -92,6 +93,19 @@ public String createCnonce() {
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();
Expand Down
Loading