You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by do...@apache.org on 2012/04/19 01:49:11 UTC
svn commit: r1327740 -
/ofbiz/trunk/framework/base/src/org/ofbiz/base/crypto/HashCrypt.java
Author: doogie
Date: Wed Apr 18 23:49:10 2012
New Revision: 1327740
URL: http://svn.apache.org/viewvc?rev=1327740&view=rev
Log:
FEATURE: Add unix(glibc)-compatible password hashing, exact same output, with support for salts.
Modified:
ofbiz/trunk/framework/base/src/org/ofbiz/base/crypto/HashCrypt.java
Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/crypto/HashCrypt.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/crypto/HashCrypt.java?rev=1327740&r1=1327739&r2=1327740&view=diff
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/crypto/HashCrypt.java (original)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/crypto/HashCrypt.java Wed Apr 18 23:49:10 2012
@@ -18,9 +18,15 @@
*******************************************************************************/
package org.ofbiz.base.crypto;
+import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Random;
+import org.apache.commons.codec.EncoderException;
+import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang.RandomStringUtils;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralRuntimeException;
import org.ofbiz.base.util.StringUtil;
@@ -33,6 +39,84 @@ import org.ofbiz.base.util.UtilValidate;
public class HashCrypt {
public static final String module = HashCrypt.class.getName();
+ public static final String CRYPT_CHAR_SET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
+
+ public static boolean comparePassword(String crypted, String defaultCrypt, String password) {
+ try {
+ if (crypted.startsWith("{")) {
+ int typeEnd = crypted.indexOf("}");
+ String hashType = crypted.substring(1, typeEnd);
+ String hashed = crypted.substring(typeEnd + 1);
+ MessageDigest messagedigest = MessageDigest.getInstance(hashType);
+ // FIXME: should have been getBytes("UTF-8") originally
+ messagedigest.update(password.getBytes());
+ byte[] digestBytes = messagedigest.digest();
+ char[] digestChars = Hex.encodeHex(digestBytes);
+ if (hashed.equals(new String(digestChars))) {
+ return true;
+ }
+ // This next block should be removed when all {prefix}oldFunnyHex are fixed.
+ int k = 0;
+ digestChars = new char[digestBytes.length * 2];
+ for (int l = 0; l < digestBytes.length; l++) {
+ int i1 = digestBytes[l];
+
+ if (i1 < 0) {
+ i1 = 127 + i1 * -1;
+ }
+ StringUtil.encodeInt(i1, k, digestChars);
+ k += 2;
+ }
+ if (hashed.equals(new String(digestChars))) {
+ Debug.logWarning("Warning: detected oldFunnyHex password prefixed with a hashType; this is not valid", module);
+ return true;
+ }
+ return false;
+ } else if (crypted.startsWith("$")) {
+ int typeEnd = crypted.indexOf("$", 1);
+ int saltEnd = crypted.indexOf("$", typeEnd + 1);
+ String hashType = crypted.substring(1, typeEnd);
+ String salt = crypted.substring(typeEnd + 1, saltEnd);
+ String hashed = crypted.substring(saltEnd + 1);
+ return hashed.equals(getCrypted(hashType, salt, password));
+ } else {
+ String hashType = defaultCrypt;
+ String hashed = crypted;
+ MessageDigest messagedigest = MessageDigest.getInstance(hashType);
+ // FIXME: should have been getBytes("UTF-8") originally
+ messagedigest.update(password.getBytes());
+ char[] digestChars = Hex.encodeHex(messagedigest.digest());
+ return hashed.equals(new String(digestChars));
+ }
+ } catch (NoSuchAlgorithmException e) {
+ throw new GeneralRuntimeException("Error while comparing password", e);
+ }
+ }
+
+ public static String cryptPassword(String hashType, String password) {
+ int saltLength = new Random().nextInt(15) + 1;
+ return cryptPassword(hashType, RandomStringUtils.random(saltLength, CRYPT_CHAR_SET), password);
+ }
+
+ public static String cryptPassword(String hashType, String salt, String password) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("$").append(hashType).append("$").append(salt).append("$");
+ sb.append(getCrypted(hashType, salt, password));
+ return sb.toString();
+ }
+
+ private static String getCrypted(String hashType, String salt, String password) {
+ try {
+ MessageDigest messagedigest = MessageDigest.getInstance(hashType);
+ messagedigest.update(salt.getBytes("UTF-8"));
+ messagedigest.update(password.getBytes("UTF-8"));
+ return Base64.encodeBase64URLSafeString(messagedigest.digest()).replace('+', '.');
+ } catch (NoSuchAlgorithmException e) {
+ throw new GeneralRuntimeException("Error while comparing password", e);
+ } catch (UnsupportedEncodingException e) {
+ throw new GeneralRuntimeException("Error while comparing password", e);
+ }
+ }
public static String getDigestHash(String str) {
return getDigestHash(str, "SHA");