package org.bouncycastle.jcajce.provider.symmetric; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import javax.crypto.SecretKey; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory; import org.bouncycastle.jcajce.provider.util.AlgorithmProvider; import org.bouncycastle.util.Strings; public final class OpenSSLPBKDF { private OpenSSLPBKDF() { } public static class PBKDF extends BaseSecretKeyFactory { public PBKDF() { super("PBKDF-OpenSSL", null); } protected SecretKey engineGenerateSecret( KeySpec keySpec) throws InvalidKeySpecException { if (keySpec instanceof PBEKeySpec) { PBEKeySpec pbeSpec = (PBEKeySpec)keySpec; if (pbeSpec.getSalt() == null) { throw new InvalidKeySpecException("missing required salt"); } if (pbeSpec.getIterationCount() <= 0) { throw new InvalidKeySpecException("positive iteration count required: " + pbeSpec.getIterationCount()); } if (pbeSpec.getKeyLength() <= 0) { throw new InvalidKeySpecException("positive key length required: " + pbeSpec.getKeyLength()); } if (pbeSpec.getPassword().length == 0) { throw new IllegalArgumentException("password empty"); } OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator(); pGen.init(Strings.toByteArray(pbeSpec.getPassword()), pbeSpec.getSalt()); return new SecretKeySpec(((KeyParameter)pGen.generateDerivedParameters(pbeSpec.getKeyLength())).getKey(), "OpenSSLPBKDF"); } throw new InvalidKeySpecException("Invalid KeySpec"); } } public static class Mappings extends AlgorithmProvider { private static final String PREFIX = OpenSSLPBKDF.class.getName(); public Mappings() { } public void configure(ConfigurableProvider provider) { provider.addAlgorithm("SecretKeyFactory.PBKDF-OPENSSL", PREFIX + "$PBKDF"); } } }