[jboss-cvs] JBossAS SVN: r62956 - projects/security/security-jboss-sx/trunk/src/main/org/jboss/security/auth/spi.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu May 10 00:14:37 EDT 2007
Author: anil.saldhana at jboss.com
Date: 2007-05-10 00:14:37 -0400 (Thu, 10 May 2007)
New Revision: 62956
Removed:
projects/security/security-jboss-sx/trunk/src/main/org/jboss/security/auth/spi/RFC2617Digest.java
Log:
SECURITY-26: JBAS integration code moved to JBAS trunk
Deleted: projects/security/security-jboss-sx/trunk/src/main/org/jboss/security/auth/spi/RFC2617Digest.java
===================================================================
--- projects/security/security-jboss-sx/trunk/src/main/org/jboss/security/auth/spi/RFC2617Digest.java 2007-05-10 04:14:07 UTC (rev 62955)
+++ projects/security/security-jboss-sx/trunk/src/main/org/jboss/security/auth/spi/RFC2617Digest.java 2007-05-10 04:14:37 UTC (rev 62956)
@@ -1,397 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.security.auth.spi;
-
-import java.util.Map;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import javax.security.auth.callback.Callback;
-
-import org.jboss.crypto.digest.DigestCallback;
-import org.jboss.security.auth.callback.MapCallback;
-
-/**
- An implementation of the DigestCallback that support the http digest auth as
- described in RFC2617 (http://www.ietf.org/rfc/rfc2617.txt).
-
- 3.2.2.1 Request-Digest
-
- If the "qop" value is "auth" or "auth-int":
-
- request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" nc-value ":"
- unq(cnonce-value) ":" unq(qop-value) ":" H(A2) ) <">
-
- If the "qop" directive is not present (this construction is for compatibility
- with RFC 2069):
-
- request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
-
- See below for the definitions for A1 and A2.
-
- 3.2.2.2 A1
-
- If the "algorithm" directive's value is "MD5" or is unspecified, then A1 is:
-
- A1 = unq(username-value) ":" unq(realm-value) ":" passwd
-
- where
-
- passwd = < user's password >
-
- If the "algorithm" directive's value is "MD5-sess", then A1 is calculated only
- once - on the first request by the client following receipt of a
- WWW-Authenticate challenge from the server. It uses the server nonce from that
- challenge, and the first client nonce value to construct A1 as follows:
-
- A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd ) ":"
- unq(nonce-value) ":" unq(cnonce-value)
-
- This creates a 'session key' for the authentication of subsequent requests and
- responses which is different for each "authentication session", thus limiting
- the amount of material hashed with any one key. (Note: see further discussion
- of the authentication session in section 3.3.) Because the server need only use
- the hash of the user credentials in order to create the A1 value, this
- construction could be used in conjunction with a third party authentication
- service so that the web server would not need the actual password value. The
- specification of such a protocol is beyond the scope of this specification.
-
- 3.2.2.3 A2
-
- If the "qop" directive's value is "auth" or is unspecified, then A2 is:
-
- A2 = Method ":" digest-uri-value
-
- If the "qop" value is "auth-int", then A2 is:
-
- A2 = Method ":" digest-uri-value ":" H(entity-body)
-
- 3.2.2.4 Directive values and quoted-string
-
- Note that the value of many of the directives, such as "username- value", are
- defined as a "quoted-string". However, the "unq" notation indicates that
- surrounding quotation marks are removed in forming the string A1. Thus if the
- Authorization header includes the fields
-
- username="Mufasa", realm=myhost at testrealm.com
-
- and the user Mufasa has password "Circle Of Life" then H(A1) would be
- H(Mufasa:myhost at testrealm.com:Circle Of Life) with no quotation marks in the
- digested string.
-
- No white space is allowed in any of the strings to which the digest function H()
- is applied unless that white space exists in the quoted strings or entity body
- whose contents make up the string to be digested. For example, the string A1
- illustrated above must be
-
- Mufasa:myhost at testrealm.com:Circle Of Life
-
- with no white space on either side of the colons, but with the white space
- between the words used in the password value. Likewise, the other strings
- digested by H() must not have white space on either side of the colons which
- delimit their fields unless that white space was in the quoted strings or entity
- body being digested.
-
- Also note that if integrity protection is applied (qop=auth-int), the
- H(entity-body) is the hash of the entity body, not the message body - it is
- computed before any transfer encoding is applied by the sender and after it has
- been removed by the recipient. Note that this includes multipart boundaries and
- embedded headers in each part of any multipart content-type.
-
- @author Scott.Stark at jboss.org
- @version $Revision$
- */
-public class RFC2617Digest implements DigestCallback
-{
- /**
- String which can enable users to know which username and password to use, in
- case they might have different ones for different servers.
- */
- public static final String REALM = "realm";
- /**
- The user's name in the specified realm.
- */
- public static final String USERNAME = "username";
- /**
- The URI from Request-URI of the Request-Line; duplicated here because proxies
- are allowed to change the Request-Line in transit.
- */
- public static final String DIGEST_URI = "digest-uri";
- /**
- A server-specified data string which MUST be different each time a
- digest-challenge is sent as part of initial authentication. It is
- recommended that this string be base64 or hexadecimal data. Note that since
- the string is passed as a quoted string, the double-quote character is not
- allowed unless escaped (see section 7.2). The contents of the nonce are
- implementation dependent. The
-
- security of the implementation depends on a good choice. It is RECOMMENDED
- that it contain at least 64 bits of entropy. The nonce is opaque to the
- client. This directive is required and MUST appear exactly once; if not
- present, or if multiple instances are present, the client should abort the
- authentication exchange.
- */
- public static final String NONCE = "nonce";
- /**
- This MUST be specified if a qop directive is sent (see above), and MUST NOT
- be specified if the server did not send a qop directive in the
- WWW-Authenticate header field. The cnonce-value is an opaque quoted string
- value provided by the client and used by both client and server to avoid
- chosen plaintext attacks, to provide mutual authentication, and to provide
- some message integrity protection. See the descriptions below of the
- calculation of the response- digest and request-digest values.
- */
- public static final String CNONCE = "cnonce";
- /**
- This MUST be specified if a qop directive is sent (see above), and MUST NOT
- be specified if the server did not send a qop directive in the
- WWW-Authenticate header field. The nc-value is the hexadecimal count of the
- number of requests (including the current request) that the client has sent
- with the nonce value in this request. For example, in the first request sent
- in response to a given nonce value, the client sends "nc=00000001". The
- purpose of this directive is to allow the server to detect request replays by
- maintaining its own copy of this count - if the same nc-value is seen twice,
- then the request is a replay. See the description below of the construction
- of the request-digest value.
- */
- public static final String NONCE_COUNT = "nc";
- /**
- Indicates what "quality of protection" the client has applied to the message.
- If present, its value MUST be one of the alternatives the server indicated it
- supports in the WWW-Authenticate header. These values affect the computation
- of the request-digest. Note that this is a single token, not a quoted list of
- alternatives as in WWW- Authenticate. This directive is optional in order to
- preserve backward compatibility with a minimal implementation of RFC 2069
- [6], but SHOULD be used if the server indicated that qop is supported by
- providing a qop directive in the WWW-Authenticate header field.
- */
- public static final String QOP = "qop";
- /**
- A string indicating a pair of algorithms used to produce the digest
- and a checksum. If this is not present it is assumed to be "MD5".
- If the algorithm is not understood, the challenge should be ignored
- (and a different one used, if there is more than one).
-
- In this document the string obtained by applying the digest
- algorithm to the data "data" with secret "secret" will be denoted
- by KD(secret, data), and the string obtained by applying the
- checksum algorithm to the data "data" will be denoted H(data). The
- notation unq(X) means the value of the quoted-string X without the
- surrounding quotes.
- */
- public static final String ALGORITHM = "algorithm";
- /**
- This directive allows for future extensions. Any unrecognized directive MUST
- be ignored.
- */
- public static final String AUTH_PARAM = "auth-param";
- /**
- The http method type
- */
- public static final String METHOD = "method";
- /**
- An explicit A2 digest
- */
- public static final String A2HASH = "a2hash";
- /**
- The ASCII printable characters the MD5 digest maps to
- */
- private static char[] MD5_HEX = "0123456789abcdef".toCharArray();
-
- private MapCallback info;
- private String username;
- private String password;
- private boolean passwordIsA1Hash;
- String rfc2617;
-
- public void init(Map options)
- {
- username = (String) options.get("javax.security.auth.login.name");
- password = (String) options.get("javax.security.auth.login.password");
- String flag = (String) options.get("passwordIsA1Hash");
- if( flag != null )
- passwordIsA1Hash = Boolean.valueOf(flag).booleanValue();
-
- // Ask for MapCallback to obtain the digest parameters
- info = new MapCallback();
- Callback[] callbacks = {info};
- options.put("callbacks", callbacks);
- }
-
- public void preDigest(MessageDigest digest)
- {
- }
- public void postDigest(MessageDigest digest)
- {
- String qop = (String) info.getInfo(QOP);
- String realm = (String) info.getInfo(REALM);
- String algorithm = (String) info.getInfo(ALGORITHM);
- String nonce = (String) info.getInfo(NONCE);
- String cnonce = (String) info.getInfo(CNONCE);
- String method = (String) info.getInfo(METHOD);
- String nc = (String) info.getInfo(NONCE_COUNT);
- String digestURI = (String) info.getInfo(DIGEST_URI);
-
- if( algorithm == null )
- algorithm = digest.getAlgorithm();
- // This replaces the existing hash, it does not add to it
- digest.reset();
-
- String hA1 = null;
- // 3.2.2.2 A1
- if (algorithm == null || algorithm.equals("MD5"))
- {
- if( passwordIsA1Hash )
- hA1 = password;
- else
- {
- String A1 = username + ":" + realm + ":" + password;
- hA1 = H(A1, digest);
- }
- }
- else if (algorithm.equals("MD5-sess"))
- {
- if( passwordIsA1Hash )
- {
- hA1 = password + ":" + nonce + ":" + cnonce;
- }
- else
- {
- String A1 = username + ":" + realm + ":" + password;
- hA1 = H(A1, digest) + ":" + nonce + ":" + cnonce;
- }
- }
- else
- {
- throw new IllegalArgumentException("Unsupported algorigthm: "+algorithm);
- }
-
- // 3.2.2.3 A2. First check to see if the A2 hash has been precomputed
- String hA2 = (String) info.getInfo(A2HASH);
- if (hA2 == null)
- {
- // No, compute it based on qop
- String A2 = null;
- if (qop == null | qop.equals("auth"))
- {
- A2 = method + ":" + digestURI;
- }
- else
- {
- throw new IllegalArgumentException("Unsupported qop="+qop);
- }
- hA2 = H(A2, digest);
- }
-
- // 3.2.2.1 Request-Digest
- if (qop == null)
- {
- String extra = nonce + ":" + hA2;
- KD(hA1, extra, digest);
- }
- else if (qop.equals("auth"))
- {
- String extra = nonce +
- ":" + nc +
- ":" + cnonce +
- ":" + qop +
- ":" + hA2;
- KD(hA1, extra, digest);
- }
- }
-
- public String getInfoDigest(MessageDigest digest)
- {
- if( rfc2617 == null )
- {
- byte[] data = digest.digest();
- rfc2617 = cvtHex(data);
- }
- return rfc2617;
- }
-
- static private String H(String data, MessageDigest digest)
- {
- digest.reset();
- byte[] x = digest.digest(data.getBytes());
- return cvtHex(x);
- }
- static private void KD(String secret, String data, MessageDigest digest)
- {
- String x = secret + ":" + data;
- digest.reset();
- digest.update(x.getBytes());
- }
-
- /**
- 3.1.3 Representation of digest values
-
- An optional header allows the server to specify the algorithm used to create
- the checksum or digest. By default the MD5 algorithm is used and that is the
- only algorithm described in this document.
-
- For the purposes of this document, an MD5 digest of 128 bits is represented
- as 32 ASCII printable characters. The bits in the 128 bit digest are
- converted from most significant to least significant bit, four bits at a time
- to their ASCII presentation as follows. Each four bits is represented by its
- familiar hexadecimal notation from the characters 0123456789abcdef. That is,
- binary 0000 getInfos represented by the character '0', 0001, by '1', and so on up
- to the representation of 1111 as 'f'.
-
- @param data - the raw MD5 hash data
- @return the encoded MD5 representation
- */
- static String cvtHex(byte[] data)
- {
- char[] hash = new char[32];
- for (int i = 0; i < 16; i++)
- {
- int j = (data[i] >> 4) & 0xf;
- hash[i * 2] = MD5_HEX[j];
- j = data[i] & 0xf;
- hash[i * 2 + 1] = MD5_HEX[j];
- }
- return new String(hash);
- }
-
- /**
- Compute the
- @param args
- */
- public static void main(String[] args) throws NoSuchAlgorithmException
- {
- if( args.length != 3 )
- {
- System.err.println("Usage: RFC2617Digest username realm password");
- System.err.println(" - username : the username");
- System.err.println(" - realm : the web app realm name");
- System.err.println(" - password : the plain text password");
- System.exit(1);
- }
- String username = args[0];
- String realm = args[1];
- String password = args[2];
- String A1 = username + ":" + realm + ":" + password;
- MessageDigest digest = MessageDigest.getInstance("MD5");
- String hA1 = H(A1, digest);
- System.out.println("RFC2617 A1 hash: "+hA1);
- }
-}
More information about the jboss-cvs-commits
mailing list