| package org.bouncycastle.pqc.crypto.xmss; |
| |
| import org.bouncycastle.crypto.Digest; |
| import org.bouncycastle.crypto.Xof; |
| |
| /** |
| * Crypto functions for XMSS. |
| * |
| */ |
| public 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[] buffer = new byte[digestSize + key.length + index.length]; |
| byte[] in = XMSSUtil.toBytesBigEndian(fixedValue, digestSize); |
| /* fill first n byte of out buffer */ |
| for (int i = 0; i < in.length; i++) { |
| buffer[i] = in[i]; |
| } |
| /* add key */ |
| for (int i = 0; i < key.length; i++) { |
| buffer[in.length + i] = key[i]; |
| } |
| /* add index */ |
| for (int i = 0; i < index.length; i++) { |
| buffer[in.length + key.length + i] = index[i]; |
| } |
| digest.update(buffer, 0, buffer.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); |
| } |
| } |