package org.bouncycastle.pqc.crypto.sphincs; import org.bouncycastle.crypto.Digest; import org.bouncycastle.util.Strings; class HashFunctions { private static final byte[] hashc = Strings.toByteArray("expand 32-byte to 64-byte state!"); private final Digest dig256; private final Digest dig512; private final Permute perm = new Permute(); // for key pair generation where message hash not required HashFunctions(Digest dig256) { this(dig256, null); } HashFunctions(Digest dig256, Digest dig512) { this.dig256 = dig256; this.dig512 = dig512; } int varlen_hash(byte[] out, int outOff, byte[] in, int inLen) { dig256.update(in, 0, inLen); dig256.doFinal(out, outOff); return 0; } Digest getMessageHash() { return dig512; } int hash_2n_n(byte[] out, int outOff, byte[] in, int inOff) { byte[] x = new byte[64]; int i; for (i = 0; i < 32; i++) { x[i] = in[inOff + i]; x[i + 32] = hashc[i]; } perm.chacha_permute(x, x); for (i = 0; i < 32; i++) { x[i] = (byte)(x[i] ^ in[inOff + i + 32]); } perm.chacha_permute(x, x); for (i = 0; i < 32; i++) { out[outOff + i] = x[i]; } return 0; } int hash_2n_n_mask(byte[] out, int outOff, byte[] in, int inOff, byte[] mask, int maskOff) { byte[] buf = new byte[2 * SPHINCS256Config.HASH_BYTES]; int i; for (i = 0; i < 2 * SPHINCS256Config.HASH_BYTES; i++) { buf[i] = (byte)(in[inOff + i] ^ mask[maskOff + i]); } int rv = hash_2n_n(out, outOff, buf, 0); return rv; } int hash_n_n(byte[] out, int outOff, byte[] in, int inOff) { byte[] x = new byte[64]; int i; for (i = 0; i < 32; i++) { x[i] = in[inOff + i]; x[i + 32] = hashc[i]; } perm.chacha_permute(x, x); for (i = 0; i < 32; i++) { out[outOff + i] = x[i]; } return 0; } int hash_n_n_mask(byte[] out, int outOff, byte[] in, int inOff, byte[] mask, int maskOff) { byte[] buf = new byte[SPHINCS256Config.HASH_BYTES]; int i; for (i = 0; i < SPHINCS256Config.HASH_BYTES; i++) { buf[i] = (byte)(in[inOff + i] ^ mask[maskOff + i]); } return hash_n_n(out, outOff, buf, 0); } }