Add `KdfCalculator` class
parent
d3c51b26e8
commit
d234f6a66d
|
@ -0,0 +1,56 @@
|
|||
package org.sufficientlysecure.keychain.securitytoken;
|
||||
|
||||
import org.bouncycastle.crypto.Digest;
|
||||
import org.bouncycastle.crypto.digests.SHA256Digest;
|
||||
import org.bouncycastle.crypto.digests.SHA512Digest;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
// References:
|
||||
// [0] RFC 4880 `OpenPGP Message Format`
|
||||
class KdfCalculator {
|
||||
public static class KdfCalculatorArguments {
|
||||
public KdfParameters.HashType digestAlgorithm;
|
||||
public byte[] salt;
|
||||
public int iterations;
|
||||
}
|
||||
|
||||
public static byte[] calculateKdf(KdfCalculatorArguments kdfCalculatorArguments, byte[] pin) {
|
||||
Digest digester;
|
||||
switch (kdfCalculatorArguments.digestAlgorithm) {
|
||||
case SHA256:
|
||||
digester = new SHA256Digest();
|
||||
break;
|
||||
case SHA512:
|
||||
digester = new SHA512Digest();
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown hash algorithm!");
|
||||
}
|
||||
byte[] salt = kdfCalculatorArguments.salt;
|
||||
int iterations = kdfCalculatorArguments.iterations;
|
||||
|
||||
// prepare input to hash function
|
||||
byte[] data = new byte[salt.length + pin.length];
|
||||
System.arraycopy(salt, 0, data, 0, salt.length);
|
||||
System.arraycopy(pin, 0, data, salt.length, pin.length);
|
||||
|
||||
// hash data repeatedly
|
||||
// the iteration count is actually the number of octets to be hashed
|
||||
// see 3.7.1.2 of [0]
|
||||
int q = iterations / data.length;
|
||||
int r = iterations % data.length;
|
||||
for (int i = 0; i < q; i++) {
|
||||
digester.update(data, 0, data.length);
|
||||
}
|
||||
digester.update(data, 0, r);
|
||||
|
||||
byte[] digest = new byte[digester.getDigestSize()];
|
||||
digester.doFinal(digest, 0);
|
||||
|
||||
// delete secrets from memory
|
||||
Arrays.fill(data, (byte) 0);
|
||||
|
||||
return digest;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue