package com.saltedhashed.crypto;
import java.lang.reflect.Constructor;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKeyFactorySpi;
/**
* Additional PBKDF2 algorithms (With SHA-X)
*
* @author bozho
*
*/
public class PBKDF2Algorithms {
private static final Provider provider = Security.getProvider("SunJCE");
public static void initialize() {
provider.put("SecretKeyFactory.PBKDF2WithHmacSHA224", "com.saltedhashed.crypto.PBKDF2Core$HmacSHA224");
provider.put("SecretKeyFactory.PBKDF2WithHmacSHA256", "com.saltedhashed.crypto.PBKDF2Core$HmacSHA256");
provider.put("SecretKeyFactory.PBKDF2WithHmacSHA384", "com.saltedhashed.crypto.PBKDF2Core$HmacSHA384");
provider.put("SecretKeyFactory.PBKDF2WithHmacSHA512", "com.saltedhashed.crypto.PBKDF2Core$HmacSHA512");
}
/**
* Factory method to get the proper factory class. The SunJCE provider
* appears to have its own classloader so simply adding the values (as
* above) does not work and the classes are not found. Hence the reflection
* work below.
*
* @param algorithm
* @return
* @throws NoSuchAlgorithmException
*/
@SuppressWarnings("unchecked")
public static SecretKeyFactory getSecretKeyFactory(String algorithm) throws NoSuchAlgorithmException {
try {
Class<SecretKeyFactorySpi> clazz = (Class<SecretKeyFactorySpi>) Class.forName((String) provider.get("SecretKeyFactory." + algorithm));
SecretKeyFactorySpi spi = clazz.newInstance();
Constructor<SecretKeyFactory> c = SecretKeyFactory.class.getDeclaredConstructor(SecretKeyFactorySpi.class, Provider.class, String.class);
c.setAccessible(true);
return c.newInstance(spi, provider, algorithm);
} catch (Exception e) {
throw new NoSuchAlgorithmException(e);
}
}
}