jodd-core/src/main/java/jodd/crypt/BCrypt.java
public static String hashpw(String password, String salt) {
		BCrypt B;
		String real_salt;
		byte[] passwordb, saltb, hashed;
		char minor = (char) 0;
		int rounds, off;
		StringBuffer rs = new StringBuffer();

		if (salt.charAt(0) != '$' || salt.charAt(1) != '2') {
			throw new IllegalArgumentException("Invalid salt version");
		}
		if (salt.charAt(2) == '$') {
			off = 3;
		}
		else {
			minor = salt.charAt(2);
			if (minor != 'a' || salt.charAt(3) != '$') {
				throw new IllegalArgumentException("Invalid salt revision");
			}
			off = 4;
		}

		// Extract number of rounds
		if (salt.charAt(off + 2) > '$') {
			throw new IllegalArgumentException("Missing salt rounds");
		}
		rounds = Integer.parseInt(salt.substring(off, off + 2));

		real_salt = salt.substring(off + 3, off + 25);
		try {
			passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8");
		}
		catch (UnsupportedEncodingException uee) {
			throw new AssertionError("UTF-8 is not supported");
		}

		saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);

		B = new BCrypt();
		hashed = B.crypt_raw(passwordb, saltb, rounds,
				(int[]) bf_crypt_ciphertext.clone());

		rs.append("$2");
		if (minor >= 'a') {
			rs.append(minor);
		}
		rs.append('$');
		if (rounds < 10) {
			rs.append('0');
		}
		if (rounds > 30) {
			throw new IllegalArgumentException(
					"rounds exceeds maximum (30)");
		}
		rs.append(rounds)
				.append('$')
				.append(encode_base64(saltb, saltb.length))
				.append(encode_base64(hashed,
						bf_crypt_ciphertext.length * 4 - 1));
		return rs.toString();
	}
public static String hashpw(String password, String salt) {
		BCrypt B;
		String real_salt;
		byte[] passwordb, saltb, hashed;
		char minor = (char) 0;
		int rounds, off;
		StringBuffer rs = new StringBuffer();

		if (salt.charAt(0) != '$' || salt.charAt(1) != '2') {
			throw new IllegalArgumentException("Invalid salt version");
		}
		if (salt.charAt(2) == '$') {
			off = 3;
		}
		else {
			minor = salt.charAt(2);
			if (minor != 'a' || salt.charAt(3) != '$') {
				throw new IllegalArgumentException("Invalid salt revision");
			}
			off = 4;
		}

		// Extract number of rounds
		if (salt.charAt(off + 2) > '$') {
			throw new IllegalArgumentException("Missing salt rounds");
		}
		rounds = Integer.parseInt(salt.substring(off, off + 2));

		real_salt = salt.substring(off + 3, off + 25);
		try {
			passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8");
		}
		catch (UnsupportedEncodingException uee) {
			throw new AssertionError("UTF-8 is not supported");
		}

		saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);

		B = new BCrypt();
		hashed = B.crypt_raw(passwordb, saltb, rounds,
				(int[]) bf_crypt_ciphertext.clone());

		rs.append("$2");
		if (minor >= 'a') {
			rs.append(minor);
		}
		rs.append('$');
		if (rounds < 10) {
			rs.append('0');
		}
		if (rounds > 30) {
			throw new IllegalArgumentException(
					"rounds exceeds maximum (30)");
		}
		rs.append(rounds)
				.append('$')
				.append(encode_base64(saltb, saltb.length))
				.append(encode_base64(hashed,
						bf_crypt_ciphertext.length * 4 - 1));
		return rs.toString();
	}
Hash a password using the OpenBSD bcrypt scheme.

@param password the password to hash
@param salt the salt to hash with (perhaps generated
using BCrypt.gensalt)
@return the hashed password