blob: e50b206bf83cdf10c17b82d17140cc806a5ec2a0 [file] [log] [blame]
package org.bouncycastle.pqc.crypto.xmss;
import java.text.ParseException;
import org.bouncycastle.util.Pack;
/**
* XMSS Signature.
*/
public final class XMSSSignature
extends XMSSReducedSignature
implements XMSSStoreableObjectInterface
{
private final int index;
private final byte[] random;
private XMSSSignature(Builder builder)
throws ParseException
{
super(builder);
index = builder.index;
int n = getParams().getDigestSize();
byte[] tmpRandom = builder.random;
if (tmpRandom != null)
{
if (tmpRandom.length != n)
{
throw new IllegalArgumentException("size of random needs to be equal to size of digest");
}
random = tmpRandom;
}
else
{
random = new byte[n];
}
}
public static class Builder
extends XMSSReducedSignature.Builder
{
private final XMSSParameters params;
/* optional */
private int index = 0;
private byte[] random = null;
public Builder(XMSSParameters params)
{
super(params);
this.params = params;
}
public Builder withIndex(int val)
{
index = val;
return this;
}
public Builder withRandom(byte[] val)
{
random = XMSSUtil.cloneArray(val);
return this;
}
public Builder withSignature(byte[] val)
{
if (val == null)
{
throw new NullPointerException("signature == null");
}
int n = params.getDigestSize();
int len = params.getWOTSPlus().getParams().getLen();
int height = params.getHeight();
int indexSize = 4;
int randomSize = n;
int signatureSize = len * n;
int authPathSize = height * n;
int position = 0;
/* extract index */
index = Pack.bigEndianToInt(val, position);
position += indexSize;
/* extract random */
random = XMSSUtil.extractBytesAtOffset(val, position, randomSize);
position += randomSize;
withReducedSignature(XMSSUtil.extractBytesAtOffset(val, position, signatureSize + authPathSize));
return this;
}
public XMSSSignature build()
throws ParseException
{
return new XMSSSignature(this);
}
}
public byte[] toByteArray()
{
/* index || random || signature || authentication path */
int n = getParams().getDigestSize();
int indexSize = 4;
int randomSize = n;
int signatureSize = getParams().getWOTSPlus().getParams().getLen() * n;
int authPathSize = getParams().getHeight() * n;
int totalSize = indexSize + randomSize + signatureSize + authPathSize;
byte[] out = new byte[totalSize];
int position = 0;
/* copy index */
XMSSUtil.intToBytesBigEndianOffset(out, index, position);
position += indexSize;
/* copy random */
XMSSUtil.copyBytesAtOffset(out, random, position);
position += randomSize;
/* copy signature */
byte[][] signature = getWOTSPlusSignature().toByteArray();
for (int i = 0; i < signature.length; i++)
{
XMSSUtil.copyBytesAtOffset(out, signature[i], position);
position += n;
}
/* copy authentication path */
for (int i = 0; i < getAuthPath().size(); i++)
{
byte[] value = getAuthPath().get(i).getValue();
XMSSUtil.copyBytesAtOffset(out, value, position);
position += n;
}
return out;
}
public int getIndex()
{
return index;
}
public byte[] getRandom()
{
return XMSSUtil.cloneArray(random);
}
}