37
37
public class Realm {
38
38
39
39
private static final String DEFAULT_NC = "00000001" ;
40
+ // MD5("")
40
41
private static final String EMPTY_ENTITY_MD5 = "d41d8cd98f00b204e9800998ecf8427e" ;
41
42
42
43
private final String principal ;
@@ -412,26 +413,35 @@ private byte[] md5FromRecycledStringBuilder(StringBuilder sb, MessageDigest md)
412
413
return md .digest ();
413
414
}
414
415
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
416
419
417
420
sb .append (principal ).append (':' ).append (realmName ).append (':' ).append (password );
418
- byte [] ha1 = md5FromRecycledStringBuilder (sb , md );
421
+ byte [] core = md5FromRecycledStringBuilder (sb , md );
419
422
420
423
if (algorithm == null || algorithm .equals ("MD5" )) {
421
- return ha1 ;
424
+ // A1 = username ":" realm-value ":" passwd
425
+ return core ;
422
426
} else if ("MD5-sess" .equals (algorithm )) {
423
- appendBase16 (sb , ha1 );
427
+ // A1 = MD5(username ":" realm-value ":" passwd ) ":" nonce ":" cnonce
428
+ appendBase16 (sb , core );
424
429
sb .append (':' ).append (nonce ).append (':' ).append (cnonce );
425
430
return md5FromRecycledStringBuilder (sb , md );
426
431
}
427
432
428
433
throw new UnsupportedOperationException ("Digest algorithm not supported: " + algorithm );
429
434
}
430
435
431
- private byte [] dataDigest (StringBuilder sb , String digestUri , MessageDigest md ) {
436
+ private byte [] ha2 (StringBuilder sb , String digestUri , MessageDigest md ) {
432
437
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)
433
440
sb .append (methodName ).append (':' ).append (digestUri );
434
441
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
435
445
sb .append (':' ).append (EMPTY_ENTITY_MD5 );
436
446
437
447
} else if (qop != null && !qop .equals ("auth" )) {
@@ -441,7 +451,8 @@ private byte[] dataDigest(StringBuilder sb, String digestUri, MessageDigest md)
441
451
return md5FromRecycledStringBuilder (sb , md );
442
452
}
443
453
444
- private void appendDataBase (StringBuilder sb ) {
454
+ private void appendMiddlePart (StringBuilder sb ) {
455
+ // request-digest = MD5(H(A1) ":" nonce ":" nc ":" cnonce ":" qop ":" H(A2))
445
456
sb .append (':' ).append (nonce ).append (':' );
446
457
if ("auth" .equals (qop ) || "auth-int" .equals (qop )) {
447
458
sb .append (nc ).append (':' ).append (cnonce ).append (':' ).append (qop ).append (':' );
@@ -457,12 +468,12 @@ private void newResponse(MessageDigest md) {
457
468
StringBuilder sb = StringBuilderPool .DEFAULT .stringBuilder ();
458
469
459
470
// 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 );
462
473
463
- appendBase16 (sb , secretDigest );
464
- appendDataBase (sb );
465
- appendBase16 (sb , dataDigest );
474
+ appendBase16 (sb , ha1 );
475
+ appendMiddlePart (sb );
476
+ appendBase16 (sb , ha2 );
466
477
467
478
byte [] responseDigest = md5FromRecycledStringBuilder (sb , md );
468
479
response = toHexString (responseDigest );
0 commit comments