package groomiac.encryptor;
/*
* This class is based on the Bouncy Castle ((c) http://www.bouncycastle.org/) Java class org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator
* See http://www.bouncycastle.org/ for the license of BC
*/
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class PBKDF2 {
private Mac hMac;
private byte[] state;
public PBKDF2(Mac mac) {
hMac = mac;
state = new byte[hMac.getMacLength()];
}
private void F(byte[] S, int c, byte[] iBuf, byte[] out, int outOff) {
if (S != null) {
hMac.update(S, 0, S.length);
}
try {
hMac.update(iBuf, 0, iBuf.length);
hMac.doFinal(state, 0);
System.arraycopy(state, 0, out, outOff, state.length);
for (int count = 1; count < c; count++) {
hMac.update(state, 0, state.length);
hMac.doFinal(state, 0);
for (int j = 0; j != state.length; j++) {
out[outOff + j] ^= state[j];
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private byte[] generateDerivedKey(int dkLen, byte[] password, byte[] salt,
int iterationCount) {
int hLen = hMac.getMacLength();
int l = (dkLen + hLen - 1) / hLen;
byte[] iBuf = new byte[4];
byte[] outBytes = new byte[l * hLen];
int outPos = 0;
try {
SecretKeySpec key = new SecretKeySpec(password, "AES");
hMac.init(key);
for (int i = 1; i <= l; i++) {
int pos = 3;
while (++iBuf[pos] == 0) {
--pos;
}
F(salt, iterationCount, iBuf, outBytes, outPos);
outPos += hLen;
}
} catch (Exception e) {
e.printStackTrace();
}
return outBytes;
}
public byte[] generateDerivedParameters(int keySize, byte[] password,
byte[] salt, int iterationCount) throws Exception {
keySize = keySize / 8;
byte[] dKey = generateDerivedKey(keySize, password, salt,
iterationCount);
if (dKey.length != keySize)
throw new Exception("ARRAY NOT IN KEYSIZE!");
return dKey;
}
}