blob: 3f76d104722c108d1283044afab85f33c8e5f867 [file] [log] [blame]
package org.bouncycastle.pqc.crypto.xmss;
import java.security.SecureRandom;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.KeyGenerationParameters;
/**
* Key pair generator for XMSS^MT keys.
*/
public final class XMSSMTKeyPairGenerator
{
private XMSSMTParameters params;
private XMSSParameters xmssParams;
private SecureRandom prng;
/**
* Base constructor...
*/
public XMSSMTKeyPairGenerator()
{
}
public void init(
KeyGenerationParameters param)
{
XMSSMTKeyGenerationParameters parameters = (XMSSMTKeyGenerationParameters)param;
prng = parameters.getRandom();
this.params = parameters.getParameters();
this.xmssParams = params.getXMSSParameters();
}
/**
* Generate a new XMSSMT private key / public key pair.
*/
public AsymmetricCipherKeyPair generateKeyPair()
{
XMSSMTPrivateKeyParameters privateKey;
XMSSMTPublicKeyParameters publicKey;
/* generate XMSSMT private key */
privateKey = generatePrivateKey(new XMSSMTPrivateKeyParameters.Builder(params).build().getBDSState());
/* import to xmss */
xmssParams.getWOTSPlus().importKeys(new byte[params.getDigestSize()], privateKey.getPublicSeed());
/* get root */
int rootLayerIndex = params.getLayers() - 1;
OTSHashAddress otsHashAddress = (OTSHashAddress)new OTSHashAddress.Builder().withLayerAddress(rootLayerIndex)
.build();
/* store BDS instance of root xmss instance */
BDS bdsRoot = new BDS(xmssParams, privateKey.getPublicSeed(), privateKey.getSecretKeySeed(), otsHashAddress);
XMSSNode root = bdsRoot.getRoot();
privateKey.getBDSState().put(rootLayerIndex, bdsRoot);
/* set XMSS^MT root / create public key */
privateKey = new XMSSMTPrivateKeyParameters.Builder(params).withSecretKeySeed(privateKey.getSecretKeySeed())
.withSecretKeyPRF(privateKey.getSecretKeyPRF()).withPublicSeed(privateKey.getPublicSeed())
.withRoot(root.getValue()).withBDSState(privateKey.getBDSState()).build();
publicKey = new XMSSMTPublicKeyParameters.Builder(params).withRoot(root.getValue())
.withPublicSeed(privateKey.getPublicSeed()).build();
return new AsymmetricCipherKeyPair(publicKey, privateKey);
}
private XMSSMTPrivateKeyParameters generatePrivateKey(BDSStateMap bdsState)
{
int n = params.getDigestSize();
byte[] secretKeySeed = new byte[n];
prng.nextBytes(secretKeySeed);
byte[] secretKeyPRF = new byte[n];
prng.nextBytes(secretKeyPRF);
byte[] publicSeed = new byte[n];
prng.nextBytes(publicSeed);
XMSSMTPrivateKeyParameters privateKey = null;
privateKey = new XMSSMTPrivateKeyParameters.Builder(params).withSecretKeySeed(secretKeySeed)
.withSecretKeyPRF(secretKeyPRF).withPublicSeed(publicSeed)
.withBDSState(bdsState).build();
return privateKey;
}
}