org.bouncycastle.crypto.fips.FipsPBKD Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bc-fips-debug Show documentation
Show all versions of bc-fips-debug Show documentation
The FIPS 140-2 Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms certified to FIPS 140-2 level 1. This jar contains the debug version JCE provider and low-level API for the BC-FJA version 1.0.2.3, FIPS Certificate #3514. Please note the debug jar is not certified.
package org.bouncycastle.crypto.fips;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.PasswordBasedDeriver;
import org.bouncycastle.crypto.PasswordConverter;
import org.bouncycastle.crypto.internal.PBEParametersGenerator;
import org.bouncycastle.crypto.internal.test.BasicKatTest;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;
/**
* Source class for FIPS approved implementations of Password-Based Key Derivation algorithms.
*/
public final class FipsPBKD
{
/**
* Algorithm ID for PBKDF2 (PKCS#5 scheme 2)
*/
private static final FipsAlgorithm ALGORITHM_PBKDF2 = new FipsAlgorithm("PBKDF2");
static
{
// FSM_STATE:5.PBKDF.0,"PBKDF GENERATE KAT","The module is performing PBKDF generate KAT self-test"
// FSM_TRANS:5.PBKDF.0.0,"CONDITIONAL TEST","PBKDF GENERATE KAT","Invoke PBKDF Generate KAT self-test"
Parameters parameters = new ParametersBuilder().using(FipsSHS.Algorithm.SHA256_HMAC, Strings.toByteArray("Legion of the Bouncy Castle"))
.withIterationCount(2048).withSalt(Hex.decode("0102030405060708090a0b0c0e0d0e0f"));
PKCS5S2ParametersGenerator engine = new PKCS5S2ParametersGenerator(
parameters,
FipsSHS.createHMac(FipsSHS.Algorithm.SHA256_HMAC));
// As per IG 10.3.A
SelfTestExecutor.validate(ALGORITHM_PBKDF2, engine,
new PbkdfTest>(parameters, Hex.decode("fb18073c0bc900343ad8280821938255")));
// FSM_TRANS:5.PBKDF.0.1,"PBKDF GENERATE KAT","CONDITIONAL TEST","PBKDF Generate KAT self-test successful completion"
// FSM_TRANS:5.PBKDF.0.2,"PBKDF GENERATE KAT","SOFT ERROR","PBKDF Generate KAT self-test failed"
}
/**
* PBKDF2 algorithm parameter source - default PRF is HMAC(SHA-1)
*/
public static final ParametersBuilder PBKDF2 = new ParametersBuilder();
private FipsPBKD()
{
}
/**
* Initial builder for PBKDF2 parameters.
*/
public static final class ParametersBuilder
extends FipsParameters
{
ParametersBuilder()
{
super(ALGORITHM_PBKDF2);
}
public Parameters using(byte[] password)
{
return using(FipsSHS.Algorithm.SHA1_HMAC, password);
}
public Parameters using(FipsDigestAlgorithm algorithm, byte[] password)
{
return new Parameters(algorithm, null, Arrays.clone(password), 1024, new byte[20]);
}
public Parameters using(PasswordConverter converter, char[] password)
{
return new Parameters(FipsSHS.Algorithm.SHA1_HMAC, converter, password);
}
public Parameters using(FipsDigestAlgorithm algorithm, PasswordConverter converter, char[] password)
{
return new Parameters(algorithm, converter, converter.convert(password), 1024, new byte[20]);
}
}
/**
* PBKD parameters.
*/
public static final class Parameters
extends FipsParameters
{
private final FipsDigestAlgorithm digestAlgorithm;
private final PasswordConverter converter;
private final byte[] password;
private final byte[] salt;
private final int iterationCount;
private Parameters(FipsDigestAlgorithm digestAlgorithm, PasswordConverter converter, byte[] password, int iterationCount, byte[] salt)
{
super(ALGORITHM_PBKDF2);
this.digestAlgorithm = digestAlgorithm;
this.converter = converter;
this.password = password;
this.iterationCount = iterationCount;
this.salt = salt;
if (CryptoServicesRegistrar.isInApprovedOnlyMode())
{
if (salt.length < 16)
{
throw new FipsUnapprovedOperationError("salt must be at least 128 bits");
}
if (password.length < 14)
{
throw new FipsUnapprovedOperationError("password must be at least 112 bits");
}
}
}
private Parameters(FipsDigestAlgorithm algorithm, PasswordConverter converter, char[] password)
{
this(algorithm, converter, converter.convert(password), 1024, new byte[20]);
}
public Parameters withSalt(byte[] salt)
{ // need copy of password as zeroize on finalisation
return new Parameters(digestAlgorithm, converter, getPassword(), iterationCount, Arrays.clone(salt));
}
public Parameters withIterationCount(int iterationCount)
{ // need copy of password as zeroize on finalisation
return new Parameters(digestAlgorithm, converter, getPassword(), iterationCount, salt);
}
synchronized byte[] getPassword()
{
return Arrays.clone(password); // to protect against premature finalization
}
public FipsDigestAlgorithm getPRF()
{
return digestAlgorithm;
}
public byte[] getSalt()
{
return Arrays.clone(salt);
}
public int getIterationCount()
{
return iterationCount;
}
public PasswordConverter getConverter()
{
return converter;
}
protected void finalize()
{
synchronized (this)
{
// explicitly zeroize password on deallocation
Arrays.fill(password, (byte)0);
}
}
}
/**
* Factory for password based key derivation functions that are based on PBKDF2 (PKCS#5 scheme 2).
*/
public static class DeriverFactory
extends FipsPasswordBasedDeriverFactory
{
public PasswordBasedDeriver createDeriver(final Parameters parameters)
{
final PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(parameters, FipsSHS.createHMac(parameters.getPRF()));
gen.init(parameters.getPassword(), parameters.getSalt(), parameters.getIterationCount());
return new PasswordBasedDeriver()
{
public Parameters getParameters()
{
return parameters;
}
public byte[] deriveKey(KeyType keyType, int keySizeInBytes)
{
return gen.deriveKey(keyType, keySizeInBytes);
}
public byte[][] deriveKeyAndIV(KeyType keyType, int keySizeInBytes, int ivSizeInBytes)
{
return gen.deriveKeyAndIV(keyType, keySizeInBytes, ivSizeInBytes);
}
};
}
}
private static class PbkdfTest>
implements BasicKatTest
{
private final Parameters params;
private final byte[] kat;
PbkdfTest(Parameters params, byte[] kat)
{
this.params = params;
this.kat = kat;
}
public boolean hasTestPassed(T generator)
{
generator.init(params.password, params.salt, params.iterationCount);
byte[] result = generator.deriveKey(PasswordBasedDeriver.KeyType.CIPHER, 16);
return Arrays.areEqual(result, kat);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy