package kr.co.gt1000.security; import java.security.SecureRandom; import java.util.Base64; public class BCryptSalt { private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10; private static final int BCRYPT_SALT_LEN = 16; static private final char base64_code[] = { '.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; /** * BCrypt * Generate a salt for use with the BCrypt.hashpw() method, selecting a reasonable * default for the number of hashing rounds to apply * @return an encoded salt value */ public static String gensalt() { return gensalt(GENSALT_DEFAULT_LOG2_ROUNDS); } /** * BCrypt * Generate a salt for use with the BCrypt.hashpw() method * @param log_rounds the log2 of the number of rounds of hashing to apply - the work * factor therefore increases as 2**log_rounds. * @return an encoded salt value */ public static String gensalt(int log_rounds) { return gensalt(log_rounds, new SecureRandom()); } /** * BCrypt * Generate a salt for use with the BCrypt.hashpw() method * @param log_rounds the log2 of the number of rounds of hashing to apply - the work * factor therefore increases as 2**log_rounds. * @param random an instance of SecureRandom to use * @return an encoded salt value */ public static String gensalt(int log_rounds, SecureRandom random) { if (log_rounds < 4 || log_rounds > 31) { throw new IllegalArgumentException("Bad number of rounds"); } StringBuilder rs = new StringBuilder(); byte rnd[] = new byte[BCRYPT_SALT_LEN]; random.nextBytes(rnd); rs.append("$2a$"); if (log_rounds < 10) { rs.append("0"); } rs.append(log_rounds); rs.append("$"); encode_base64(rnd, rnd.length, rs); return rs.toString(); } /** * Encode a byte array using bcrypt's slightly-modified base64 encoding scheme. Note * that this is not compatible with the standard MIME-base64 * encoding. * * @param d the byte array to encode * @param len the number of bytes to encode * @param rs the destination buffer for the base64-encoded string * @exception IllegalArgumentException if the length is invalid */ static void encode_base64(byte d[], int len, StringBuilder rs) throws IllegalArgumentException { int off = 0; int c1, c2; if (len <= 0 || len > d.length) { throw new IllegalArgumentException("Invalid len"); } while (off < len) { c1 = d[off++] & 0xff; rs.append(base64_code[(c1 >> 2) & 0x3f]); c1 = (c1 & 0x03) << 4; if (off >= len) { rs.append(base64_code[c1 & 0x3f]); break; } c2 = d[off++] & 0xff; c1 |= (c2 >> 4) & 0x0f; rs.append(base64_code[c1 & 0x3f]); c1 = (c2 & 0x0f) << 2; if (off >= len) { rs.append(base64_code[c1 & 0x3f]); break; } c2 = d[off++] & 0xff; c1 |= (c2 >> 6) & 0x03; rs.append(base64_code[c1 & 0x3f]); rs.append(base64_code[c2 & 0x3f]); } } // /** // * SALT 생성 // * @return // */ // public static String getSalt() { // String value = ""; // try { // SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); // // Salt generation 128 bits long // byte[] salt = new byte[16]; // secureRandom.nextBytes(salt); // byte[] encoded = Base64.getEncoder().encode(salt); // return new String(encoded); // } catch(Exception e) { // e.printStackTrace(); // } // return value; // } }