public final class DigestChallengeResponse
extends java.lang.Object
Authorization header.
 
 Instances of this class is normally created as a response to an incoming challenge using
 responseTo(DigestChallenge). To generate the Authorization header, som
 additional values must be set:
 
username and password for
 authentication.digest-uri used in the HTTP request.request method of the request, such as "GET" or "POST".
 Here is an example of how to create a response:
 
 DigestChallengeResponse response = DigestChallengeResponse.responseTo(challenge)
                                                           .username("user")
                                                           .password("passwd")
                                                           .digestUri("/example")
                                                           .requestMethod("GET");
 
 
 
 Each time the challenge response is reused the nonce count must be increased by one, see
 incrementNonceCount(). It is also a good idea to generate a new random client nonce with
 randomizeClientNonce():
 
 
 response.incrementNonceCount().randomizeClientNonce(); // Response is now ready for reuse
 
 
 auth-int quality of protection (optional, rarely used)auth-int quality of protection the challenge response includes a hash of the
 request's entity-body, which provides some protection from man-in-the-middle attacks.
 Not all requests include an entity-body, PUT and POST do but GET does not. To support
 auth-int, you must set either the digest of the entity-body (using
 entityBodyDigest(byte[])) or the entity-body itself (using
 entityBody(byte[])).
 java.security.SecureRandom, which should be suitable for most purposes.
 
 If you still for some reason need to override the default client nonce you can set it using
 clientNonce(String). You may also have to call firstRequestClientNonce(String),
 see the documentation of that method for details.
 
| Modifier and Type | Field and Description | 
|---|---|
static java.lang.String | 
HTTP_HEADER_AUTHORIZATION
The name of the HTTP request header ("Authorization"). 
 | 
| Constructor and Description | 
|---|
DigestChallengeResponse()
Creates an empty challenge response. 
 | 
| Modifier and Type | Method and Description | 
|---|---|
DigestChallengeResponse | 
algorithm(java.lang.String algorithm)
Sets the  
algorithm directive, which must be the same as the algorithm directive
 of the challenge. | 
DigestChallengeResponse | 
challenge(DigestChallenge challenge)
Sets the values of the  
realm, nonce, opaque, and algorithm
 directives and the supported quality of protection types based on a challenge. | 
DigestChallengeResponse | 
clientNonce(java.lang.String clientNonce)
Sets the  
cnonce directive, which is a random string generated by the client that will
 be included in the challenge response hash. | 
DigestChallengeResponse | 
digestUri(java.lang.String digestUri)
Sets the  
digest-uri directive, which must be exactly the same as the
 Request-URI of the Request-Line of the HTTP request. | 
DigestChallengeResponse | 
entityBody(byte[] entityBody)
Sets the  
entity-body of the request, which is only used for the "auth-int" quality of
 protection. | 
DigestChallengeResponse | 
entityBodyDigest(byte[] entityBodyDigest)
Sets the digest of the  
entity-body of the request, which is only used for the
 "auth-int" quality of protection. | 
DigestChallengeResponse | 
firstRequestClientNonce(java.lang.String firstRequestClientNonce)
Sets the value of client nonce used in the first request. 
 | 
java.lang.String | 
getAlgorithm()
Returns the value of the  
algorithm directive. | 
java.lang.String | 
getClientNonce()
Returns the value of the  
cnonce directive. | 
java.lang.String | 
getDigestUri()
Returns the value of the  
digest-uri directive. | 
byte[] | 
getEntityBodyDigest()
Returns the digest of the  
entity-body. | 
java.lang.String | 
getFirstRequestClientNonce()
Returns the value of client nonce used in the first request. 
 | 
java.lang.String | 
getHeaderValue()
Returns the  
credentials, that is, the string to set in the Authorization
 HTTP request header. | 
java.lang.String | 
getNonce()
Returns the unquoted value of the  
nonce directive | 
int | 
getNonceCount()
Returns the integer representation of the  
nonce-count directive. | 
java.lang.String | 
getOpaque()
Returns the the unquoted value of the  
opaque directive, or null. | 
java.lang.String | 
getPassword()
Returns the password to use for authentication. 
 | 
DigestChallenge.QualityOfProtection | 
getQop()
Returns the "quality of protection" that will be used for the response. 
 | 
java.lang.String | 
getQuotedNonce()
Returns the quoted value of the  
nonce directive. | 
java.lang.String | 
getQuotedOpaque()
Returns the the quoted value of the  
opaque directive, or null. | 
java.lang.String | 
getQuotedRealm()
Returns the quoted value of the  
realm directive. | 
java.lang.String | 
getRealm()
Returns the unquoted value of the  
realm directive. | 
java.lang.String | 
getRequestMethod()
Returns the HTTP method of the request. 
 | 
java.util.Set<DigestChallenge.QualityOfProtection> | 
getSupportedQopTypes()
Returns the type of "quality of protection" that can be used when responding to the request. 
 | 
java.lang.String | 
getUsername()
Returns the username to use for authentication. 
 | 
DigestChallengeResponse | 
incrementNonceCount()
Increments the value of the  
nonce-count by one. | 
static boolean | 
isAlgorithmSupported(java.lang.String algorithm)
Returns  
true if a given digest algorithm is supported. | 
static boolean | 
isChallengeSupported(DigestChallenge challenge)
Returns  
true if a given challenge is supported and a response to it can be generated
 (given that all other required values are supplied). | 
boolean | 
isEntityBodyDigestRequired()
Returns  
true if the digest of the entity-body is required to generate an
 authorization header for this response. | 
DigestChallengeResponse | 
nonce(java.lang.String unquotedNonce)
Sets the  
nonce directive, which must be the same as the nonce directive of the
 challenge. | 
DigestChallengeResponse | 
nonceCount(int nonceCount)
Sets the integer representation of the  
nonce-count directive, which indicates how many
 times this a challenge response with this nonce has been used. | 
DigestChallengeResponse | 
opaque(java.lang.String unquotedOpaque)
Sets the  
opaque directive, which must be the same as the opaque directive of
 the challenge. | 
DigestChallengeResponse | 
password(java.lang.String password)
Sets the password to use for authentication. 
 | 
DigestChallengeResponse | 
quotedNonce(java.lang.String quotedNonce)
Sets the  
nonce directive, which must be the same as the nonce directive of the
 challenge. | 
DigestChallengeResponse | 
quotedOpaque(java.lang.String quotedOpaque)
Sets the  
opaque directive, which must be the same as the opaque directive of
 the challenge. | 
DigestChallengeResponse | 
quotedRealm(java.lang.String quotedRealm)
Sets the  
realm directive, which must be the same as the realm directive of
 the challenge. | 
DigestChallengeResponse | 
randomizeClientNonce()
Sets the  
cnonce directive to a random value. | 
DigestChallengeResponse | 
realm(java.lang.String unquotedRealm)
Sets the  
realm directive, which must be the same as the realm directive of
 the challenge. | 
DigestChallengeResponse | 
requestMethod(java.lang.String requestMethod)
Sets the HTTP method of the request (GET, POST, etc). 
 | 
DigestChallengeResponse | 
resetNonceCount()
Sets the value of the  
nonce-count to one. | 
static DigestChallengeResponse | 
responseTo(DigestChallenge challenge)
Creates a digest challenge response, setting the values of the  
realm, nonce,
 opaque, and algorithm directives and the supported quality of protection
 types based on a challenge. | 
DigestChallengeResponse | 
supportedQopTypes(java.util.Set<DigestChallenge.QualityOfProtection> supportedQopTypes)
Sets the type of "quality of protection" that can be used when responding to the request. 
 | 
java.lang.String | 
toString()  | 
DigestChallengeResponse | 
username(java.lang.String username)
Sets the username to use for authentication. 
 | 
public static final java.lang.String HTTP_HEADER_AUTHORIZATION
public DigestChallengeResponse()
 Consider using responseTo(DigestChallenge) when creating a response to a specific
 challenge.
public static boolean isChallengeSupported(DigestChallenge challenge)
true if a given challenge is supported and a response to it can be generated
 (given that all other required values are supplied).
 For a challenge to be supported, the following requirements must be met:
isAlgorithmSupported(String)).supportedQopTypes(Set).challenge - the challengetrue if the challenge is supportedpublic static DigestChallengeResponse responseTo(DigestChallenge challenge)
realm, nonce,
 opaque, and algorithm directives and the supported quality of protection
 types based on a challenge.
 
 If the challenge is not supported an exception is thrown. Use
 isChallengeSupported(DigestChallenge) to check if a challenge is supported before
 calling this method.
challenge - the challengejava.lang.IllegalArgumentException - if the challenge is not supportedisChallengeSupported(DigestChallenge)public static boolean isAlgorithmSupported(java.lang.String algorithm)
true if a given digest algorithm is supported.
 
 Supported values are "MD5", "MD5-sess", "SHA-256", "SHA-256-sess", and null. null indicates that the digest is generated using MD5, but no algorithm directive is
 included in the response.
algorithm - the algorithmtrue if the algorithm is supportedpublic DigestChallengeResponse algorithm(java.lang.String algorithm)
algorithm directive, which must be the same as the algorithm directive
 of the challenge.
 
 Use isAlgorithmSupported(String) to check if a particular algorithm is supported.
 
 Note: Setting the algorithm will also reset the entity-body to a byte array of
 zero length, see entityBody(byte[]). This is because the entity-body is
 not stored, only the digest is. If you need to set both entity-body and
 algorithm, make sure to set algorithm first.
algorithm - the value of the algorithm directive or null to not include an
                  algorithm in the responsejava.lang.IllegalArgumentException - if the algorithm is not supportedgetAlgorithm(), 
isAlgorithmSupported(String), 
Section 3.2.2 of RFC 2617public java.lang.String getAlgorithm()
algorithm directive.algorithm directive or null if algorithm is
 not setalgorithm(String)public DigestChallengeResponse username(java.lang.String username)
username - the usernamegetUsername(), 
Section 3.2.2 of RFC 2617public java.lang.String getUsername()
username(String)public DigestChallengeResponse password(java.lang.String password)
password - the passwordgetPassword()public java.lang.String getPassword()
password(String)public DigestChallengeResponse clientNonce(java.lang.String clientNonce)
cnonce directive, which is a random string generated by the client that will
 be included in the challenge response hash.
 
 There is normally no need to manually set the client nonce since it will have a default
 value of a randomly generated string. If you do, make sure to call
 firstRequestClientNonce(String) if you modify the client nonce for the first request,
 or some session variants of algorithms (those ending in -sess) may not work.
clientNonce - The unquoted value of the cnonce directive.getClientNonce(), 
randomizeClientNonce(), 
Section 3.2.2 of RFC 2617public java.lang.String getClientNonce()
cnonce directive.
 
 Unless overridden by calling clientNonce(String), the cnonce directive is
 set to a randomly generated string.
cnonce directiveclientNonce(String)public DigestChallengeResponse randomizeClientNonce()
cnonce directive to a random value.clientNonce(String), 
getClientNonce()public DigestChallengeResponse firstRequestClientNonce(java.lang.String firstRequestClientNonce)
 This value is used in session based algorithms (those ending in -sess). If the
 challenge is reused for multiple request, the original client nonce used when responding to
 the original challenge is used in subsequent challenge responses, even if the client changes
 the client nonce for subsequent requests.
 
Normally, there is no need to call this method. The default value of the client nonce is a randomly generated string, and the default value of the first request client nonce is the same string. It is only if you override the default value and supply your own client nonce for the first request that you must make sure to call this method with the same value:
 response.clientNonce("my own client nonce").firstRequestClientNonce(response.getClientNonce());
 
 firstRequestClientNonce - the client nonce value used in the first requestgetFirstRequestClientNonce(), 
clientNonce(String), 
getClientNonce(), 
randomizeClientNonce(), 
Section 3.2.2.2, A1, of RFC
 2617public java.lang.String getFirstRequestClientNonce()
 This value is used in session based algorithms (those ending in -sess). If the
 challenge is reused for multiple request, the original client nonce used when responding to
 the original challenge is used in subsequent challenge responses, even if the client changes
 the client nonce for subsequent requests.
firstRequestClientNonce(String), 
clientNonce(String), 
getClientNonce(), 
randomizeClientNonce(), 
Section 3.2.2.2, A1, of RFC
 2617public DigestChallengeResponse quotedNonce(java.lang.String quotedNonce)
nonce directive, which must be the same as the nonce directive of the
 challenge.
 
 Setting the nonce directive resets the nonce count to one.
quotedNonce - the quoted value of the nonce directivegetQuotedNonce(), 
nonce(String), 
getNonce(), 
Section 3.2.2 of RFC 2617public java.lang.String getQuotedNonce()
nonce directive.nonce directivequotedNonce(String), 
nonce(String), 
getNonce()public DigestChallengeResponse nonce(java.lang.String unquotedNonce)
nonce directive, which must be the same as the nonce directive of the
 challenge.
 Setting the nonce directive resets the nonce count to one.
unquotedNonce - the unquoted value of the nonce directivegetNonce(), 
quotedNonce(String), 
getQuotedNonce(), 
Section 3.2.2 of RFC 2617public java.lang.String getNonce()
nonce directivenonce directivenonce(String), 
quotedNonce(String), 
getQuotedNonce()public DigestChallengeResponse nonceCount(int nonceCount)
nonce-count directive, which indicates how many
 times this a challenge response with this nonce has been used.
 This is useful when using a challenge response from a previous challenge when sending a request. For each time a challenge response is used, the nonce count should be increased by one.
nonceCount - integer representation of the nonce-count directivegetNonceCount(), 
resetNonceCount(), 
incrementNonceCount(), 
Section 3.2.2 of RFC 2617public DigestChallengeResponse incrementNonceCount()
nonce-count by one.nonceCount(int), 
getNonceCount(), 
resetNonceCount()public DigestChallengeResponse resetNonceCount()
nonce-count to one.nonceCount(int), 
getNonceCount(), 
incrementNonceCount()public int getNonceCount()
nonce-count directive.nonce-count directivenonceCount(int), 
resetNonceCount(), 
incrementNonceCount()public DigestChallengeResponse quotedOpaque(java.lang.String quotedOpaque)
opaque directive, which must be the same as the opaque directive of
 the challenge.quotedOpaque - the quoted value of the opaque directive, or null if no
                     opaque directive should be included in the challenge responsegetQuotedOpaque(), 
opaque(String), 
getOpaque(), 
Section 3.2.2 of RFC 2617public java.lang.String getQuotedOpaque()
opaque directive, or null.opaque directive, or null if the opaque is not setquotedOpaque(String), 
opaque(String), 
getOpaque()public DigestChallengeResponse opaque(java.lang.String unquotedOpaque)
opaque directive, which must be the same as the opaque directive of
 the challenge.
 
 Note: Since the value of the opaque directive is always received from a challenge
 quoted it is normally better to use the quotedOpaque(String) method to avoid
 unnecessary quoting/unquoting.
unquotedOpaque - the unquoted value of the opaque directive, or null if no
                       opaque directive should be included in the challenge responsegetOpaque(), 
quotedOpaque(String), 
getQuotedOpaque(), 
Section 3.2.2 of RFC 2617public java.lang.String getOpaque()
opaque directive, or null.opaque directive, or null if the opaque is not setopaque(String), 
quotedOpaque(String), 
getQuotedOpaque()public DigestChallengeResponse supportedQopTypes(java.util.Set<DigestChallenge.QualityOfProtection> supportedQopTypes)
 Normally, this value is sent by the server in the challenge, but setting it manually can be
 used to force a particular qop type. To see which quality of protection that will be used in
 the response, see getQop().
supportedQopTypes - the types of quality of protection that the server supports, must not
                          be emptyjava.lang.IllegalArgumentException - if supportedQopTypes is emptygetSupportedQopTypes(), 
getQop()public java.util.Set<DigestChallenge.QualityOfProtection> getSupportedQopTypes()
supportedQopTypes(Set), 
getQop()public DigestChallenge.QualityOfProtection getQop()
This is a derived value, computed from the set of supported "quality of protection" types:
DigestChallenge.QualityOfProtection.AUTH is supported it is used.DigestChallenge.QualityOfProtection.AUTH_INT is supported it is used.DigestChallenge.QualityOfProtection.UNSPECIFIED_RFC2069_COMPATIBLE is supported it
 is used.null will be returned.supportedQopTypes(Set), 
getSupportedQopTypes(), 
entityBodyDigest(byte[]), 
getEntityBodyDigest(), 
entityBody(byte[])public DigestChallengeResponse digestUri(java.lang.String digestUri)
digest-uri directive, which must be exactly the same as the
 Request-URI of the Request-Line of the HTTP request.
 The digest URI is explained in Section 3.2.2 of RFC 2617, and refers to the explanation of Request-URI found in Section 5.1.2 of RFC 2616.
 Examples: If the Request-Line is
 
GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1the
Request-URI (and digest-uri) is "http://www.w3.org/pub/WWW/TheProject.html". If Request-Line is
 GET /pub/WWW/TheProject.html HTTP/1.1the
Request-URI is "/pub/WWW/TheProject.html".
 
 This can be problematic since depending on the HTTP stack being used the Request-Line
 and Request-URI values may not be accessible. If in doubt, a sensible guess is to set
 the digest-uri to the path part of the URL being requested, for instance using
 
 getPath() in the URL class.
digestUri - the value of the digest-uri directivegetDigestUri()public java.lang.String getDigestUri()
digest-uri directive.digest-uri directivedigestUri(String)public DigestChallengeResponse quotedRealm(java.lang.String quotedRealm)
realm directive, which must be the same as the realm directive of
 the challenge.quotedRealm - the quoted value of the realm directivegetQuotedRealm(), 
realm(String), 
getRealm(), 
Section 3.2.1 of RFC 2617, 
Section 3.2.2 of RFC 2617public java.lang.String getQuotedRealm()
realm directive.realm directivequotedRealm(String), 
realm(String), 
getRealm()public DigestChallengeResponse realm(java.lang.String unquotedRealm)
realm directive, which must be the same as the realm directive of
 the challenge.unquotedRealm - the unquoted value of the realm directivegetRealm(), 
quotedRealm(String), 
getQuotedRealm(), 
Section 3.2.1 of RFC 2617, 
Section 3.2.2 of RFC 2617public java.lang.String getRealm()
realm directive.realm directiverealm(String), 
quotedRealm(String), 
getQuotedRealm()public DigestChallengeResponse requestMethod(java.lang.String requestMethod)
requestMethod - the request methodgetRequestMethod(), 
Section 5.1.1 of RFC 2616public java.lang.String getRequestMethod()
requestMethod(String)public DigestChallengeResponse entityBody(byte[] entityBody)
entity-body of the request, which is only used for the "auth-int" quality of
 protection.
 
 The default value is a byte array of zero length. Note that the entity-body is
 not stored, to save space only the digest of the entity-body is stored. For this
 reason, changing the digest algorithm (see algorithm(String)) will reset the
 entity-body to a zero-length array.
 
 With "auth-int" quality of protection, the whole entity-body of the message is
 hashed and included in the response, providing some protection against tampering.
 
 The entity-body is not the same as the message-body as explained in
 RFC 2616, Section 7.2:
 
[…]The entity-body is obtained from the message-body by decoding any Transfer-Encoding that might have been applied to ensure safe and proper transfer of the message.So if, for example,
Transfer-Encoding is gzip, the entity-body is the
 unzipped message and the message-body is the gzipped message.
 
 Not all requests include an entity-body, as explained in
 RFC 2616, Section 4.3:
 
[…]The presence of a message-body in a request is signaled by the inclusion of a Content-Length or Transfer-Encoding header field in the request's message-headers.[…]In particular, PUT and POST requests include an
entity-body (although it may be of
 zero length), GET requests do not. To be fully conformant with the standards, "auth-int"
 cannot be used to authenticate requests without an entity-body. Some servers
 implementations allow requests without an entity-body to be authenticated using an
 entity-body of zero length.entityBody - the entity-bodyentityBodyDigest(byte[])public DigestChallengeResponse entityBodyDigest(byte[] entityBodyDigest)
entity-body of the request, which is only used for the
 "auth-int" quality of protection.
 
 Note that the entity-body is not the same as the message-body. See
 entityBody(byte[]) for details.
 
Here is an example of how to compute the SHA-256 digest of an entity body:
 
 MessageDigest md = MessageDigest.getInstance("SHA-256");
 md.update(entityBody);
 byte[] digest = md.digest();
 
 entityBodyDigest - the digest of the entity-bodyentityBody(byte[])public byte[] getEntityBodyDigest()
entity-body.entity-bodypublic boolean isEntityBodyDigestRequired()
true if the digest of the entity-body is required to generate an
 authorization header for this response.
 
 For most challenges the digest of the entity-body is not used. It is only required
 if getQop() returns DigestChallenge.QualityOfProtection.AUTH_INT.
true if the digest of the entity-body must be setentityBody(byte[]), 
entityBodyDigest(byte[]), 
getSupportedQopTypes()public DigestChallengeResponse challenge(DigestChallenge challenge)
realm, nonce, opaque, and algorithm
 directives and the supported quality of protection types based on a challenge.
 
 If the challenge is not supported an exception is thrown. Use
 isChallengeSupported(DigestChallenge) to check if a challenge is supported before
 calling this method.
challenge - the challengejava.lang.IllegalArgumentException - if the challenge is not supportedisChallengeSupported(DigestChallenge)public java.lang.String getHeaderValue()
credentials, that is, the string to set in the Authorization
 HTTP request header.
 Before calling this method a number of values and directives must be set. The following are the most important:
 If the qop type is auth-int the following must also be set unless the default
 value (zero-length entity body) is applicable:
 
The following directives must also be set, but are normally parsed from the challenge or have default values, listed here mostly for completions sake:
quotedRealm(String), parsed from the challenge.quotedNonce(String), parsed from the challenge.supportedQopTypes(Set), parsed from the challenge.clientNonce(String)}, except if using the
 DigestChallenge.QualityOfProtection.UNSPECIFIED_RFC2069_COMPATIBLE qop (not recommended). Set to a
 random value by default.firstRequestClientNonce(String) if the algorithm is MD-sess. Set to the client
 nonce by default.Authorization HTTP request headerInsufficientInformationException - if any of the mandatory directives and values
                                          listed above has not been setpublic java.lang.String toString()
toString in class java.lang.Object