blob: f428f2f2512ddd619571760ea3ef7152dfccdd15 [file] [log] [blame]
package org.bouncycastle.pqc.crypto.xmss;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Xof;
/**
* Crypto functions for XMSS.
*/
final class KeyedHashFunctions
{
private final Digest digest;
private final int digestSize;
protected KeyedHashFunctions(Digest digest, int digestSize)
{
super();
if (digest == null)
{
throw new NullPointerException("digest == null");
}
this.digest = digest;
this.digestSize = digestSize;
}
private byte[] coreDigest(int fixedValue, byte[] key, byte[] index)
{
byte[] in = XMSSUtil.toBytesBigEndian(fixedValue, digestSize);
/* fill first n byte of out buffer */
digest.update(in, 0, in.length);
/* add key */
digest.update(key, 0, key.length);
/* add index */
digest.update(index, 0, index.length);
byte[] out = new byte[digestSize];
if (digest instanceof Xof)
{
((Xof)digest).doFinal(out, 0, digestSize);
}
else
{
digest.doFinal(out, 0);
}
return out;
}
protected byte[] F(byte[] key, byte[] in)
{
if (key.length != digestSize)
{
throw new IllegalArgumentException("wrong key length");
}
if (in.length != digestSize)
{
throw new IllegalArgumentException("wrong in length");
}
return coreDigest(0, key, in);
}
protected byte[] H(byte[] key, byte[] in)
{
if (key.length != digestSize)
{
throw new IllegalArgumentException("wrong key length");
}
if (in.length != (2 * digestSize))
{
throw new IllegalArgumentException("wrong in length");
}
return coreDigest(1, key, in);
}
protected byte[] HMsg(byte[] key, byte[] in)
{
if (key.length != (3 * digestSize))
{
throw new IllegalArgumentException("wrong key length");
}
return coreDigest(2, key, in);
}
protected byte[] PRF(byte[] key, byte[] address)
{
if (key.length != digestSize)
{
throw new IllegalArgumentException("wrong key length");
}
if (address.length != 32)
{
throw new IllegalArgumentException("wrong address length");
}
return coreDigest(3, key, address);
}
}