Saturday, May 12, 2012
Surviving password changes with a Hash Chain
Sick and tired of having to create and memorize yet another new login password due to password expiry ? Here is an idea:
- Generate a random root password once, memorize and then destroy it
- Use a hash function (eg SHA-256) to recursively hash the root for N times, resulting in a list of hash values
H(root), H(H(root)), ...
- Every time you need a new password, pick a value from the list in the reverse order of
N, N-1, ...
- Encode (eg using ASCII-85) and truncate the value as necessary to become your new password
public class HashChainPassword {
private static SecureRandom rand = new SecureRandom();
private static Charset UTF8 = Charset.forName("UTF-8");
public static String generate(int length) {
byte[] ba = new byte[length];
rand.nextBytes(ba);
String a85 = Ascii85.encodeAsString(ba);
return a85.substring(0, length);
}
public static String nthPasswordOf(int n, String root)
throws NoSuchAlgorithmException
{
byte[] ba = root.getBytes(UTF8);
for (int i=0; i < n; i++) {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(ba);
ba = md.digest();
}
String a85 = Ascii85.encodeAsString(ba);
return a85.substring(0, root.length());
}
public static void main(String[] args) throws NoSuchAlgorithmException {
String root = HashChainPassword.generate(8);
System.out.println("Root password: " + root);
System.out.println("Password generation from 99th to 90th:\n");
for (int i=99; i >= 90; i--) {
String s = nthPasswordOf(i, root);
System.out.println(i +": " + s);
}
}
}
Sample Output:
Root password: H#C[Xe09 Password generation from 99th to 90th: 99: O9(kK*/l 98: NdPnLI\c 97: #.ZQ9lm& 96: KKK"`fW# 95: Wepl2msM 94: G#bitr\? 93: 0gR!CI9H 92: 9QQ#]Yn> 91: Nid.b4cg 90: WMI'e[\"