[seam-commits] Seam SVN: r10419 - in trunk/src/main/org/jboss/seam/security: crypto and 1 other directories.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Wed Apr 15 02:41:04 EDT 2009
Author: shane.bryzak at jboss.com
Date: 2009-04-15 02:41:04 -0400 (Wed, 15 Apr 2009)
New Revision: 10419
Added:
trunk/src/main/org/jboss/seam/security/crypto/
trunk/src/main/org/jboss/seam/security/crypto/BinTools.java
trunk/src/main/org/jboss/seam/security/crypto/MacBasedPRF.java
trunk/src/main/org/jboss/seam/security/crypto/PBKDF2.java
trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Engine.java
trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Formatter.java
trunk/src/main/org/jboss/seam/security/crypto/PBKDF2HexFormatter.java
trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Parameters.java
trunk/src/main/org/jboss/seam/security/crypto/PRF.java
Modified:
trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java
trunk/src/main/org/jboss/seam/security/management/PasswordHash.java
Log:
hashing algorithms in jdk5 suck, so provide our own default one
Added: trunk/src/main/org/jboss/seam/security/crypto/BinTools.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/crypto/BinTools.java (rev 0)
+++ trunk/src/main/org/jboss/seam/security/crypto/BinTools.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -0,0 +1,122 @@
+package org.jboss.seam.security.crypto;
+
+/**
+ * Copied from Matthias Gartner's PKCS#5 implementation - see
+ * http://rtner.de/software/PBKDF2.html
+ *
+ * <p>
+ * Free auxiliary functions. Copyright (c) 2007 Matthias Gärtner
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * </p>
+ * <p>
+ * For Details, see <a
+ * href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
+ * >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
+ * </p>
+ *
+ * @author Matthias Gärtner
+ * @version 1.0
+ */
+public class BinTools
+{
+ public static final String hex = "0123456789ABCDEF";
+
+ /**
+ * Simple binary-to-hexadecimal conversion.
+ *
+ * @param b
+ * Input bytes. May be <code>null</code>.
+ * @return Hexadecimal representation of b. Uppercase A-F, two characters per
+ * byte. Empty string on <code>null</code> input.
+ */
+ public static String bin2hex(final byte[] b)
+ {
+ if (b == null)
+ {
+ return "";
+ }
+ StringBuffer sb = new StringBuffer(2 * b.length);
+ for (int i = 0; i < b.length; i++)
+ {
+ int v = (256 + b[i]) % 256;
+ sb.append(hex.charAt((v / 16) & 15));
+ sb.append(hex.charAt((v % 16) & 15));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Convert hex string to array of bytes.
+ *
+ * @param s
+ * String containing hexadecimal digits. May be <code>null</code>.
+ * On odd length leading zero will be assumed.
+ * @return Array on bytes, non-<code>null</code>.
+ * @throws IllegalArgumentException
+ * when string contains non-hex character
+ */
+ public static byte[] hex2bin(final String s)
+ {
+ String m = s;
+ if (s == null)
+ {
+ // Allow empty input string.
+ m = "";
+ }
+ else if (s.length() % 2 != 0)
+ {
+ // Assume leading zero for odd string length
+ m = "0" + s;
+ }
+ byte r[] = new byte[m.length() / 2];
+ for (int i = 0, n = 0; i < m.length(); n++)
+ {
+ char h = m.charAt(i++);
+ char l = m.charAt(i++);
+ r[n] = (byte) (hex2bin(h) * 16 + hex2bin(l));
+ }
+ return r;
+ }
+
+ /**
+ * Convert hex digit to numerical value.
+ *
+ * @param c
+ * 0-9, a-f, A-F allowd.
+ * @return 0-15
+ * @throws IllegalArgumentException
+ * on non-hex character
+ */
+ public static int hex2bin(char c)
+ {
+ if (c >= '0' && c <= '9')
+ {
+ return (c - '0');
+ }
+ if (c >= 'A' && c <= 'F')
+ {
+ return (c - 'A' + 10);
+ }
+ if (c >= 'a' && c <= 'f')
+ {
+ return (c - 'a' + 10);
+ }
+ throw new IllegalArgumentException("Input string may only contain hex digits, but found '" + c + "'");
+ }
+}
\ No newline at end of file
Added: trunk/src/main/org/jboss/seam/security/crypto/MacBasedPRF.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/crypto/MacBasedPRF.java (rev 0)
+++ trunk/src/main/org/jboss/seam/security/crypto/MacBasedPRF.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -0,0 +1,114 @@
+package org.jboss.seam.security.crypto;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Copied from Matthias Gartner's PKCS#5 implementation - see
+ * http://rtner.de/software/PBKDF2.html
+ *
+ * Default PRF implementation based on standard javax.crypt.Mac mechanisms.
+ *
+ * <hr />
+ * <p>
+ * A free Java implementation of Password Based Key Derivation Function 2 as
+ * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * </p>
+ * <p>
+ * For Details, see <a
+ * href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
+ * </p>
+ *
+ * @author Matthias Gärtner
+ * @version 1.0
+ */
+public class MacBasedPRF implements PRF
+{
+ protected Mac mac;
+
+ protected int hLen;
+
+ protected String macAlgorithm;
+
+ /**
+ * Create Mac-based Pseudo Random Function.
+ *
+ * @param macAlgorithm
+ * Mac algorithm to use, i.e. HMacSHA1 or HMacMD5.
+ */
+ public MacBasedPRF(String macAlgorithm)
+ {
+ this.macAlgorithm = macAlgorithm;
+ try
+ {
+ mac = Mac.getInstance(macAlgorithm);
+ hLen = mac.getMacLength();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MacBasedPRF(String macAlgorithm, String provider)
+ {
+ this.macAlgorithm = macAlgorithm;
+ try
+ {
+ mac = Mac.getInstance(macAlgorithm, provider);
+ hLen = mac.getMacLength();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public byte[] doFinal(byte[] M)
+ {
+ byte[] r = mac.doFinal(M);
+ return r;
+ }
+
+ public int getHLen()
+ {
+ return hLen;
+ }
+
+ public void init(byte[] P)
+ {
+ try
+ {
+ mac.init(new SecretKeySpec(P, macAlgorithm));
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
Added: trunk/src/main/org/jboss/seam/security/crypto/PBKDF2.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/crypto/PBKDF2.java (rev 0)
+++ trunk/src/main/org/jboss/seam/security/crypto/PBKDF2.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -0,0 +1,102 @@
+package org.jboss.seam.security.crypto;
+
+/**
+ * Copied from Matthias Gartner's PKCS#5 implementation - see
+ * http://rtner.de/software/PBKDF2.html.
+ *
+ * <p>
+ * A free Java implementation of Password Based Key Derivation Function 2 as
+ * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * </p>
+ * <p>
+ * For Details, see <a
+ * href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
+ * >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
+ * </p>
+ *
+ * @author Matthias Gärtner
+ * @version 1.0
+ */
+public interface PBKDF2
+{
+ /**
+ * Convert String-based input to internal byte array, then invoke PBKDF2.
+ * Desired key length defaults to Pseudo Random Function block size.
+ *
+ * @param inputPassword
+ * Candidate password to compute the derived key for.
+ * @return internal byte array
+ */
+ public abstract byte[] deriveKey(String inputPassword);
+
+ /**
+ * Convert String-based input to internal byte array, then invoke PBKDF2.
+ *
+ * @param inputPassword
+ * Candidate password to compute the derived key for.
+ * @param dkLen
+ * Specify desired key length
+ * @return internal byte array
+ */
+ public abstract byte[] deriveKey(String inputPassword, int dkLen);
+
+ /**
+ * Convert String-based input to internal byte arrays, then invoke PBKDF2 and
+ * verify result against the reference data that is supplied in the
+ * PBKDF2Parameters.
+ *
+ * @param inputPassword
+ * Candidate password to compute the derived key for.
+ * @return <code>true</code> password match; <code>false</code> incorrect
+ * password
+ */
+ public abstract boolean verifyKey(String inputPassword);
+
+ /**
+ * Allow reading of configured parameters.
+ *
+ * @return Currently set parameters.
+ */
+ public abstract PBKDF2Parameters getParameters();
+
+ /**
+ * Allow setting of configured parameters.
+ *
+ * @param parameters
+ */
+ public abstract void setParameters(PBKDF2Parameters parameters);
+
+ /**
+ * Get currently set Pseudo Random Function.
+ *
+ * @return Currently set Pseudo Random Function
+ */
+ public abstract PRF getPseudoRandomFunction();
+
+ /**
+ * Set the Pseudo Random Function to use. Note that deriveKeys/getPRF does
+ * init this object using the supplied candidate password. If this is
+ * undesired, one has to override getPRF.
+ *
+ * @param prf
+ * Pseudo Random Function to set.
+ */
+ public abstract void setPseudoRandomFunction(PRF prf);
+}
\ No newline at end of file
Added: trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Engine.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Engine.java (rev 0)
+++ trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Engine.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -0,0 +1,340 @@
+package org.jboss.seam.security.crypto;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+/**
+ * Copied from Matthias Gartner's PKCS#5 implementation - see
+ * http://rtner.de/software/PBKDF2.html
+ *
+ * <p>
+ * Request for Comments: 2898 PKCS #5: Password-Based Cryptography Specification
+ * <p>
+ * Version 2.0
+ *
+ * <p>
+ * PBKDF2 (P, S, c, dkLen)
+ *
+ * <p>
+ * Options:
+ * <ul>
+ * <li>PRF underlying pseudorandom function (hLen denotes the length in octets
+ * of the pseudorandom function output). PRF is pluggable.</li>
+ * </ul>
+ *
+ * <p>
+ * Input:
+ * <ul>
+ * <li>P password, an octet string</li>
+ * <li>S salt, an octet string</li>
+ * <li>c iteration count, a positive integer</li>
+ * <li>dkLen intended length in octets of the derived key, a positive integer,
+ * at most (2^32 - 1) * hLen</li>
+ * </ul>
+ *
+ * <p>
+ * Output:
+ * <ul>
+ * <li>DK derived key, a dkLen-octet string</li>
+ * </ul>
+ *
+ * <hr />
+ * <p>
+ * A free Java implementation of Password Based Key Derivation Function 2 as
+ * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * </p>
+ * <p>
+ * For Details, see <a
+ * href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
+ * >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
+ * </p>
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898</a>
+ * @author Matthias Gärtner
+ * @version 1.0
+ */
+public class PBKDF2Engine implements PBKDF2
+{
+ protected PBKDF2Parameters parameters;
+
+ protected PRF prf;
+
+ /**
+ * Constructor for PBKDF2 implementation object. PBKDF2 parameters must be
+ * passed later.
+ */
+ public PBKDF2Engine()
+ {
+ this.parameters = null;
+ prf = null;
+ }
+
+ /**
+ * Constructor for PBKDF2 implementation object. PBKDF2 parameters are passed
+ * so that this implementation knows iteration count, method to use and
+ * String encoding.
+ *
+ * @param parameters
+ * Data holder for iteration count, method to use et cetera.
+ */
+ public PBKDF2Engine(PBKDF2Parameters parameters)
+ {
+ this.parameters = parameters;
+ prf = null;
+ }
+
+ /**
+ * Constructor for PBKDF2 implementation object. PBKDF2 parameters are passed
+ * so that this implementation knows iteration count, method to use and
+ * String encoding.
+ *
+ * @param parameters
+ * Data holder for iteration count, method to use et cetera.
+ * @param prf
+ * Supply customer Pseudo Random Function.
+ */
+ public PBKDF2Engine(PBKDF2Parameters parameters, PRF prf)
+ {
+ this.parameters = parameters;
+ this.prf = prf;
+ }
+
+ public byte[] deriveKey(String inputPassword)
+ {
+ return deriveKey(inputPassword, 0);
+ }
+
+ public byte[] deriveKey(String inputPassword, int dkLen)
+ {
+ byte[] r = null;
+ byte P[] = null;
+ String charset = parameters.getHashCharset();
+ if (inputPassword == null)
+ {
+ inputPassword = "";
+ }
+ try
+ {
+ if (charset == null)
+ {
+ P = inputPassword.getBytes();
+ }
+ else
+ {
+ P = inputPassword.getBytes(charset);
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ assertPRF(P);
+ if (dkLen == 0)
+ {
+ dkLen = prf.getHLen();
+ }
+ r = PBKDF2(prf, parameters.getSalt(), parameters.getIterationCount(), dkLen);
+ return r;
+ }
+
+ public boolean verifyKey(String inputPassword)
+ {
+ byte[] referenceKey = getParameters().getDerivedKey();
+ if (referenceKey == null || referenceKey.length == 0)
+ {
+ return false;
+ }
+ byte[] inputKey = deriveKey(inputPassword, referenceKey.length);
+
+ if (inputKey == null || inputKey.length != referenceKey.length)
+ {
+ return false;
+ }
+ for (int i = 0; i < inputKey.length; i++)
+ {
+ if (inputKey[i] != referenceKey[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Factory method. Default implementation is (H)MAC-based. To be overridden
+ * in derived classes.
+ *
+ * @param P
+ * User-supplied candidate password as array of bytes.
+ */
+ protected void assertPRF(byte[] P)
+ {
+ if (prf == null)
+ {
+ prf = new MacBasedPRF(parameters.getHashAlgorithm());
+ }
+ prf.init(P);
+ }
+
+ public PRF getPseudoRandomFunction()
+ {
+ return prf;
+ }
+
+ /**
+ * Core Password Based Key Derivation Function 2.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2</a>
+ * @param prf
+ * Pseudo Random Function (i.e. HmacSHA1)
+ * @param S
+ * Salt as array of bytes. <code>null</code> means no salt.
+ * @param c
+ * Iteration count (see RFC 2898 4.2)
+ * @param dkLen
+ * desired length of derived key.
+ * @return internal byte array
+ */
+ protected byte[] PBKDF2(PRF prf, byte[] S, int c, int dkLen)
+ {
+ if (S == null)
+ {
+ S = new byte[0];
+ }
+ int hLen = prf.getHLen();
+ int l = ceil(dkLen, hLen);
+ int r = dkLen - (l - 1) * hLen;
+ byte T[] = new byte[l * hLen];
+ int ti_offset = 0;
+ for (int i = 1; i <= l; i++)
+ {
+ _F(T, ti_offset, prf, S, c, i);
+ ti_offset += hLen;
+ }
+ if (r < hLen)
+ {
+ // Incomplete last block
+ byte DK[] = new byte[dkLen];
+ System.arraycopy(T, 0, DK, 0, dkLen);
+ return DK;
+ }
+ return T;
+ }
+
+ /**
+ * Integer division with ceiling function.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 2.</a>
+ * @param a
+ * @param b
+ * @return ceil(a/b)
+ */
+ protected int ceil(int a, int b)
+ {
+ int m = 0;
+ if (a % b > 0)
+ {
+ m = 1;
+ }
+ return a / b + m;
+ }
+
+ /**
+ * Function F.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 3.</a>
+ * @param dest
+ * Destination byte buffer
+ * @param offset
+ * Offset into destination byte buffer
+ * @param prf
+ * Pseudo Random Function
+ * @param S
+ * Salt as array of bytes
+ * @param c
+ * Iteration count
+ * @param blockIndex
+ */
+ protected void _F(byte[] dest, int offset, PRF prf, byte[] S, int c, int blockIndex)
+ {
+ int hLen = prf.getHLen();
+ byte U_r[] = new byte[hLen];
+
+ // U0 = S || INT (i);
+ byte U_i[] = new byte[S.length + 4];
+ System.arraycopy(S, 0, U_i, 0, S.length);
+ INT(U_i, S.length, blockIndex);
+
+ for (int i = 0; i < c; i++)
+ {
+ U_i = prf.doFinal(U_i);
+ xor(U_r, U_i);
+ }
+ System.arraycopy(U_r, 0, dest, offset, hLen);
+ }
+
+ /**
+ * Block-Xor. Xor source bytes into destination byte buffer. Destination
+ * buffer must be same length or less than source buffer.
+ *
+ * @param dest
+ * @param src
+ */
+ protected void xor(byte[] dest, byte[] src)
+ {
+ for (int i = 0; i < dest.length; i++)
+ {
+ dest[i] ^= src[i];
+ }
+ }
+
+ /**
+ * Four-octet encoding of the integer i, most significant octet first.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 3.</a>
+ * @param dest
+ * @param offset
+ * @param i
+ */
+ protected void INT(byte[] dest, int offset, int i)
+ {
+ dest[offset + 0] = (byte) (i / (256 * 256 * 256));
+ dest[offset + 1] = (byte) (i / (256 * 256));
+ dest[offset + 2] = (byte) (i / (256));
+ dest[offset + 3] = (byte) (i);
+ }
+
+ public PBKDF2Parameters getParameters()
+ {
+ return parameters;
+ }
+
+ public void setParameters(PBKDF2Parameters parameters)
+ {
+ this.parameters = parameters;
+ }
+
+ public void setPseudoRandomFunction(PRF prf)
+ {
+ this.prf = prf;
+ }
+}
Added: trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Formatter.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Formatter.java (rev 0)
+++ trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Formatter.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -0,0 +1,57 @@
+package org.jboss.seam.security.crypto;
+
+/**
+ * Copied from Matthias Gartner's PKCS#5 implementation - see
+ * http://rtner.de/software/PBKDF2.html
+ *
+ * <p>
+ * A free Java implementation of Password Based Key Derivation Function 2 as
+ * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * </p>
+ * <p>
+ * For Details, see <a
+ * href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
+ * </p>
+ *
+ * @author Matthias Gärtner
+ * @version 1.0
+ */
+public interface PBKDF2Formatter
+{
+ /**
+ * Convert parameters to String.
+ *
+ * @param p
+ * Parameters object to output.
+ * @return String representation
+ */
+ public abstract String toString(PBKDF2Parameters p);
+
+ /**
+ * Convert String to parameters. Depending on actual implementation, it may
+ * be required to set further fields externally.
+ *
+ * @param s
+ * String representation of parameters to decode.
+ * @return <code>false</code> syntax OK, <code>true</code> some syntax
+ * issue.
+ */
+ public abstract boolean fromString(PBKDF2Parameters p, String s);
+}
\ No newline at end of file
Added: trunk/src/main/org/jboss/seam/security/crypto/PBKDF2HexFormatter.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/crypto/PBKDF2HexFormatter.java (rev 0)
+++ trunk/src/main/org/jboss/seam/security/crypto/PBKDF2HexFormatter.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -0,0 +1,68 @@
+package org.jboss.seam.security.crypto;
+
+/**
+ * Copied from Matthias Gartner's PKCS#5 implementation - see
+ * http://rtner.de/software/PBKDF2.html
+ *
+ * <p>
+ * A free Java implementation of Password Based Key Derivation Function 2 as
+ * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * </p>
+ * <p>
+ * For Details, see <a
+ * href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
+ * </p>
+ *
+ * @author Matthias Gärtner
+ * @version 1.0
+ */
+public class PBKDF2HexFormatter implements PBKDF2Formatter
+{
+ public boolean fromString(PBKDF2Parameters p, String s)
+ {
+ if (p == null || s == null)
+ {
+ return true;
+ }
+
+ String[] p123 = s.split(":");
+ if (p123 == null || p123.length != 3)
+ {
+ return true;
+ }
+
+ byte salt[] = BinTools.hex2bin(p123[0]);
+ int iterationCount = Integer.parseInt(p123[1]);
+ byte bDK[] = BinTools.hex2bin(p123[2]);
+
+ p.setSalt(salt);
+ p.setIterationCount(iterationCount);
+ p.setDerivedKey(bDK);
+ return false;
+ }
+
+ public String toString(PBKDF2Parameters p)
+ {
+ String s = BinTools.bin2hex(p.getSalt()) + ":"
+ + String.valueOf(p.getIterationCount()) + ":"
+ + BinTools.bin2hex(p.getDerivedKey());
+ return s;
+ }
+}
\ No newline at end of file
Added: trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Parameters.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Parameters.java (rev 0)
+++ trunk/src/main/org/jboss/seam/security/crypto/PBKDF2Parameters.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -0,0 +1,165 @@
+package org.jboss.seam.security.crypto;
+
+/**
+ * Copied from Matthias Gartner's PKCS#5 implementation - see
+ * http://rtner.de/software/PBKDF2.html
+ *
+ * <p>
+ * Parameter data holder for PBKDF2 configuration.
+ * </p>
+ *
+ * <hr />
+ * <p>
+ * A free Java implementation of Password Based Key Derivation Function 2 as
+ * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * </p>
+ * <p>
+ * For Details, see <a
+ * href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
+ * >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
+ * </p>
+ *
+ * @author Matthias Gärtner
+ * @version 1.0
+ */
+public class PBKDF2Parameters
+{
+ protected byte[] salt;
+
+ protected int iterationCount;
+
+ protected String hashAlgorithm;
+
+ protected String hashCharset;
+
+ /**
+ * The derived key is actually only a convenience to store a reference
+ * derived key. It is not used during computation.
+ */
+ protected byte[] derivedKey;
+
+ /**
+ * Constructor. Defaults to <code>null</code> for byte arrays, UTF-8 as
+ * character set and 1000 for iteration count.
+ *
+ */
+ public PBKDF2Parameters()
+ {
+ this.hashAlgorithm = null;
+ this.hashCharset = "UTF-8";
+ this.salt = null;
+ this.iterationCount = 1000;
+ this.derivedKey = null;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param hashAlgorithm
+ * for example HMacSHA1 or HMacMD5
+ * @param hashCharset
+ * for example UTF-8
+ * @param salt
+ * Salt as byte array, may be <code>null</code> (not recommended)
+ * @param iterationCount
+ * Number of iterations to execute. Recommended value 1000.
+ */
+ public PBKDF2Parameters(String hashAlgorithm, String hashCharset, byte[] salt, int iterationCount)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.hashCharset = hashCharset;
+ this.salt = salt;
+ this.iterationCount = iterationCount;
+ this.derivedKey = null;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param hashAlgorithm
+ * for example HMacSHA1 or HMacMD5
+ * @param hashCharset
+ * for example UTF-8
+ * @param salt
+ * Salt as byte array, may be <code>null</code> (not recommended)
+ * @param iterationCount
+ * Number of iterations to execute. Recommended value 1000.
+ * @param derivedKey
+ * Convenience data holder, not used during computation.
+ */
+ public PBKDF2Parameters(String hashAlgorithm, String hashCharset, byte[] salt, int iterationCount, byte[] derivedKey)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.hashCharset = hashCharset;
+ this.salt = salt;
+ this.iterationCount = iterationCount;
+ this.derivedKey = derivedKey;
+ }
+
+ public int getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ public void setIterationCount(int iterationCount)
+ {
+ this.iterationCount = iterationCount;
+ }
+
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ public void setSalt(byte[] salt)
+ {
+ this.salt = salt;
+ }
+
+ public byte[] getDerivedKey()
+ {
+ return derivedKey;
+ }
+
+ public void setDerivedKey(byte[] derivedKey)
+ {
+ this.derivedKey = derivedKey;
+ }
+
+ public String getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public void setHashAlgorithm(String hashAlgorithm)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ }
+
+ public String getHashCharset()
+ {
+ return hashCharset;
+ }
+
+ public void setHashCharset(String hashCharset)
+ {
+ this.hashCharset = hashCharset;
+ }
+}
Added: trunk/src/main/org/jboss/seam/security/crypto/PRF.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/crypto/PRF.java (rev 0)
+++ trunk/src/main/org/jboss/seam/security/crypto/PRF.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -0,0 +1,64 @@
+package org.jboss.seam.security.crypto;
+
+/**
+ * Copied from Matthias Gartner's PKCS#5 implementation - see
+ * http://rtner.de/software/PBKDF2.html
+ *
+ * <p>
+ * A free Java implementation of Password Based Key Derivation Function 2 as
+ * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * This library 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.
+ * </p>
+ * <p>
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * </p>
+ * <p>
+ * For Details, see <a
+ * href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
+ * >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
+ * </p>
+ *
+ * @author Matthias Gärtner
+ * @version 1.0
+ */
+public interface PRF
+{
+ /**
+ * Initialize this instance with the user-supplied password.
+ *
+ * @param P
+ * The password supplied as array of bytes. It is the caller's task
+ * to convert String passwords to bytes as appropriate.
+ */
+ public void init(byte[] P);
+
+ /**
+ * Pseudo Random Function
+ *
+ * @param M
+ * Input data/message etc. Together with any data supplied during
+ * initilization.
+ * @return Random bytes of hLen length.
+ */
+ public byte[] doFinal(byte[] M);
+
+ /**
+ * Query block size of underlying algorithm/mechanism.
+ *
+ * @return block size
+ */
+ public int getHLen();
+}
\ No newline at end of file
Modified: trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java 2009-04-14 23:58:24 UTC (rev 10418)
+++ trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -43,8 +43,8 @@
import org.jboss.seam.security.Identity;
import org.jboss.seam.security.Role;
import org.jboss.seam.security.SimplePrincipal;
+import org.jboss.seam.security.crypto.BinTools;
import org.jboss.seam.util.AnnotatedBeanProperty;
-import org.jboss.seam.util.Base64;
import org.jboss.seam.util.TypedBeanProperty;
/**
@@ -254,7 +254,7 @@
if (passwordSaltProperty.isSet())
{
byte[] salt = generateUserSalt(user);
- passwordSaltProperty.setValue(user, Base64.encodeBytes(salt));
+ passwordSaltProperty.setValue(user, BinTools.bin2hex(salt));
userPasswordProperty.setValue(user, generatePasswordHash(password, salt));
}
else
@@ -821,7 +821,7 @@
", but it contains no value");
}
- passwordHash = generatePasswordHash(password, Base64.decode(encodedSalt));
+ passwordHash = generatePasswordHash(password, BinTools.hex2bin(encodedSalt));
}
else
{
Modified: trunk/src/main/org/jboss/seam/security/management/PasswordHash.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/management/PasswordHash.java 2009-04-14 23:58:24 UTC (rev 10418)
+++ trunk/src/main/org/jboss/seam/security/management/PasswordHash.java 2009-04-15 06:41:04 UTC (rev 10419)
@@ -10,7 +10,6 @@
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
-import javax.crypto.spec.SecretKeySpec;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
@@ -18,6 +17,10 @@
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.security.crypto.BinTools;
+import org.jboss.seam.security.crypto.PBKDF2;
+import org.jboss.seam.security.crypto.PBKDF2Engine;
+import org.jboss.seam.security.crypto.PBKDF2Parameters;
import org.jboss.seam.util.Base64;
/**
@@ -36,7 +39,15 @@
private static final String DEFAULT_ALGORITHM = ALGORITHM_MD5;
- private int saltLength = 8; // default password salt length, in bytes
+ /*
+ * If specified, use the JCE instead of the built in algorithm
+ */
+ private String hashAlgorithm = null;
+
+ /*
+ * default password salt length, in bytes
+ */
+ private int saltLength = 8;
@Deprecated
public String generateHash(String password)
@@ -100,12 +111,20 @@
public String createPasswordKey(char[] password, byte[] salt, int iterations)
throws GeneralSecurityException
{
- PBEKeySpec passwordKeySpec = new PBEKeySpec(password, salt, iterations, 256);
- SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
- SecretKey passwordKey = secretKeyFactory.generateSecret(passwordKeySpec);
- passwordKeySpec.clearPassword();
- byte[] encoded = passwordKey.getEncoded();
- return Base64.encodeBytes(new SecretKeySpec(encoded, "AES").getEncoded());
+ if (hashAlgorithm != null)
+ {
+ PBEKeySpec passwordKeySpec = new PBEKeySpec(password, salt, iterations, 256);
+ SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(hashAlgorithm);
+ SecretKey passwordKey = secretKeyFactory.generateSecret(passwordKeySpec);
+ passwordKeySpec.clearPassword();
+ return BinTools.bin2hex(passwordKey.getEncoded());
+ }
+ else
+ {
+ PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA1", "ISO-8859-1", salt, iterations);
+ PBKDF2 pbkdf2 = new PBKDF2Engine(params);
+ return BinTools.bin2hex(pbkdf2.deriveKey(new String(password)));
+ }
}
public static PasswordHash instance()
@@ -113,6 +132,16 @@
return (PasswordHash) Component.getInstance(PasswordHash.class, ScopeType.STATELESS);
}
+ public String getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public void setHashAlgorithm(String hashAlgorithm)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ }
+
public int getSaltLength()
{
return saltLength;
More information about the seam-commits
mailing list