name.neuhalfen.projects.crypto.symmetric.keygeneration.impl.stretching.SCryptKeyStretching Maven / Gradle / Ivy
Show all versions of bouncy-gpg Show documentation
package name.neuhalfen.projects.crypto.symmetric.keygeneration.impl.stretching;
import java.io.Serializable;
import java.util.Objects;
import name.neuhalfen.projects.crypto.internal.Preconditions;
import org.bouncycastle.crypto.generators.SCrypt;
@SuppressWarnings({"PMD.ShortVariable", "PMD.VariableNamingConventions",
"PMD.FieldNamingConventions", "PMD.FormalParameterNamingConventions"})
public class SCryptKeyStretching implements KeyStretching {
private final SCryptKeyStretchingParameters cfg;
public SCryptKeyStretching(SCryptKeyStretchingParameters cfg) {
this.cfg = cfg;
}
public static SCryptKeyStretching forConfig(SCryptKeyStretchingParameters cfg) {
return new SCryptKeyStretching(cfg);
}
@Override
public byte[] strengthenKey(byte[] salt, byte[] keyToStrengthen, int desiredKeyLengthInBit) {
Preconditions.checkArgument(desiredKeyLengthInBit % 8 == 0,
"desiredKeyLengthInBits must be multiple of 8 but is " + desiredKeyLengthInBit);
final int desiredKeyLengthInBytes = desiredKeyLengthInBit / 8;
return SCrypt.generate(keyToStrengthen, salt, cfg.getN(), cfg.getR(), cfg.getP(),
desiredKeyLengthInBytes);
}
@SuppressWarnings({"PMD.ShortVariable", "PMD.VariableNamingConventions",
"PMD.FieldNamingConventions"})
public final static class SCryptKeyStretchingParameters implements Serializable {
private static final long serialVersionUID = 3949486467011133166L;
private final int N;
private final int r;
private final int p;
public SCryptKeyStretchingParameters(int N, int r, int p) {
this.N = N;
this.r = r;
this.p = p;
}
/**
* Generate a workload factor for sensitive ( ~5 seconds in 2017) derivation with very weak
* input key material.
*
* Examples would be user supplied passwords, etc.
*
* @return N:=2^20, r:=8, p:=1
*/
public static SCryptKeyStretchingParameters forWeakInputKeyMaterial() {
return new SCryptKeyStretchingParameters(1 << 20, 8, 1);
}
/**
* Generate a workload factor for quick (~10ms in 2017) derivation. You can use this if the
* secret has a very high entropy but is not perfect.
*
* @return N:=2^12, r:=4, p:=1
*/
public static SCryptKeyStretchingParameters forModeratelyStongInputKeyMaterial() {
return new SCryptKeyStretchingParameters(1 << 12, 4, 1);
}
/**
* Generate a workload factor for quickest (~1ms in 2017) derivation.
**Only use this if
* your input key material is very good**
*
* Candidates for good key material are * very long, random passwords (~22 chars for a 128 bit
* key) * passwords generated by e.g. a password manager
This brings effectively
* close-to-zero protection against brute force attacks.
*
* @return N:=2^8, r:=4, p:=1
*/
public static SCryptKeyStretchingParameters forStrongInputKeyMaterial() {
return new SCryptKeyStretchingParameters(1 << 8, 4, 1);
}
public int getN() {
return N;
}
public int getR() {
return r;
}
public int getP() {
return p;
}
@SuppressWarnings("PMD.OnlyOneReturn")
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final SCryptKeyStretchingParameters that = (SCryptKeyStretchingParameters) o;
return N == that.N &&
r == that.r &&
p == that.p;
}
@Override
public int hashCode() {
return Objects.hash(N, r, p);
}
@Override
public String toString() {
return "PBKDF2KeyStretchingParameters{"
+ "N=" + N
+ ", r=" + r
+ ", p=" + p
+ '}';
}
}
}