3737public class Realm {
3838
3939 private static final String DEFAULT_NC = "00000001" ;
40+ // MD5("")
4041 private static final String EMPTY_ENTITY_MD5 = "d41d8cd98f00b204e9800998ecf8427e" ;
4142
4243 private final String principal ;
@@ -412,26 +413,35 @@ private byte[] md5FromRecycledStringBuilder(StringBuilder sb, MessageDigest md)
412413 return md .digest ();
413414 }
414415
415- private byte [] secretDigest (StringBuilder sb , MessageDigest md ) {
416+ private byte [] ha1 (StringBuilder sb , MessageDigest md ) {
417+ // if algorithm is "MD5" or is unspecified => A1 = username ":" realm-value ":" passwd
418+ // if algorithm is "MD5-sess" => A1 = MD5( username-value ":" realm-value ":" passwd ) ":" nonce-value ":" cnonce-value
416419
417420 sb .append (principal ).append (':' ).append (realmName ).append (':' ).append (password );
418- byte [] ha1 = md5FromRecycledStringBuilder (sb , md );
421+ byte [] core = md5FromRecycledStringBuilder (sb , md );
419422
420423 if (algorithm == null || algorithm .equals ("MD5" )) {
421- return ha1 ;
424+ // A1 = username ":" realm-value ":" passwd
425+ return core ;
422426 } else if ("MD5-sess" .equals (algorithm )) {
423- appendBase16 (sb , ha1 );
427+ // A1 = MD5(username ":" realm-value ":" passwd ) ":" nonce ":" cnonce
428+ appendBase16 (sb , core );
424429 sb .append (':' ).append (nonce ).append (':' ).append (cnonce );
425430 return md5FromRecycledStringBuilder (sb , md );
426431 }
427432
428433 throw new UnsupportedOperationException ("Digest algorithm not supported: " + algorithm );
429434 }
430435
431- private byte [] dataDigest (StringBuilder sb , String digestUri , MessageDigest md ) {
436+ private byte [] ha2 (StringBuilder sb , String digestUri , MessageDigest md ) {
432437
438+ // if qop is "auth" or is unspecified => A2 = Method ":" digest-uri-value
439+ // if qop is "auth-int" => A2 = Method ":" digest-uri-value ":" H(entity-body)
433440 sb .append (methodName ).append (':' ).append (digestUri );
434441 if ("auth-int" .equals (qop )) {
442+ // when qop == "auth-int", A2 = Method ":" digest-uri-value ":" H(entity-body)
443+ // but we don't have the request body here
444+ // we would need a new API
435445 sb .append (':' ).append (EMPTY_ENTITY_MD5 );
436446
437447 } else if (qop != null && !qop .equals ("auth" )) {
@@ -441,7 +451,8 @@ private byte[] dataDigest(StringBuilder sb, String digestUri, MessageDigest md)
441451 return md5FromRecycledStringBuilder (sb , md );
442452 }
443453
444- private void appendDataBase (StringBuilder sb ) {
454+ private void appendMiddlePart (StringBuilder sb ) {
455+ // request-digest = MD5(H(A1) ":" nonce ":" nc ":" cnonce ":" qop ":" H(A2))
445456 sb .append (':' ).append (nonce ).append (':' );
446457 if ("auth" .equals (qop ) || "auth-int" .equals (qop )) {
447458 sb .append (nc ).append (':' ).append (cnonce ).append (':' ).append (qop ).append (':' );
@@ -457,12 +468,12 @@ private void newResponse(MessageDigest md) {
457468 StringBuilder sb = StringBuilderPool .DEFAULT .stringBuilder ();
458469
459470 // WARNING: DON'T MOVE, BUFFER IS RECYCLED!!!!
460- byte [] secretDigest = secretDigest (sb , md );
461- byte [] dataDigest = dataDigest (sb , digestUri , md );
471+ byte [] ha1 = ha1 (sb , md );
472+ byte [] ha2 = ha2 (sb , digestUri , md );
462473
463- appendBase16 (sb , secretDigest );
464- appendDataBase (sb );
465- appendBase16 (sb , dataDigest );
474+ appendBase16 (sb , ha1 );
475+ appendMiddlePart (sb );
476+ appendBase16 (sb , ha2 );
466477
467478 byte [] responseDigest = md5FromRecycledStringBuilder (sb , md );
468479 response = toHexString (responseDigest );
0 commit comments