package de.pinyto.ctSESAM; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.util.List; /** * This class handles the hashing and the creation of passwords. Please initialize first. * Do not forget to hash at least once because otherwise the password might look not very * random. It is safe to hash often because an attacker has to hash as often as you did for * every try of a brute-force attack. getPassword creates a password string out of the hash * digest. */ public class PasswordGenerator { private byte[] hashValue; public PasswordGenerator(byte[] domain, byte[] username, byte[] kgk, byte[] salt, int iterations) throws NotHashedException { byte[] startValue = new byte[domain.length + username.length + kgk.length]; int i = 0; while (i < domain.length) { startValue[i] = domain[i]; i++; } while (i < domain.length + username.length) { startValue[i] = username[i - domain.length]; i++; } while (i < domain.length + username.length + kgk.length) { startValue[i] = kgk[i - domain.length - username.length]; i++; } if (iterations <= 0) { throw new NotHashedException(Integer.toString(iterations) + " iterations means the password is not hashed at all."); } this.hashValue = PBKDF2.hmac("SHA512", startValue, salt, iterations); Clearer.zero(startValue); } public String getPassword(PasswordSetting setting) { byte[] positiveHashValue = new byte[hashValue.length + 1]; positiveHashValue[0] = 0; System.arraycopy(hashValue, 0, positiveHashValue, 1, hashValue.length); BigInteger hashNumber = new BigInteger(positiveHashValue); Clearer.zero(positiveHashValue); String password = ""; List<String> characterSet = setting.getCharacterSet(); List<String> digitsSet = setting.getDigitsCharacterSet(); List<String> lowerSet = setting.getLowerCaseLettersCharacterSet(); List<String> upperSet = setting.getUpperCaseLettersCharacterSet(); List<String> extraSet = setting.getExtraCharacterSet(); if (characterSet.size() > 0) { String template = setting.getTemplate(); for (int i = 0; i < template.length(); i++) { if (hashNumber.compareTo(BigInteger.ZERO) > 0) { List<String> set = characterSet; if (template.charAt(i) == 'a') { set = lowerSet; } else if (template.charAt(i) == 'A') { set = upperSet; } else if (template.charAt(i) == 'n') { set = digitsSet; } else if (template.charAt(i) == 'o') { set = extraSet; } else if (template.charAt(i) == 'x') { set = characterSet; } BigInteger setSize = BigInteger.valueOf(set.size()); BigInteger[] divAndMod = hashNumber.divideAndRemainder(setSize); hashNumber = divAndMod[0]; int mod = divAndMod[1].intValue(); password += set.get(mod); } } } return password; } protected void finalize() throws Throwable { Clearer.zero(this.hashValue); super.finalize(); } }