[jboss-cvs] JBossAS SVN: r62953 - projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu May 10 00:08:50 EDT 2007
Author: anil.saldhana at jboss.com
Date: 2007-05-10 00:08:50 -0400 (Thu, 10 May 2007)
New Revision: 62953
Added:
projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CryptoUtil.java
Removed:
projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherClientSocketFactory.java
projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherServerSocket.java
projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherServerSocketFactory.java
projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherSocket.java
Log:
SECURITY-26: JBAS integration code moved to JBAS trunk
Deleted: projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherClientSocketFactory.java
===================================================================
--- projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherClientSocketFactory.java 2007-05-10 04:00:17 UTC (rev 62952)
+++ projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherClientSocketFactory.java 2007-05-10 04:08:50 UTC (rev 62953)
@@ -1,67 +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.crypto;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.net.Socket;
-import java.rmi.server.RMIClientSocketFactory;
-
-
-/** An implementation of RMIClientSocketFactory that uses the JCE Cipher
- with an SRP session key to create an encrypted stream.
-
- at author Scott.Stark at jboss.org
- at version $Revision$
-*/
-public class CipherClientSocketFactory implements RMIClientSocketFactory, Serializable
-{
- private static final long serialVersionUID = -6412485012870705607L;
-
- /** Creates new CipherClientSocketFactory */
- public CipherClientSocketFactory()
- {
- }
-
- /** Create a client socket connected to the specified host and port.
- * @param host - the host name
- * @param port - the port number
- * @return a socket connected to the specified host and port.
- * @exception IOException if an I/O error occurs during socket creation.
- */
- public Socket createSocket(String host, int port)
- throws IOException
- {
- CipherSocket socket = null;
- return socket;
- }
-
- public boolean equals(Object obj)
- {
- return obj instanceof CipherClientSocketFactory;
- }
- public int hashCode()
- {
- return getClass().getName().hashCode();
- }
-
-}
Deleted: projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherServerSocket.java
===================================================================
--- projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherServerSocket.java 2007-05-10 04:00:17 UTC (rev 62952)
+++ projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherServerSocket.java 2007-05-10 04:08:50 UTC (rev 62953)
@@ -1,53 +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.crypto;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import javax.crypto.SecretKey;
-
-/**
- *
- * @author Scott.Stark at jboss.org
- */
-public class CipherServerSocket extends ServerSocket
-{
- String algorithm;
- SecretKey key;
-
- /** Creates a new instance of CipherServerSocket */
- public CipherServerSocket(int port, int backlog,
- InetAddress bindAddr, String algorithm, SecretKey key) throws IOException
- {
- super(port, backlog, bindAddr);
- this.algorithm = algorithm;
- this.key = key;
- }
-
- public Socket accept() throws IOException
- {
- Socket s = super.accept();
- return new CipherSocket(s, algorithm, key);
- }
-}
Deleted: projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherServerSocketFactory.java
===================================================================
--- projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherServerSocketFactory.java 2007-05-10 04:00:17 UTC (rev 62952)
+++ projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherServerSocketFactory.java 2007-05-10 04:08:50 UTC (rev 62953)
@@ -1,75 +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.crypto;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.net.ServerSocket;
-import java.net.UnknownHostException;
-import java.rmi.server.RMIServerSocketFactory;
-
-
-/** An implementation of RMIServerSocketFactory that uses a
- DomainServerSocketFactory for its implementation. This class is just an
- adaptor from the RMIServerSocketFactory to the DomainServerSocketFactory.
-
- This class is not suitable for RMI object that require a Serializable socket
- factory like activatable services. The reason for this limitation is that
- a SecurityDomain is not serializable due to its association with a local
- KeyStore.
-
- at author Scott.Stark at jboss.org
- at version $Revision$
-*/
-public class CipherServerSocketFactory implements RMIServerSocketFactory
-{
-
- /** Creates new RMISSLServerSocketFactory */
- public CipherServerSocketFactory()
- {
- }
-
-
- /**
- * Create a server socket on the specified port (port 0 indicates
- * an anonymous port).
- * @param port the port number
- * @return the server socket on the specified port
- * @exception IOException if an I/O error occurs during server socket
- * creation
- */
- public ServerSocket createServerSocket(int port)
- throws IOException
- {
- CipherServerSocket socket = null;
- return socket;
- }
-
- public boolean equals(Object obj)
- {
- return obj instanceof CipherServerSocketFactory;
- }
- public int hashCode()
- {
- return getClass().getName().hashCode();
- }
-}
Deleted: projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherSocket.java
===================================================================
--- projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherSocket.java 2007-05-10 04:00:17 UTC (rev 62952)
+++ projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CipherSocket.java 2007-05-10 04:08:50 UTC (rev 62953)
@@ -1,104 +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.crypto;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.util.Arrays;
-import javax.crypto.Cipher;
-import javax.crypto.CipherInputStream;
-import javax.crypto.CipherOutputStream;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.SecretKey;
-
-/**
- *
- * @author Scott.Stark at jboss.org
- */
-public class CipherSocket extends Socket
-{
- private Cipher cipher;
- private Socket delegate;
- String algorithm;
- SecretKey key;
-
- /** Creates a new instance of CipherSocket */
- public CipherSocket(String host, int port, String algorithm, SecretKey key)
- throws IOException
- {
- super(host, port);
- this.algorithm = algorithm;
- this.key = key;
- }
- public CipherSocket(Socket delegate, String algorithm, SecretKey key)
- throws IOException
- {
- this.delegate = delegate;
- this.algorithm = algorithm;
- this.key = key;
- }
-
- public InputStream getInputStream() throws IOException
- {
- InputStream is = delegate == null ? super.getInputStream() : delegate.getInputStream();
- Cipher cipher = null;
- try
- {
- cipher = Cipher.getInstance(algorithm);
- int size = cipher.getBlockSize();
- byte[] tmp = new byte[size];
- Arrays.fill(tmp, (byte)15);
- IvParameterSpec iv = new IvParameterSpec(tmp);
- cipher.init(Cipher.DECRYPT_MODE, key, iv);
- }
- catch(Exception e)
- {
- e.printStackTrace();
- throw new IOException("Failed to init cipher: "+e.getMessage());
- }
- CipherInputStream cis = new CipherInputStream(is, cipher);
- return cis;
- }
-
- public OutputStream getOutputStream() throws IOException
- {
- OutputStream os = delegate == null ? super.getOutputStream() : delegate.getOutputStream();
- Cipher cipher = null;
- try
- {
- cipher = Cipher.getInstance(algorithm);
- int size = cipher.getBlockSize();
- byte[] tmp = new byte[size];
- Arrays.fill(tmp, (byte)15);
- IvParameterSpec iv = new IvParameterSpec(tmp);
- cipher.init(Cipher.ENCRYPT_MODE, key, iv);
- }
- catch(Exception e)
- {
- throw new IOException("Failed to init cipher: "+e.getMessage());
- }
- CipherOutputStream cos = new CipherOutputStream(os, cipher);
- return cos;
- }
-}
Added: projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CryptoUtil.java
===================================================================
--- projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CryptoUtil.java (rev 0)
+++ projects/security/security-jboss-sx/trunk/src/main/org/jboss/crypto/CryptoUtil.java 2007-05-10 04:08:50 UTC (rev 62953)
@@ -0,0 +1,609 @@
+/*
+* 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.crypto;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.SecureRandom;
+import java.security.acl.Group;
+import java.util.Iterator;
+import java.util.Random;
+import java.util.Set;
+import javax.naming.InitialContext;
+import javax.security.auth.Subject;
+
+import org.jboss.crypto.JBossSXProvider;
+import org.jboss.crypto.digest.DigestCallback;
+import org.jboss.logging.Logger;
+import org.jboss.security.AuthenticationManager;
+import org.jboss.security.AuthorizationManager;
+import org.jboss.security.Base64Encoder;
+import org.jboss.security.Base64Utils;
+import org.jboss.security.SecurityConstants;
+import org.jboss.security.config.ApplicationPolicy;
+import org.jboss.security.config.SecurityConfiguration;
+
+/** Various security related utilities like MessageDigest
+ factories, SecureRandom access, password hashing.
+
+ This product includes software developed by Tom Wu and Eugene
+ Jhong for the SRP Distribution (http://srp.stanford.edu/srp/).
+
+ @author Scott.Stark at jboss.org
+ @version $Revision: 62650 $
+ */
+public class CryptoUtil
+{
+ private static Logger log = Logger.getLogger(CryptoUtil.class);
+ private static final int HASH_LEN = 20;
+ public static final String BASE64_ENCODING = "BASE64";
+ public static final String BASE16_ENCODING = "HEX";
+ public static final String RFC2617_ENCODING = "RFC2617";
+ /**
+ The ASCII printable characters the MD5 digest maps to for RFC2617
+ */
+ private static char[] MD5_HEX = "0123456789abcdef".toCharArray();
+
+ private static SecureRandom psuedoRng;
+ private static MessageDigest sha1Digest;
+ private static boolean initialized;
+
+ public static void init() throws NoSuchAlgorithmException
+ {
+ if( initialized )
+ return;
+ init(null);
+ }
+ public static void init(byte[] prngSeed) throws NoSuchAlgorithmException
+ {
+ // Get an instance of the SHA-1 digest
+ sha1Digest = MessageDigest.getInstance("SHA");
+ // Get a cryptographically strong pseudo-random generator
+ psuedoRng = SecureRandom.getInstance("SHA1PRNG");
+ if( prngSeed != null )
+ psuedoRng.setSeed(prngSeed);
+ // Install the JBossSX security provider
+ Provider provider = new JBossSXProvider();
+ Security.addProvider(provider);
+ initialized = true;
+ }
+
+ public static MessageDigest newDigest()
+ {
+ MessageDigest md = null;
+ try
+ {
+ md = (MessageDigest) sha1Digest.clone();
+ }
+ catch(CloneNotSupportedException e)
+ {
+ }
+ return md;
+ }
+ public static MessageDigest copy(MessageDigest md)
+ {
+ MessageDigest copy = null;
+ try
+ {
+ copy = (MessageDigest) md.clone();
+ }
+ catch(CloneNotSupportedException e)
+ {
+ }
+ return copy;
+ }
+
+ public static Random getPRNG()
+ {
+ return psuedoRng;
+ }
+ /** Returns the next pseudorandom, uniformly distributed double value
+ between 0.0 and 1.0 from this random number generator's sequence.
+ */
+ public static double nextDouble()
+ {
+ return psuedoRng.nextDouble();
+ }
+ /** Returns the next pseudorandom, uniformly distributed long value from
+ this random number generator's sequence. The general contract of
+ nextLong is that one long value is pseudorandomly generated and
+ returned. All 264 possible long values are produced with
+ (approximately) equal probability.
+ */
+ public static long nextLong()
+ {
+ return psuedoRng.nextLong();
+ }
+ /** Generates random bytes and places them into a user-supplied byte
+ array. The number of random bytes produced is equal to the length
+ of the byte array.
+ */
+ public static void nextBytes(byte[] bytes)
+ {
+ psuedoRng.nextBytes(bytes);
+ }
+ /** Returns the given number of seed bytes, computed using the seed
+ generation algorithm that this class uses to seed itself. This call
+ may be used to seed other random number generators.
+ */
+ public static byte[] generateSeed(int numBytes)
+ {
+ return psuedoRng.generateSeed(numBytes);
+ }
+
+ /** Cacluate the SRP RFC2945 password hash = H(salt | H(username | ':' | password))
+ where H = SHA secure hash. The username is converted to a byte[] using the
+ UTF-8 encoding.
+ */
+ public static byte[] calculatePasswordHash(String username, char[] password,
+ byte[] salt)
+ {
+ // Calculate x = H(s | H(U | ':' | password))
+ MessageDigest xd = newDigest();
+ // Try to convert the username to a byte[] using UTF-8
+ byte[] user = null;
+ byte[] colon = {};
+ try
+ {
+ user = username.getBytes("UTF-8");
+ colon = ":".getBytes("UTF-8");
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ log.error("Failed to convert username to byte[] using UTF-8", e);
+ // Use the default platform encoding
+ user = username.getBytes();
+ colon = ":".getBytes();
+ }
+ byte[] passBytes = new byte[2*password.length];
+ int passBytesLength = 0;
+ for(int p = 0; p < password.length; p ++)
+ {
+ int c = (password[p] & 0x00FFFF);
+ // The low byte of the char
+ byte b0 = (byte) (c & 0x0000FF);
+ // The high byte of the char
+ byte b1 = (byte) ((c & 0x00FF00) >> 8);
+ passBytes[passBytesLength ++] = b0;
+ // Only encode the high byte if c is a multi-byte char
+ if( c > 255 )
+ passBytes[passBytesLength ++] = b1;
+ }
+
+ // Build the hash
+ xd.update(user);
+ xd.update(colon);
+ xd.update(passBytes, 0, passBytesLength);
+ byte[] h = xd.digest();
+ xd.reset();
+ xd.update(salt);
+ xd.update(h);
+ byte[] xb = xd.digest();
+ return xb;
+ }
+
+ /** Calculate x = H(s | H(U | ':' | password)) verifier
+ v = g^x % N
+ described in RFC2945.
+ */
+ public static byte[] calculateVerifier(String username, char[] password,
+ byte[] salt, byte[] Nb, byte[] gb)
+ {
+ BigInteger g = new BigInteger(1, gb);
+ BigInteger N = new BigInteger(1, Nb);
+ return calculateVerifier(username, password, salt, N, g);
+ }
+ /** Calculate x = H(s | H(U | ':' | password)) verifier
+ v = g^x % N
+ described in RFC2945.
+ */
+ public static byte[] calculateVerifier(String username, char[] password,
+ byte[] salt, BigInteger N, BigInteger g)
+ {
+ byte[] xb = calculatePasswordHash(username, password, salt);
+ BigInteger x = new BigInteger(1, xb);
+ BigInteger v = g.modPow(x, N);
+ return v.toByteArray();
+ }
+
+ /** Perform an interleaved even-odd hash on the byte string
+ */
+ public static byte[] sessionKeyHash(byte[] number)
+ {
+ int i, offset;
+
+ for(offset = 0; offset < number.length && number[offset] == 0; ++offset)
+ ;
+
+ byte[] key = new byte[2 * HASH_LEN];
+ byte[] hout;
+
+ int klen = (number.length - offset) / 2;
+ byte[] hbuf = new byte[klen];
+
+ for(i = 0; i < klen; ++i)
+ {
+ hbuf[i] = number[number.length - 2 * i - 1];
+ }
+ hout = newDigest().digest(hbuf);
+ for(i = 0; i < HASH_LEN; ++i)
+ key[2 * i] = hout[i];
+
+ for(i = 0; i < klen; ++i)
+ {
+ hbuf[i] = number[number.length - 2 * i - 2];
+ }
+ hout = newDigest().digest(hbuf);
+ for(i = 0; i < HASH_LEN; ++i)
+ key[2 * i + 1] = hout[i];
+
+ return key;
+ }
+
+ /** Treat the input as the MSB representation of a number,
+ and lop off leading zero elements. For efficiency, the
+ input is simply returned if no leading zeroes are found.
+ */
+ public static byte[] trim(byte[] in)
+ {
+ if(in.length == 0 || in[0] != 0)
+ return in;
+
+ int len = in.length;
+ int i = 1;
+ while(in[i] == 0 && i < len)
+ ++i;
+ byte[] ret = new byte[len - i];
+ System.arraycopy(in, i, ret, 0, len - i);
+ return ret;
+ }
+
+ public static byte[] xor(byte[] b1, byte[] b2, int length)
+ {
+ byte[] result = new byte[length];
+ for(int i = 0; i < length; ++i)
+ result[i] = (byte) (b1[i] ^ b2[i]);
+ return result;
+ }
+
+ /**
+ 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
+ */
+ public static String encodeRFC2617(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);
+ }
+
+ /**
+ * Hex encoding of hashes, as used by Catalina. Each byte is converted to
+ * the corresponding two hex characters.
+ */
+ public static String encodeBase16(byte[] bytes)
+ {
+ StringBuffer sb = new StringBuffer(bytes.length * 2);
+ for (int i = 0; i < bytes.length; i++)
+ {
+ byte b = bytes[i];
+ // top 4 bits
+ char c = (char)((b >> 4) & 0xf);
+ if(c > 9)
+ c = (char)((c - 10) + 'a');
+ else
+ c = (char)(c + '0');
+ sb.append(c);
+ // bottom 4 bits
+ c = (char)(b & 0xf);
+ if (c > 9)
+ c = (char)((c - 10) + 'a');
+ else
+ c = (char)(c + '0');
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * BASE64 encoder implementation.
+ * Provides encoding methods, using the BASE64 encoding rules, as defined
+ * in the MIME specification, <a href="http://ietf.org/rfc/rfc1521.txt">rfc1521</a>.
+ */
+ public static String encodeBase64(byte[] bytes)
+ {
+ String base64 = null;
+ try
+ {
+ base64 = Base64Encoder.encode(bytes);
+ }
+ catch(Exception e)
+ {
+ }
+ return base64;
+ }
+
+ /**
+ * Calculate a password hash using a MessageDigest.
+ *
+ * @param hashAlgorithm - the MessageDigest algorithm name
+ * @param hashEncoding - either base64 or hex to specify the type of
+ encoding the MessageDigest as a string.
+ * @param hashCharset - the charset used to create the byte[] passed to the
+ * MessageDigestfrom the password String. If null the platform default is
+ * used.
+ * @param username - ignored in default version
+ * @param password - the password string to be hashed
+ * @return the hashed string if successful, null if there is a digest exception
+ */
+ public static String createPasswordHash(String hashAlgorithm, String hashEncoding,
+ String hashCharset, String username, String password)
+ {
+ return createPasswordHash(hashAlgorithm, hashEncoding,
+ hashCharset, username, password, null);
+ }
+ /**
+ * Calculate a password hash using a MessageDigest.
+ *
+ * @param hashAlgorithm - the MessageDigest algorithm name
+ * @param hashEncoding - either base64 or hex to specify the type of
+ encoding the MessageDigest as a string.
+ * @param hashCharset - the charset used to create the byte[] passed to the
+ * MessageDigestfrom the password String. If null the platform default is
+ * used.
+ * @param username - ignored in default version
+ * @param password - the password string to be hashed
+ * @param callback - the callback used to allow customization of the hash
+ * to occur. The preDigest method is called before the password is added
+ * and the postDigest method is called after the password has been added.
+ * @return the hashed string if successful, null if there is a digest exception
+ */
+ public static String createPasswordHash(String hashAlgorithm, String hashEncoding,
+ String hashCharset, String username, String password, DigestCallback callback)
+ {
+ byte[] passBytes;
+ String passwordHash = null;
+
+ // convert password to byte data
+ try
+ {
+ if(hashCharset == null)
+ passBytes = password.getBytes();
+ else
+ passBytes = password.getBytes(hashCharset);
+ }
+ catch(UnsupportedEncodingException uee)
+ {
+ log.error("charset " + hashCharset + " not found. Using platform default.", uee);
+ passBytes = password.getBytes();
+ }
+
+ // calculate the hash and apply the encoding.
+ try
+ {
+ MessageDigest md = MessageDigest.getInstance(hashAlgorithm);
+ if( callback != null )
+ callback.preDigest(md);
+ md.update(passBytes);
+ if( callback != null )
+ callback.postDigest(md);
+ byte[] hash = md.digest();
+ if(hashEncoding.equalsIgnoreCase(BASE64_ENCODING))
+ {
+ passwordHash = encodeBase64(hash);
+ }
+ else if(hashEncoding.equalsIgnoreCase(BASE16_ENCODING))
+ {
+ passwordHash = encodeBase16(hash);
+ }
+ else if(hashEncoding.equalsIgnoreCase(RFC2617_ENCODING))
+ {
+ passwordHash = encodeRFC2617(hash);
+ }
+ else
+ {
+ log.error("Unsupported hash encoding format " + hashEncoding);
+ }
+ }
+ catch(Exception e)
+ {
+ log.error("Password hash calculation failed ", e);
+ }
+ return passwordHash;
+ }
+
+ // These functions assume that the byte array has MSB at 0, LSB at end.
+ // Reverse the byte array (not the String) if this is not the case.
+ // All base64 strings are in natural order, least significant digit last.
+ public static String tob64(byte[] buffer)
+ {
+ return Base64Utils.tob64(buffer);
+ }
+
+ public static byte[] fromb64(String str) throws NumberFormatException
+ {
+ return Base64Utils.fromb64(str);
+ }
+
+ /** From Appendix E of the JCE ref guide, the xaximum key size
+ * allowed by the "Strong" jurisdiction policy files allows a maximum Blowfish
+ * cipher size of 128 bits.
+ * @return true if a Blowfish key can be initialized with 256 bit
+ * size, false otherwise.
+ */
+ public static boolean hasUnlimitedCrypto()
+ {
+ boolean hasUnlimitedCrypto = false;
+ try
+ {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Class keyGenClass = loader.loadClass("javax.crypto.KeyGenerator");
+ Class[] sig = {String.class};
+ Object[] args = {"Blowfish"};
+ Method kgenInstance = keyGenClass.getDeclaredMethod("getInstance", sig);
+ Object kgen = kgenInstance.invoke(null, args);
+
+ Class[] sig2 = {int.class};
+ Object[] args2 = {new Integer(256)};
+ Method init = keyGenClass.getDeclaredMethod("init", sig2);
+ init.invoke(kgen, args2);
+ hasUnlimitedCrypto = true;
+ }
+ catch(Throwable e)
+ {
+ log.debug("hasUnlimitedCrypto error", e);
+ }
+ return hasUnlimitedCrypto;
+ }
+
+ /** Use reflection to create a javax.crypto.spec.SecretKeySpec to avoid
+ an explicit reference to SecretKeySpec so that the JCE is not needed
+ unless the SRP parameters indicate that encryption is needed.
+ @return a javax.cyrpto.SecretKey
+ */
+ public static Object createSecretKey(String cipherAlgorithm, Object key) throws KeyException
+ {
+ Class[] signature = {key.getClass(), String.class};
+ Object[] args = {key, cipherAlgorithm};
+ Object secretKey = null;
+ try
+ {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Class secretKeySpecClass = loader.loadClass("javax.crypto.spec.SecretKeySpec");
+ Constructor ctor = secretKeySpecClass.getDeclaredConstructor(signature);
+ secretKey = ctor.newInstance(args);
+ }
+ catch(Exception e)
+ {
+ throw new KeyException("Failed to create SecretKeySpec from session key, msg="+e.getMessage());
+ }
+ catch(Throwable e)
+ {
+ throw new KeyException("Unexpected exception during SecretKeySpec creation, msg="+e.getMessage());
+ }
+ return secretKey;
+ }
+
+ /**
+ * @param cipherAlgorithm
+ * @return A javax.crypto.Cipher
+ * @throws GeneralSecurityException
+ */
+ public static Object createCipher(String cipherAlgorithm)
+ throws GeneralSecurityException
+ {
+ javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(cipherAlgorithm);
+ return cipher;
+ }
+ public static Object createSealedObject(String cipherAlgorithm, Object key, byte[] cipherIV,
+ Serializable data)
+ throws GeneralSecurityException
+ {
+ Object sealedObject = null;
+ try
+ {
+ javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(cipherAlgorithm);
+ javax.crypto.SecretKey skey = (javax.crypto.SecretKey) key;
+ if( cipherIV != null )
+ {
+ javax.crypto.spec.IvParameterSpec iv = new javax.crypto.spec.IvParameterSpec(cipherIV);
+ cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, skey, iv);
+ }
+ else
+ {
+ cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, skey);
+ }
+ sealedObject = new javax.crypto.SealedObject(data, cipher);
+ }
+ catch(GeneralSecurityException e)
+ {
+ throw e;
+ }
+ catch(Throwable e)
+ {
+ throw new GeneralSecurityException("Failed to create SealedObject, msg="+e.getMessage());
+ }
+ return sealedObject;
+ }
+
+ public static Object accessSealedObject(String cipherAlgorithm, Object key, byte[] cipherIV,
+ Object obj)
+ throws GeneralSecurityException
+ {
+ Object data = null;
+ try
+ {
+ javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(cipherAlgorithm);
+ javax.crypto.SecretKey skey = (javax.crypto.SecretKey) key;
+ if( cipherIV != null )
+ {
+ javax.crypto.spec.IvParameterSpec iv = new javax.crypto.spec.IvParameterSpec(cipherIV);
+ cipher.init(javax.crypto.Cipher.DECRYPT_MODE, skey, iv);
+ }
+ else
+ {
+ cipher.init(javax.crypto.Cipher.DECRYPT_MODE, skey);
+ }
+ javax.crypto.SealedObject sealedObj = (javax.crypto.SealedObject) obj;
+ data = sealedObj.getObject(cipher);
+ }
+ catch(GeneralSecurityException e)
+ {
+ throw e;
+ }
+ catch(Throwable e)
+ {
+ throw new GeneralSecurityException("Failed to access SealedObject, msg="+e.getMessage());
+ }
+ return data;
+ }
+
+}
More information about the jboss-cvs-commits
mailing list