All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.pqc.crypto.xmss.XMSSMTSignature Maven / Gradle / Ivy

package org.bouncycastle.pqc.crypto.xmss;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

/**
 * XMSSMT Signature.
 *
 */
public final class XMSSMTSignature implements XMSSStoreableObjectInterface {

	private final XMSSMTParameters params;
	private final long index;
	private final byte[] random;
	private final List reducedSignatures;

	private XMSSMTSignature(Builder builder) throws ParseException {
		super();
		params = builder.params;
		if (params == null) {
			throw new NullPointerException("params == null");
		}
		int n = params.getDigestSize();
		byte[] signature = builder.signature;
		if (signature != null) {
			/* import */
			int len = params.getWOTSPlus().getParams().getLen();
			int indexSize = (int) Math.ceil(params.getHeight() / (double) 8);
			int randomSize = n;
			int reducedSignatureSizeSingle = ((params.getHeight() / params.getLayers()) + len) * n;
			int reducedSignaturesSizeTotal = reducedSignatureSizeSingle * params.getLayers();
			int totalSize = indexSize + randomSize + reducedSignaturesSizeTotal;
			if (signature.length != totalSize) {
				throw new ParseException("signature has wrong size", 0);
			}
			int position = 0;
			index = XMSSUtil.bytesToXBigEndian(signature, position, indexSize);
			if (!XMSSUtil.isIndexValid(params.getHeight(), index)) {
				throw new ParseException("index out of bounds", 0);
			}
			position += indexSize;
			random = XMSSUtil.extractBytesAtOffset(signature, position, randomSize);
			position += randomSize;
			reducedSignatures = new ArrayList();
			while (position < signature.length) {
				XMSSReducedSignature xmssSig = new XMSSReducedSignature.Builder(params.getXMSS().getParams())
						.withReducedSignature(XMSSUtil.extractBytesAtOffset(signature, position, reducedSignatureSizeSingle))
						.build();
				reducedSignatures.add(xmssSig);
				position += reducedSignatureSizeSingle;
			}
		} else {
			/* set */
			index = builder.index;
			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];
			}
			List tmpReducedSignatures = builder.reducedSignatures;
			if (tmpReducedSignatures != null) {
				reducedSignatures = tmpReducedSignatures;
			} else {
				reducedSignatures = new ArrayList();
			}
		}
	}

	public static class Builder {
		
		/* mandatory */
		private final XMSSMTParameters params;
		/* optional */
		private long index = 0L;
		private byte[] random = null;
		private List reducedSignatures = null;
		private byte[] signature = null;
		
		public Builder(XMSSMTParameters params) {
			super();
			this.params = params;
		}
		
		public Builder withIndex(long val) {
			index = val;
			return this;
		}
		
		public Builder withRandom(byte[] val) {
			random = XMSSUtil.cloneArray(val);
			return this;
		}
		
		public Builder withReducedSignatures(List val) {
			reducedSignatures = val;
			return this;
		}

		public Builder withSignature(byte[] val) {
			signature = val;
			return this;
		}

		public XMSSMTSignature build() throws ParseException {
			return new XMSSMTSignature(this);
		}
	}

	public byte[] toByteArray() {
		/* index || random || reduced signatures */
		int n = params.getDigestSize();
		int len = params.getWOTSPlus().getParams().getLen();
		int indexSize = (int) Math.ceil(params.getHeight() / (double) 8);
		int randomSize = n;
		int reducedSignatureSizeSingle = ((params.getHeight() / params.getLayers()) + len) * n;
		int reducedSignaturesSizeTotal = reducedSignatureSizeSingle * params.getLayers();
		int totalSize = indexSize + randomSize + reducedSignaturesSizeTotal;
		byte[] out = new byte[totalSize];
		int position = 0;
		/* copy index */
		byte[] indexBytes = XMSSUtil.toBytesBigEndian(index, indexSize);
		XMSSUtil.copyBytesAtOffset(out, indexBytes, position);
		position += indexSize;
		/* copy random */
		XMSSUtil.copyBytesAtOffset(out, random, position);
		position += randomSize;
		/* copy reduced signatures */
		for (XMSSReducedSignature reducedSignature : reducedSignatures) {
			byte[] signature = reducedSignature.toByteArray();
			XMSSUtil.copyBytesAtOffset(out, signature, position);
			position += reducedSignatureSizeSingle;
		}
		return out;
	}

	public long getIndex() {
		return index;
	}

	public byte[] getRandom() {
		return XMSSUtil.cloneArray(random);
	}

	public List getReducedSignatures() {
		return reducedSignatures;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy