package org.beanfuse.security.codec;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class PasswordHandler {
protected PasswordHandler() {
}
public static PasswordHandler getInstance() {
return handler;
}
public boolean verify(String digest, String password) throws NoSuchAlgorithmException {
String alg = null;
int size = 0;
if (digest.regionMatches(true, 0, "{CRYPT}", 0, 7)) {
digest = digest.substring(7);
return UnixCrypt.matches(digest, password);
}
if (digest.regionMatches(true, 0, "{SHA}", 0, 5)) {
digest = digest.substring(5);
alg = "SHA-1";
size = 20;
} else if (digest.regionMatches(true, 0, "{SSHA}", 0, 6)) {
digest = digest.substring(6);
alg = "SHA-1";
size = 20;
} else if (digest.regionMatches(true, 0, "{MD5}", 0, 5)) {
digest = digest.substring(5);
alg = "MD5";
size = 16;
} else if (digest.regionMatches(true, 0, "{SMD5}", 0, 6)) {
digest = digest.substring(6);
alg = "MD5";
size = 16;
} else {
return digest.equals(password);
}
MessageDigest msgDigest = MessageDigest.getInstance(alg);
byte hs[][] = split(Base64.decode(digest.toCharArray()), size);
byte hash[] = hs[0];
byte salt[] = hs[1];
msgDigest.reset();
msgDigest.update(password.getBytes());
msgDigest.update(salt);
byte pwhash[] = msgDigest.digest();
return MessageDigest.isEqual(hash, pwhash);
}
public String generateDigest(String password, String saltHex, String algorithm)
throws NoSuchAlgorithmException {
if (algorithm.equalsIgnoreCase("crypt"))
return "{CRYPT}" + UnixCrypt.crypt(password);
if (algorithm.equalsIgnoreCase("sha"))
algorithm = "SHA-1";
else if (algorithm.equalsIgnoreCase("md5"))
algorithm = "MD5";
MessageDigest msgDigest = MessageDigest.getInstance(algorithm);
byte salt[] = new byte[0];
if (saltHex != null)
salt = fromHex(saltHex);
String label = null;
if (algorithm.startsWith("SHA"))
label = salt.length <= 0 ? "{SHA}" : "{SSHA}";
else if (algorithm.startsWith("MD5"))
label = salt.length <= 0 ? "{MD5}" : "{SMD5}";
msgDigest.reset();
msgDigest.update(password.getBytes());
msgDigest.update(salt);
byte pwhash[] = msgDigest.digest();
StringBuilder digest = new StringBuilder(label);
digest.append(Base64.encode(concatenate(pwhash, salt)));
return digest.toString();
}
private static byte[] concatenate(byte l[], byte r[]) {
byte b[] = new byte[l.length + r.length];
System.arraycopy(l, 0, b, 0, l.length);
System.arraycopy(r, 0, b, l.length, r.length);
return b;
}
private static byte[][] split(byte src[], int n) {
byte l[];
byte r[];
if (src.length <= n) {
l = src;
r = new byte[0];
} else {
l = new byte[n];
r = new byte[src.length - n];
System.arraycopy(src, 0, l, 0, n);
System.arraycopy(src, n, r, 0, r.length);
}
byte lr[][] = { l, r };
return lr;
}
private static String toHex(byte block[]) {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < block.length; i++) {
buf.append(hexits.charAt(block[i] >>> 4 & 0xf));
buf.append(hexits.charAt(block[i] & 0xf));
}
return buf.toString();
}
private static byte[] fromHex(String s) {
s = s.toLowerCase();
byte b[] = new byte[(s.length() + 1) / 2];
int j = 0;
int nybble = -1;
for (int i = 0; i < s.length(); i++) {
int h = hexits.indexOf(s.charAt(i));
if (h >= 0)
if (nybble < 0) {
nybble = h;
} else {
b[j++] = (byte) ((nybble << 4) + h);
nybble = -1;
}
}
if (nybble >= 0)
b[j++] = (byte) (nybble << 4);
if (j < b.length) {
byte b2[] = new byte[j];
System.arraycopy(b, 0, b2, 0, j);
b = b2;
}
return b;
}
private static PasswordHandler handler = new PasswordHandler();
private static String hexits = "0123456789abcdef";
}