in compute/src/main/java/org/jclouds/compute/functions/Sha512Crypt.java [141:320]
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; // Default number of rounds.
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);
/*
* Repeatedly run the collected hash value through SHA512 to burn CPU
* cycles.
*/
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));
/*
* Clear the buffer for the intermediate result so that people attaching
* to processes or reading core dumps cannot get any information.
*/
ctx.reset();
return buffer.toString();
}