照着JeeSite代码搬出来的。
需要了解的知识 Hex编码 散列算法

用户 注册/修改 密码的时候根据输入的密码生成一段加密串,每次验证密码时候根据算法进行密文比对,想要通过密文解出明文密码需要花费大量时间。

<1> 加密
    1. 生成一段salt,值随机,长度自定义。 // 个人理解就是捣乱的,因为是随机的
    2. 将 明文密码 + salt 进行散列N次。 // N自定义,哈希算法自定义。
    3. 将 1 2 分别Hex编码,并且相加的密文密码。
<2> 解密
    1. 截取密文密码前 xx 位数,进行Hex解码取得salt。
    2. 将 用户输入的明文密码 + salt 进行散列N次。
    3. 将 1 2 分别Hex编码 相加,最后与密文密码对比。

因为salt是随机生成的,如果想要破解需要针对每条密文数据进行破解。
根据哈希算法的不同于计算次数不同增加了破解的难度。

import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.SecureRandom;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.Validate;

public class Security {

    public static final int SALT_SIZE = 8;
    private static final String SHA1 = "SHA-1";
    private static SecureRandom random = new SecureRandom();
    public static final int HASH_INTERATIONS = 1024;

    /**
     * 传入明文密码,生成密文密码
     */
    public static String entryptPassword(String plainPassword) {
        String plain = unescapeHtml(plainPassword);
        byte[] salt = generateSalt(SALT_SIZE);
        byte[] hashPassword = sha1(plain.getBytes(), salt, HASH_INTERATIONS);
        return encodeHex(salt) + encodeHex(hashPassword);
    }

    /**
     * 对比
     * @param plainPassword(明文密码)
     * 与
     * @param encryptedPassword(密文密码)
     */
    public static boolean comparePassword(String plainPassword,
            String encryptedPassword) {
        byte[] salt = decodeHex(encryptedPassword.substring(0, 16));
        String plain = unescapeHtml(plainPassword);
        byte[] hashPassword = sha1(plain.getBytes(), salt, HASH_INTERATIONS);
        if (encodeHex(hashPassword).equals(encryptedPassword.substring(16))) {
            return true;
        }
        return false;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        String plainPassword = "123456";
        String encryptedPassword = "ac2246ecf3b6ef595da8b0d0210a6239adbf7a93cf73f799dbadb744";
        // System.out.println(entryptPassword("123456"));
        System.out.println(comparePassword(plainPassword, encryptedPassword));
    }

    /**
     * Html 解码.
     */
    private static String unescapeHtml(String htmlEscaped) {
        return StringEscapeUtils.unescapeHtml4(htmlEscaped);
    }

    /**
     * 生成随机的Byte[]作为salt.
     * 
     * @param numBytes
     *            byte数组的大小
     */
    private static byte[] generateSalt(int numBytes) {
        Validate.isTrue(numBytes > 0,
                "numBytes argument must be a positive integer (1 or larger)",
                numBytes);

        byte[] bytes = new byte[numBytes];
        random.nextBytes(bytes);
        return bytes;
    }

    private static byte[] sha1(byte[] input, byte[] salt, int iterations) {
        return digest(input, SHA1, salt, iterations);
    }

    /**
     * 对字符串进行散列, 支持md5与sha1算法.
     */
    private static byte[] digest(byte[] input, String algorithm, byte[] salt,
            int iterations) {
        try {
            MessageDigest digest = MessageDigest.getInstance(algorithm);

            if (salt != null) {
                digest.update(salt);
            }

            byte[] result = digest.digest(input);

            for (int i = 1; i < iterations; i++) {
                digest.reset();
                result = digest.digest(result);
            }
            return result;
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Hex编码.
     */
    private static String encodeHex(byte[] input) {
        return new String(Hex.encodeHex(input));
    }

    /**
     * Hex解码.
     */
    private static byte[] decodeHex(String input) {
        try {
            return Hex.decodeHex(input.toCharArray());
        } catch (DecoderException e) {
            throw new RuntimeException(e);
        }
    }

}