package org.bouncycastle.crypto.agreement.kdf;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.DerivationParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.DigestDerivationFunction;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Pack;
public class GSKKFDGenerator
implements DigestDerivationFunction
{
private final Digest digest;
private byte[] z;
private int counter;
private byte[] r;
private byte[] buf;
public GSKKFDGenerator(Digest digest)
{
this.digest = digest;
this.buf = new byte[digest.getDigestSize()];
}
public Digest getDigest()
{
return digest;
}
public void init(DerivationParameters param)
{
if (param instanceof GSKKDFParameters)
{
this.z = ((GSKKDFParameters)param).getZ();
this.counter = ((GSKKDFParameters)param).getStartCounter();
this.r = ((GSKKDFParameters)param).getNonce();
}
else
{
throw new IllegalArgumentException("unkown parameters type");
}
}
public int generateBytes(byte[] out, int outOff, int len)
throws DataLengthException, IllegalArgumentException
{
if (outOff + len > out.length)
{
throw new DataLengthException("output buffer too small");
}
digest.update(z, 0, z.length);
byte[] c = Pack.intToBigEndian(counter++);
digest.update(c, 0, c.length);
if (r != null)
{
digest.update(r, 0, r.length);
}
digest.doFinal(buf, 0);
System.arraycopy(buf, 0, out, outOff, len);
Arrays.clear(buf);
return len;
}
}