org.bouncycastle.pqc.crypto.xmss.BDSStateMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-jdk15to18 Show documentation
Show all versions of bcprov-jdk15to18 Show documentation
The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for JDK 1.5 to JDK 1.8.
package org.bouncycastle.pqc.crypto.xmss;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.util.Integers;
public class BDSStateMap
implements Serializable
{
private static final long serialVersionUID = -3464451825208522308L;
private final Map bdsState = new TreeMap();
private transient long maxIndex;
BDSStateMap(long maxIndex)
{
this.maxIndex = maxIndex;
}
BDSStateMap(BDSStateMap stateMap, long maxIndex)
{
for (Iterator it = stateMap.bdsState.keySet().iterator(); it.hasNext();)
{
Integer key = (Integer)it.next();
bdsState.put(key, new BDS(stateMap.bdsState.get(key)));
}
this.maxIndex = maxIndex;
}
BDSStateMap(XMSSMTParameters params, long globalIndex, byte[] publicSeed, byte[] secretKeySeed)
{
this.maxIndex = (1L << params.getHeight()) - 1;
for (long index = 0; index < globalIndex; index++)
{
updateState(params, index, publicSeed, secretKeySeed);
}
}
public long getMaxIndex()
{
return maxIndex;
}
void updateState(XMSSMTParameters params, long globalIndex, byte[] publicSeed, byte[] secretKeySeed)
{
XMSSParameters xmssParams = params.getXMSSParameters();
int xmssHeight = xmssParams.getHeight();
//
// set up state for next signature
//
long indexTree = XMSSUtil.getTreeIndex(globalIndex, xmssHeight);
int indexLeaf = XMSSUtil.getLeafIndex(globalIndex, xmssHeight);
OTSHashAddress otsHashAddress = (OTSHashAddress)new OTSHashAddress.Builder().withTreeAddress(indexTree)
.withOTSAddress(indexLeaf).build();
/* prepare authentication path for next leaf */
if (indexLeaf < ((1 << xmssHeight) - 1))
{
if (this.get(0) == null || indexLeaf == 0)
{
this.put(0, new BDS(xmssParams, publicSeed, secretKeySeed, otsHashAddress));
}
this.update(0, publicSeed, secretKeySeed, otsHashAddress);
}
/* loop over remaining layers */
for (int layer = 1; layer < params.getLayers(); layer++)
{
/* get root of layer - 1 */
indexLeaf = XMSSUtil.getLeafIndex(indexTree, xmssHeight);
indexTree = XMSSUtil.getTreeIndex(indexTree, xmssHeight);
/* adjust addresses */
otsHashAddress = (OTSHashAddress)new OTSHashAddress.Builder().withLayerAddress(layer)
.withTreeAddress(indexTree).withOTSAddress(indexLeaf).build();
/* prepare authentication path for next leaf */
if (bdsState.get(layer) == null || XMSSUtil.isNewBDSInitNeeded(globalIndex, xmssHeight, layer))
{
bdsState.put(layer, new BDS(xmssParams, publicSeed, secretKeySeed, otsHashAddress));
}
if (indexLeaf < ((1 << xmssHeight) - 1)
&& XMSSUtil.isNewAuthenticationPathNeeded(globalIndex, xmssHeight, layer))
{
this.update(layer, publicSeed, secretKeySeed, otsHashAddress);
}
}
}
public boolean isEmpty()
{
return bdsState.isEmpty();
}
BDS get(int index)
{
return bdsState.get(Integers.valueOf(index));
}
BDS update(int index, byte[] publicSeed, byte[] secretKeySeed, OTSHashAddress otsHashAddress)
{
return bdsState.put(Integers.valueOf(index), bdsState.get(Integers.valueOf(index)).getNextState(publicSeed, secretKeySeed, otsHashAddress));
}
void put(int index, BDS bds)
{
bdsState.put(Integers.valueOf(index), bds);
}
public BDSStateMap withWOTSDigest(ASN1ObjectIdentifier digestName)
{
BDSStateMap newStateMap = new BDSStateMap(this.maxIndex);
for (Iterator keys = bdsState.keySet().iterator(); keys.hasNext();)
{
Integer key = keys.next();
newStateMap.bdsState.put(key, bdsState.get(key).withWOTSDigest(digestName));
}
return newStateMap;
}
private void readObject(
ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
if (in.available() != 0)
{
this.maxIndex = in.readLong();
}
else
{
this.maxIndex = 0;
}
}
private void writeObject(
ObjectOutputStream out)
throws IOException
{
out.defaultWriteObject();
out.writeLong(this.maxIndex);
}
}