package no.ntnu.item.cryptoutil; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import de.rtner.security.auth.spi.PBKDF2Engine; import de.rtner.security.auth.spi.PBKDF2Parameters; public class KeyChain { private String password; private byte[] salt; private SecretKey key; public static final int SALT_SIZE = Cryptoutil.SYM_SIZE; public static final String HASH_ALG = Cryptoutil.HMAC_ALG; public static final String RANDOM_GENERATOR = "SHA1PRNG"; public static final int ITERATION_COUNT = 4096; public static final String ENCODING = "UTF-8"; /** * Generate a new PBKDF2 key * * @param password */ public KeyChain(String password) { assert password != null; this.password = password; this.salt = new byte[SALT_SIZE / Byte.SIZE]; SecureRandom sr; try { sr = SecureRandom.getInstance(RANDOM_GENERATOR); sr.nextBytes(this.salt); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } common(); } /** * Generate existing PBKDF2 key * * @param password * @param salt */ public KeyChain(String password, byte[] salt) { assert salt != null; assert password != null; this.password = password; this.salt = salt; common(); } private void common() { PBKDF2Parameters param = new PBKDF2Parameters(HASH_ALG, ENCODING, this.salt, ITERATION_COUNT); PBKDF2Engine engine = new PBKDF2Engine(param); param.setDerivedKey(engine.deriveKey(password, (Cryptoutil.SYM_SIZE / Byte.SIZE))); byte tmp[] = param.getDerivedKey(); this.key = new SecretKeySpec(tmp, Cryptoutil.SYM_CIPHER); } public SecretKey getKey() { return this.key; } public String getPassword() { return this.password; } public byte[] getSalt() { return this.salt; } public int getIterations() { return ITERATION_COUNT; } }