package org.bouncycastle.pqc.crypto.sphincs; import java.security.SecureRandom; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.KeyGenerationParameters; public class SPHINCS256KeyPairGenerator implements AsymmetricCipherKeyPairGenerator { private SecureRandom random; private Digest treeDigest; public void init(KeyGenerationParameters param) { random = param.getRandom(); treeDigest = ((SPHINCS256KeyGenerationParameters)param).getTreeDigest(); } public AsymmetricCipherKeyPair generateKeyPair() { Tree.leafaddr a = new Tree.leafaddr(); byte[] sk = new byte[SPHINCS256Config.CRYPTO_SECRETKEYBYTES]; random.nextBytes(sk); byte[] pk = new byte[SPHINCS256Config.CRYPTO_PUBLICKEYBYTES]; System.arraycopy(sk, SPHINCS256Config.SEED_BYTES, pk, 0, Horst.N_MASKS * SPHINCS256Config.HASH_BYTES); // Initialization of top-subtree address a.level = SPHINCS256Config.N_LEVELS - 1; a.subtree = 0; a.subleaf = 0; HashFunctions hs = new HashFunctions(treeDigest); // Format pk: [|N_MASKS*params.HASH_BYTES| Bitmasks || root] // Construct top subtree Tree.treehash(hs, pk, (Horst.N_MASKS * SPHINCS256Config.HASH_BYTES), SPHINCS256Config.SUBTREE_HEIGHT, sk, a, pk, 0); return new AsymmetricCipherKeyPair(new SPHINCSPublicKeyParameters(pk), new SPHINCSPrivateKeyParameters(sk)); } }