@Test(dataProvider = "data") public void testMakeCryptedPasswordHash(String password, String salt, String expected) { assertEquals(Sha512Crypt.makeShadowLine(password, salt), expected); }
static String makeShadowLine(String password, @Nullable String shadowPrefix) { MessageDigest ctx = sha512(); MessageDigest alt_ctx = sha512(); byte[] alt_result; byte[] temp_result; byte[] p_bytes = null; byte[] s_bytes = null; int cnt; int cnt2; int rounds = ROUNDS_DEFAULT; StringBuilder buffer; if (shadowPrefix != null) { if (shadowPrefix.startsWith(sha512_salt_prefix)) { shadowPrefix = shadowPrefix.substring(sha512_salt_prefix.length()); } if (shadowPrefix.startsWith(sha512_rounds_prefix)) { String num = shadowPrefix.substring(sha512_rounds_prefix.length(), shadowPrefix.indexOf('$')); int srounds = Integer.parseInt(num); shadowPrefix = shadowPrefix.substring(shadowPrefix.indexOf('$') + 1); rounds = Math.max(ROUNDS_MIN, Math.min(srounds, ROUNDS_MAX)); } if (shadowPrefix.length() > SALT_LEN_MAX) { shadowPrefix = shadowPrefix.substring(0, SALT_LEN_MAX); } } else { java.util.Random randgen = new java.security.SecureRandom(); StringBuilder saltBuf = new StringBuilder(); while (saltBuf.length() < 16) { int index = (int) (randgen.nextFloat() * SALTCHARS.length()); saltBuf.append(SALTCHARS, index, index + 1); } shadowPrefix = saltBuf.toString(); } byte[] key = password.getBytes(); byte[] salts = shadowPrefix.getBytes(); ctx.reset(); ctx.update(key, 0, key.length); ctx.update(salts, 0, salts.length); alt_ctx.reset(); alt_ctx.update(key, 0, key.length); alt_ctx.update(salts, 0, salts.length); alt_ctx.update(key, 0, key.length); alt_result = alt_ctx.digest(); for (cnt = key.length; cnt > 64; cnt -= 64) { ctx.update(alt_result, 0, 64); } ctx.update(alt_result, 0, cnt); for (cnt = key.length; cnt > 0; cnt >>= 1) { if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(key, 0, key.length); } } alt_result = ctx.digest(); alt_ctx.reset(); for (cnt = 0; cnt < key.length; ++cnt) { alt_ctx.update(key, 0, key.length); } temp_result = alt_ctx.digest(); p_bytes = new byte[key.length]; for (cnt2 = 0, cnt = p_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, p_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, p_bytes, cnt2, cnt); alt_ctx.reset(); for (cnt = 0; cnt < 16 + (alt_result[0] & 0xFF); ++cnt) { alt_ctx.update(salts, 0, salts.length); } temp_result = alt_ctx.digest(); s_bytes = new byte[salts.length]; for (cnt2 = 0, cnt = s_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, s_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, s_bytes, cnt2, cnt); for (cnt = 0; cnt < rounds; ++cnt) { ctx.reset(); if ((cnt & 1) != 0) { ctx.update(p_bytes, 0, key.length); } else { ctx.update(alt_result, 0, 64); } if (cnt % 3 != 0) { ctx.update(s_bytes, 0, salts.length); } if (cnt % 7 != 0) { ctx.update(p_bytes, 0, key.length); } if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(p_bytes, 0, key.length); } alt_result = ctx.digest(); } buffer = new StringBuilder(sha512_salt_prefix); if (rounds != 5000) { buffer.append(sha512_rounds_prefix); buffer.append(rounds); buffer.append("$"); } buffer.append(shadowPrefix); buffer.append("$"); buffer.append(b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4)); buffer.append(b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4)); buffer.append(b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4)); buffer.append(b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4)); buffer.append(b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4)); buffer.append(b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4)); buffer.append(b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4)); buffer.append(b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4)); buffer.append(b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4)); buffer.append(b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4)); buffer.append(b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4)); buffer.append(b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4)); buffer.append(b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4)); buffer.append(b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4)); buffer.append(b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4)); buffer.append(b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4)); buffer.append(b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4)); buffer.append(b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4)); buffer.append(b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4)); buffer.append(b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4)); buffer.append(b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4)); buffer.append(b64_from_24bit((byte) 0x00, (byte) 0x00, alt_result[63], 2)); ctx.reset(); return buffer.toString(); }
Sha512Crypt { static String makeShadowLine(String password, @Nullable String shadowPrefix) { MessageDigest ctx = sha512(); MessageDigest alt_ctx = sha512(); byte[] alt_result; byte[] temp_result; byte[] p_bytes = null; byte[] s_bytes = null; int cnt; int cnt2; int rounds = ROUNDS_DEFAULT; StringBuilder buffer; if (shadowPrefix != null) { if (shadowPrefix.startsWith(sha512_salt_prefix)) { shadowPrefix = shadowPrefix.substring(sha512_salt_prefix.length()); } if (shadowPrefix.startsWith(sha512_rounds_prefix)) { String num = shadowPrefix.substring(sha512_rounds_prefix.length(), shadowPrefix.indexOf('$')); int srounds = Integer.parseInt(num); shadowPrefix = shadowPrefix.substring(shadowPrefix.indexOf('$') + 1); rounds = Math.max(ROUNDS_MIN, Math.min(srounds, ROUNDS_MAX)); } if (shadowPrefix.length() > SALT_LEN_MAX) { shadowPrefix = shadowPrefix.substring(0, SALT_LEN_MAX); } } else { java.util.Random randgen = new java.security.SecureRandom(); StringBuilder saltBuf = new StringBuilder(); while (saltBuf.length() < 16) { int index = (int) (randgen.nextFloat() * SALTCHARS.length()); saltBuf.append(SALTCHARS, index, index + 1); } shadowPrefix = saltBuf.toString(); } byte[] key = password.getBytes(); byte[] salts = shadowPrefix.getBytes(); ctx.reset(); ctx.update(key, 0, key.length); ctx.update(salts, 0, salts.length); alt_ctx.reset(); alt_ctx.update(key, 0, key.length); alt_ctx.update(salts, 0, salts.length); alt_ctx.update(key, 0, key.length); alt_result = alt_ctx.digest(); for (cnt = key.length; cnt > 64; cnt -= 64) { ctx.update(alt_result, 0, 64); } ctx.update(alt_result, 0, cnt); for (cnt = key.length; cnt > 0; cnt >>= 1) { if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(key, 0, key.length); } } alt_result = ctx.digest(); alt_ctx.reset(); for (cnt = 0; cnt < key.length; ++cnt) { alt_ctx.update(key, 0, key.length); } temp_result = alt_ctx.digest(); p_bytes = new byte[key.length]; for (cnt2 = 0, cnt = p_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, p_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, p_bytes, cnt2, cnt); alt_ctx.reset(); for (cnt = 0; cnt < 16 + (alt_result[0] & 0xFF); ++cnt) { alt_ctx.update(salts, 0, salts.length); } temp_result = alt_ctx.digest(); s_bytes = new byte[salts.length]; for (cnt2 = 0, cnt = s_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, s_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, s_bytes, cnt2, cnt); for (cnt = 0; cnt < rounds; ++cnt) { ctx.reset(); if ((cnt & 1) != 0) { ctx.update(p_bytes, 0, key.length); } else { ctx.update(alt_result, 0, 64); } if (cnt % 3 != 0) { ctx.update(s_bytes, 0, salts.length); } if (cnt % 7 != 0) { ctx.update(p_bytes, 0, key.length); } if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(p_bytes, 0, key.length); } alt_result = ctx.digest(); } buffer = new StringBuilder(sha512_salt_prefix); if (rounds != 5000) { buffer.append(sha512_rounds_prefix); buffer.append(rounds); buffer.append("$"); } buffer.append(shadowPrefix); buffer.append("$"); buffer.append(b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4)); buffer.append(b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4)); buffer.append(b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4)); buffer.append(b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4)); buffer.append(b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4)); buffer.append(b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4)); buffer.append(b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4)); buffer.append(b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4)); buffer.append(b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4)); buffer.append(b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4)); buffer.append(b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4)); buffer.append(b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4)); buffer.append(b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4)); buffer.append(b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4)); buffer.append(b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4)); buffer.append(b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4)); buffer.append(b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4)); buffer.append(b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4)); buffer.append(b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4)); buffer.append(b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4)); buffer.append(b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4)); buffer.append(b64_from_24bit((byte) 0x00, (byte) 0x00, alt_result[63], 2)); ctx.reset(); return buffer.toString(); } }
Sha512Crypt { static String makeShadowLine(String password, @Nullable String shadowPrefix) { MessageDigest ctx = sha512(); MessageDigest alt_ctx = sha512(); byte[] alt_result; byte[] temp_result; byte[] p_bytes = null; byte[] s_bytes = null; int cnt; int cnt2; int rounds = ROUNDS_DEFAULT; StringBuilder buffer; if (shadowPrefix != null) { if (shadowPrefix.startsWith(sha512_salt_prefix)) { shadowPrefix = shadowPrefix.substring(sha512_salt_prefix.length()); } if (shadowPrefix.startsWith(sha512_rounds_prefix)) { String num = shadowPrefix.substring(sha512_rounds_prefix.length(), shadowPrefix.indexOf('$')); int srounds = Integer.parseInt(num); shadowPrefix = shadowPrefix.substring(shadowPrefix.indexOf('$') + 1); rounds = Math.max(ROUNDS_MIN, Math.min(srounds, ROUNDS_MAX)); } if (shadowPrefix.length() > SALT_LEN_MAX) { shadowPrefix = shadowPrefix.substring(0, SALT_LEN_MAX); } } else { java.util.Random randgen = new java.security.SecureRandom(); StringBuilder saltBuf = new StringBuilder(); while (saltBuf.length() < 16) { int index = (int) (randgen.nextFloat() * SALTCHARS.length()); saltBuf.append(SALTCHARS, index, index + 1); } shadowPrefix = saltBuf.toString(); } byte[] key = password.getBytes(); byte[] salts = shadowPrefix.getBytes(); ctx.reset(); ctx.update(key, 0, key.length); ctx.update(salts, 0, salts.length); alt_ctx.reset(); alt_ctx.update(key, 0, key.length); alt_ctx.update(salts, 0, salts.length); alt_ctx.update(key, 0, key.length); alt_result = alt_ctx.digest(); for (cnt = key.length; cnt > 64; cnt -= 64) { ctx.update(alt_result, 0, 64); } ctx.update(alt_result, 0, cnt); for (cnt = key.length; cnt > 0; cnt >>= 1) { if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(key, 0, key.length); } } alt_result = ctx.digest(); alt_ctx.reset(); for (cnt = 0; cnt < key.length; ++cnt) { alt_ctx.update(key, 0, key.length); } temp_result = alt_ctx.digest(); p_bytes = new byte[key.length]; for (cnt2 = 0, cnt = p_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, p_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, p_bytes, cnt2, cnt); alt_ctx.reset(); for (cnt = 0; cnt < 16 + (alt_result[0] & 0xFF); ++cnt) { alt_ctx.update(salts, 0, salts.length); } temp_result = alt_ctx.digest(); s_bytes = new byte[salts.length]; for (cnt2 = 0, cnt = s_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, s_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, s_bytes, cnt2, cnt); for (cnt = 0; cnt < rounds; ++cnt) { ctx.reset(); if ((cnt & 1) != 0) { ctx.update(p_bytes, 0, key.length); } else { ctx.update(alt_result, 0, 64); } if (cnt % 3 != 0) { ctx.update(s_bytes, 0, salts.length); } if (cnt % 7 != 0) { ctx.update(p_bytes, 0, key.length); } if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(p_bytes, 0, key.length); } alt_result = ctx.digest(); } buffer = new StringBuilder(sha512_salt_prefix); if (rounds != 5000) { buffer.append(sha512_rounds_prefix); buffer.append(rounds); buffer.append("$"); } buffer.append(shadowPrefix); buffer.append("$"); buffer.append(b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4)); buffer.append(b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4)); buffer.append(b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4)); buffer.append(b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4)); buffer.append(b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4)); buffer.append(b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4)); buffer.append(b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4)); buffer.append(b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4)); buffer.append(b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4)); buffer.append(b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4)); buffer.append(b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4)); buffer.append(b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4)); buffer.append(b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4)); buffer.append(b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4)); buffer.append(b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4)); buffer.append(b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4)); buffer.append(b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4)); buffer.append(b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4)); buffer.append(b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4)); buffer.append(b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4)); buffer.append(b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4)); buffer.append(b64_from_24bit((byte) 0x00, (byte) 0x00, alt_result[63], 2)); ctx.reset(); return buffer.toString(); }  }
Sha512Crypt { static String makeShadowLine(String password, @Nullable String shadowPrefix) { MessageDigest ctx = sha512(); MessageDigest alt_ctx = sha512(); byte[] alt_result; byte[] temp_result; byte[] p_bytes = null; byte[] s_bytes = null; int cnt; int cnt2; int rounds = ROUNDS_DEFAULT; StringBuilder buffer; if (shadowPrefix != null) { if (shadowPrefix.startsWith(sha512_salt_prefix)) { shadowPrefix = shadowPrefix.substring(sha512_salt_prefix.length()); } if (shadowPrefix.startsWith(sha512_rounds_prefix)) { String num = shadowPrefix.substring(sha512_rounds_prefix.length(), shadowPrefix.indexOf('$')); int srounds = Integer.parseInt(num); shadowPrefix = shadowPrefix.substring(shadowPrefix.indexOf('$') + 1); rounds = Math.max(ROUNDS_MIN, Math.min(srounds, ROUNDS_MAX)); } if (shadowPrefix.length() > SALT_LEN_MAX) { shadowPrefix = shadowPrefix.substring(0, SALT_LEN_MAX); } } else { java.util.Random randgen = new java.security.SecureRandom(); StringBuilder saltBuf = new StringBuilder(); while (saltBuf.length() < 16) { int index = (int) (randgen.nextFloat() * SALTCHARS.length()); saltBuf.append(SALTCHARS, index, index + 1); } shadowPrefix = saltBuf.toString(); } byte[] key = password.getBytes(); byte[] salts = shadowPrefix.getBytes(); ctx.reset(); ctx.update(key, 0, key.length); ctx.update(salts, 0, salts.length); alt_ctx.reset(); alt_ctx.update(key, 0, key.length); alt_ctx.update(salts, 0, salts.length); alt_ctx.update(key, 0, key.length); alt_result = alt_ctx.digest(); for (cnt = key.length; cnt > 64; cnt -= 64) { ctx.update(alt_result, 0, 64); } ctx.update(alt_result, 0, cnt); for (cnt = key.length; cnt > 0; cnt >>= 1) { if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(key, 0, key.length); } } alt_result = ctx.digest(); alt_ctx.reset(); for (cnt = 0; cnt < key.length; ++cnt) { alt_ctx.update(key, 0, key.length); } temp_result = alt_ctx.digest(); p_bytes = new byte[key.length]; for (cnt2 = 0, cnt = p_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, p_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, p_bytes, cnt2, cnt); alt_ctx.reset(); for (cnt = 0; cnt < 16 + (alt_result[0] & 0xFF); ++cnt) { alt_ctx.update(salts, 0, salts.length); } temp_result = alt_ctx.digest(); s_bytes = new byte[salts.length]; for (cnt2 = 0, cnt = s_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, s_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, s_bytes, cnt2, cnt); for (cnt = 0; cnt < rounds; ++cnt) { ctx.reset(); if ((cnt & 1) != 0) { ctx.update(p_bytes, 0, key.length); } else { ctx.update(alt_result, 0, 64); } if (cnt % 3 != 0) { ctx.update(s_bytes, 0, salts.length); } if (cnt % 7 != 0) { ctx.update(p_bytes, 0, key.length); } if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(p_bytes, 0, key.length); } alt_result = ctx.digest(); } buffer = new StringBuilder(sha512_salt_prefix); if (rounds != 5000) { buffer.append(sha512_rounds_prefix); buffer.append(rounds); buffer.append("$"); } buffer.append(shadowPrefix); buffer.append("$"); buffer.append(b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4)); buffer.append(b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4)); buffer.append(b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4)); buffer.append(b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4)); buffer.append(b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4)); buffer.append(b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4)); buffer.append(b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4)); buffer.append(b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4)); buffer.append(b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4)); buffer.append(b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4)); buffer.append(b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4)); buffer.append(b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4)); buffer.append(b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4)); buffer.append(b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4)); buffer.append(b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4)); buffer.append(b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4)); buffer.append(b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4)); buffer.append(b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4)); buffer.append(b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4)); buffer.append(b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4)); buffer.append(b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4)); buffer.append(b64_from_24bit((byte) 0x00, (byte) 0x00, alt_result[63], 2)); ctx.reset(); return buffer.toString(); }  static com.google.common.base.Function<String, String> function(); }
Sha512Crypt { static String makeShadowLine(String password, @Nullable String shadowPrefix) { MessageDigest ctx = sha512(); MessageDigest alt_ctx = sha512(); byte[] alt_result; byte[] temp_result; byte[] p_bytes = null; byte[] s_bytes = null; int cnt; int cnt2; int rounds = ROUNDS_DEFAULT; StringBuilder buffer; if (shadowPrefix != null) { if (shadowPrefix.startsWith(sha512_salt_prefix)) { shadowPrefix = shadowPrefix.substring(sha512_salt_prefix.length()); } if (shadowPrefix.startsWith(sha512_rounds_prefix)) { String num = shadowPrefix.substring(sha512_rounds_prefix.length(), shadowPrefix.indexOf('$')); int srounds = Integer.parseInt(num); shadowPrefix = shadowPrefix.substring(shadowPrefix.indexOf('$') + 1); rounds = Math.max(ROUNDS_MIN, Math.min(srounds, ROUNDS_MAX)); } if (shadowPrefix.length() > SALT_LEN_MAX) { shadowPrefix = shadowPrefix.substring(0, SALT_LEN_MAX); } } else { java.util.Random randgen = new java.security.SecureRandom(); StringBuilder saltBuf = new StringBuilder(); while (saltBuf.length() < 16) { int index = (int) (randgen.nextFloat() * SALTCHARS.length()); saltBuf.append(SALTCHARS, index, index + 1); } shadowPrefix = saltBuf.toString(); } byte[] key = password.getBytes(); byte[] salts = shadowPrefix.getBytes(); ctx.reset(); ctx.update(key, 0, key.length); ctx.update(salts, 0, salts.length); alt_ctx.reset(); alt_ctx.update(key, 0, key.length); alt_ctx.update(salts, 0, salts.length); alt_ctx.update(key, 0, key.length); alt_result = alt_ctx.digest(); for (cnt = key.length; cnt > 64; cnt -= 64) { ctx.update(alt_result, 0, 64); } ctx.update(alt_result, 0, cnt); for (cnt = key.length; cnt > 0; cnt >>= 1) { if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(key, 0, key.length); } } alt_result = ctx.digest(); alt_ctx.reset(); for (cnt = 0; cnt < key.length; ++cnt) { alt_ctx.update(key, 0, key.length); } temp_result = alt_ctx.digest(); p_bytes = new byte[key.length]; for (cnt2 = 0, cnt = p_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, p_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, p_bytes, cnt2, cnt); alt_ctx.reset(); for (cnt = 0; cnt < 16 + (alt_result[0] & 0xFF); ++cnt) { alt_ctx.update(salts, 0, salts.length); } temp_result = alt_ctx.digest(); s_bytes = new byte[salts.length]; for (cnt2 = 0, cnt = s_bytes.length; cnt >= 64; cnt -= 64) { System.arraycopy(temp_result, 0, s_bytes, cnt2, 64); cnt2 += 64; } System.arraycopy(temp_result, 0, s_bytes, cnt2, cnt); for (cnt = 0; cnt < rounds; ++cnt) { ctx.reset(); if ((cnt & 1) != 0) { ctx.update(p_bytes, 0, key.length); } else { ctx.update(alt_result, 0, 64); } if (cnt % 3 != 0) { ctx.update(s_bytes, 0, salts.length); } if (cnt % 7 != 0) { ctx.update(p_bytes, 0, key.length); } if ((cnt & 1) != 0) { ctx.update(alt_result, 0, 64); } else { ctx.update(p_bytes, 0, key.length); } alt_result = ctx.digest(); } buffer = new StringBuilder(sha512_salt_prefix); if (rounds != 5000) { buffer.append(sha512_rounds_prefix); buffer.append(rounds); buffer.append("$"); } buffer.append(shadowPrefix); buffer.append("$"); buffer.append(b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4)); buffer.append(b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4)); buffer.append(b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4)); buffer.append(b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4)); buffer.append(b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4)); buffer.append(b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4)); buffer.append(b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4)); buffer.append(b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4)); buffer.append(b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4)); buffer.append(b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4)); buffer.append(b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4)); buffer.append(b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4)); buffer.append(b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4)); buffer.append(b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4)); buffer.append(b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4)); buffer.append(b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4)); buffer.append(b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4)); buffer.append(b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4)); buffer.append(b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4)); buffer.append(b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4)); buffer.append(b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4)); buffer.append(b64_from_24bit((byte) 0x00, (byte) 0x00, alt_result[63], 2)); ctx.reset(); return buffer.toString(); }  static com.google.common.base.Function<String, String> function();  }