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

org.bouncycastle.pqc.asn1.GMSSPrivateKey Maven / Gradle / Ivy

Go to download

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 Java 1.8 and later with debug enabled.

The newest version!
package org.bouncycastle.pqc.asn1;

import java.util.Vector;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.pqc.legacy.crypto.gmss.GMSSLeaf;
import org.bouncycastle.pqc.legacy.crypto.gmss.GMSSParameters;
import org.bouncycastle.pqc.legacy.crypto.gmss.GMSSRootCalc;
import org.bouncycastle.pqc.legacy.crypto.gmss.GMSSRootSig;
import org.bouncycastle.pqc.legacy.crypto.gmss.Treehash;

public class GMSSPrivateKey
    extends ASN1Object
{
    public static GMSSPrivateKey getInstance(Object o)
    {
        if (o instanceof GMSSPrivateKey)
        {
            return (GMSSPrivateKey)o;
        }
        else if (o != null)
        {
            return new GMSSPrivateKey(ASN1Sequence.getInstance(o));
        }

        return null;
    }

    private ASN1Primitive primitive;

    private GMSSPrivateKey(ASN1Sequence mtsPrivateKey)
    {
        // --- Decode .
        ASN1Sequence indexPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(0);
        int[] index = new int[indexPart.size()];
        for (int i = 0; i < indexPart.size(); i++)
        {
            index[i] = checkBigIntegerInIntRange(indexPart.getObjectAt(i));
        }

        // --- Decode .
        ASN1Sequence curSeedsPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(1);
        byte[][] curSeeds = new byte[curSeedsPart.size()][];
        for (int i = 0; i < curSeeds.length; i++)
        {
            curSeeds[i] = ((DEROctetString)curSeedsPart.getObjectAt(i)).getOctets();
        }

        // --- Decode .
        ASN1Sequence nextNextSeedsPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(2);
        byte[][] nextNextSeeds = new byte[nextNextSeedsPart.size()][];
        for (int i = 0; i < nextNextSeeds.length; i++)
        {
            nextNextSeeds[i] = ((DEROctetString)nextNextSeedsPart.getObjectAt(i)).getOctets();
        }

        // --- Decode .
        ASN1Sequence curAuthPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(3);
        ASN1Sequence curAuthPart1;

        byte[][][] curAuth = new byte[curAuthPart0.size()][][];
        for (int i = 0; i < curAuth.length; i++)
        {
            curAuthPart1 = (ASN1Sequence)curAuthPart0.getObjectAt(i);
            curAuth[i] = new byte[curAuthPart1.size()][];
            for (int j = 0; j < curAuth[i].length; j++)
            {
                curAuth[i][j] = ((DEROctetString)curAuthPart1.getObjectAt(j)).getOctets();
            }
        }

        // --- Decode .
        ASN1Sequence nextAuthPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(4);
        ASN1Sequence nextAuthPart1;

        byte[][][] nextAuth = new byte[nextAuthPart0.size()][][];
        for (int i = 0; i < nextAuth.length; i++)
        {
            nextAuthPart1 = (ASN1Sequence)nextAuthPart0.getObjectAt(i);
            nextAuth[i] = new byte[nextAuthPart1.size()][];
            for (int j = 0; j < nextAuth[i].length; j++)
            {
                nextAuth[i][j] = ((DEROctetString)nextAuthPart1.getObjectAt(j)).getOctets();
            }
        }

        // --- Decode .
        ASN1Sequence seqOfcurTreehash0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(5);
        ASN1Sequence seqOfcurTreehash1;
        ASN1Sequence seqOfcurTreehashStat;
        ASN1Sequence seqOfcurTreehashBytes;
        ASN1Sequence seqOfcurTreehashInts;
        ASN1Sequence seqOfcurTreehashString;

        Treehash[][] curTreehash = new Treehash[seqOfcurTreehash0.size()][];
        /*
        for (int i = 0; i < curTreehash.length; i++)
        {
            seqOfcurTreehash1 = (ASN1Sequence)seqOfcurTreehash0.getObjectAt(i);
            curTreehash[i] = new Treehash[seqOfcurTreehash1.size()];
            for (int j = 0; j < curTreehash[i].length; j++)
            {
                seqOfcurTreehashStat = (ASN1Sequence)seqOfcurTreehash1.getObjectAt(j);
                seqOfcurTreehashString = (ASN1Sequence)seqOfcurTreehashStat
                    .getObjectAt(0);
                seqOfcurTreehashBytes = (ASN1Sequence)seqOfcurTreehashStat
                    .getObjectAt(1);
                seqOfcurTreehashInts = (ASN1Sequence)seqOfcurTreehashStat
                    .getObjectAt(2);

                String[] name = new String[2];
                name[0] = ((DERIA5String)seqOfcurTreehashString.getObjectAt(0)).getString();
                name[1] = ((DERIA5String)seqOfcurTreehashString.getObjectAt(1)).getString();

                int tailLength = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(1));
                byte[][] statByte = new byte[3 + tailLength][];
                statByte[0] = ((DEROctetString)seqOfcurTreehashBytes.getObjectAt(0)).getOctets();

                if (statByte[0].length == 0)
                { // if null was encoded
                    statByte[0] = null;
                }

                statByte[1] = ((DEROctetString)seqOfcurTreehashBytes.getObjectAt(1)).getOctets();
                statByte[2] = ((DEROctetString)seqOfcurTreehashBytes.getObjectAt(2)).getOctets();
                for (int k = 0; k < tailLength; k++)
                {
                    statByte[3 + k] = ((DEROctetString)seqOfcurTreehashBytes
                        .getObjectAt(3 + k)).getOctets();
                }
                int[] statInt = new int[6 + tailLength];
                statInt[0] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(0));
                statInt[1] = tailLength;
                statInt[2] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(2));
                statInt[3] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(3));
                statInt[4] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(4));
                statInt[5] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(5));
                for (int k = 0; k < tailLength; k++)
                {
                    statInt[6 + k] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(6 + k));
                }

                // TODO: Check if we can do better than throwing away name[1] !!!
                curTreehash[i][j] = new Treehash(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
            }
        }


        // --- Decode .
        ASN1Sequence seqOfNextTreehash0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(6);
        ASN1Sequence seqOfNextTreehash1;
        ASN1Sequence seqOfNextTreehashStat;
        ASN1Sequence seqOfNextTreehashBytes;
        ASN1Sequence seqOfNextTreehashInts;
        ASN1Sequence seqOfNextTreehashString;

        Treehash[][] nextTreehash = new Treehash[seqOfNextTreehash0.size()][];

        for (int i = 0; i < nextTreehash.length; i++)
        {
            seqOfNextTreehash1 = (ASN1Sequence)seqOfNextTreehash0.getObjectAt(i);
            nextTreehash[i] = new Treehash[seqOfNextTreehash1.size()];
            for (int j = 0; j < nextTreehash[i].length; j++)
            {
                seqOfNextTreehashStat = (ASN1Sequence)seqOfNextTreehash1
                    .getObjectAt(j);
                seqOfNextTreehashString = (ASN1Sequence)seqOfNextTreehashStat
                    .getObjectAt(0);
                seqOfNextTreehashBytes = (ASN1Sequence)seqOfNextTreehashStat
                    .getObjectAt(1);
                seqOfNextTreehashInts = (ASN1Sequence)seqOfNextTreehashStat
                    .getObjectAt(2);

                String[] name = new String[2];
                name[0] = ((DERIA5String)seqOfNextTreehashString.getObjectAt(0))
                    .getString();
                name[1] = ((DERIA5String)seqOfNextTreehashString.getObjectAt(1))
                    .getString();

                int tailLength = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(1));

                byte[][] statByte = new byte[3 + tailLength][];
                statByte[0] = ((DEROctetString)seqOfNextTreehashBytes.getObjectAt(0)).getOctets();
                if (statByte[0].length == 0)
                { // if null was encoded
                    statByte[0] = null;
                }

                statByte[1] = ((DEROctetString)seqOfNextTreehashBytes.getObjectAt(1)).getOctets();
                statByte[2] = ((DEROctetString)seqOfNextTreehashBytes.getObjectAt(2)).getOctets();
                for (int k = 0; k < tailLength; k++)
                {
                    statByte[3 + k] = ((DEROctetString)seqOfNextTreehashBytes
                        .getObjectAt(3 + k)).getOctets();
                }
                int[] statInt = new int[6 + tailLength];
                statInt[0] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(0));

                statInt[1] = tailLength;
                statInt[2] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(2));

                statInt[3] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(3));

                statInt[4] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(4));

                statInt[5] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(5));

                for (int k = 0; k < tailLength; k++)
                {
                    statInt[6 + k] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(6 + k));

                }
                nextTreehash[i][j] = new Treehash(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
            }
        }


        // --- Decode .
        ASN1Sequence keepPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(7);
        ASN1Sequence keepPart1;

        byte[][][] keep = new byte[keepPart0.size()][][];
        for (int i = 0; i < keep.length; i++)
        {
            keepPart1 = (ASN1Sequence)keepPart0.getObjectAt(i);
            keep[i] = new byte[keepPart1.size()][];
            for (int j = 0; j < keep[i].length; j++)
            {
                keep[i][j] = ((DEROctetString)keepPart1.getObjectAt(j)).getOctets();
            }
        }

        // --- Decode .
        ASN1Sequence curStackPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(8);
        ASN1Sequence curStackPart1;

        Vector[] curStack = new Vector[curStackPart0.size()];
        for (int i = 0; i < curStack.length; i++)
        {
            curStackPart1 = (ASN1Sequence)curStackPart0.getObjectAt(i);
            curStack[i] = new Vector();
            for (int j = 0; j < curStackPart1.size(); j++)
            {
                curStack[i].addElement(((DEROctetString)curStackPart1.getObjectAt(j)).getOctets());
            }
        }

        // --- Decode .
        ASN1Sequence nextStackPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(9);
        ASN1Sequence nextStackPart1;

        Vector[] nextStack = new Vector[nextStackPart0.size()];
        for (int i = 0; i < nextStack.length; i++)
        {
            nextStackPart1 = (ASN1Sequence)nextStackPart0.getObjectAt(i);
            nextStack[i] = new Vector();
            for (int j = 0; j < nextStackPart1.size(); j++)
            {
                nextStack[i].addElement(((DEROctetString)nextStackPart1
                    .getObjectAt(j)).getOctets());
            }
        }

        // --- Decode .
        ASN1Sequence curRetainPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(10);
        ASN1Sequence curRetainPart1;
        ASN1Sequence curRetainPart2;

        Vector[][] curRetain = new Vector[curRetainPart0.size()][];
        for (int i = 0; i < curRetain.length; i++)
        {
            curRetainPart1 = (ASN1Sequence)curRetainPart0.getObjectAt(i);
            curRetain[i] = new Vector[curRetainPart1.size()];
            for (int j = 0; j < curRetain[i].length; j++)
            {
                curRetainPart2 = (ASN1Sequence)curRetainPart1.getObjectAt(j);
                curRetain[i][j] = new Vector();
                for (int k = 0; k < curRetainPart2.size(); k++)
                {
                    curRetain[i][j]
                        .addElement(((DEROctetString)curRetainPart2
                            .getObjectAt(k)).getOctets());
                }
            }
        }

        // --- Decode .
        ASN1Sequence nextRetainPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(11);
        ASN1Sequence nextRetainPart1;
        ASN1Sequence nextRetainPart2;

        Vector[][] nextRetain = new Vector[nextRetainPart0.size()][];
        for (int i = 0; i < nextRetain.length; i++)
        {
            nextRetainPart1 = (ASN1Sequence)nextRetainPart0.getObjectAt(i);
            nextRetain[i] = new Vector[nextRetainPart1.size()];
            for (int j = 0; j < nextRetain[i].length; j++)
            {
                nextRetainPart2 = (ASN1Sequence)nextRetainPart1.getObjectAt(j);
                nextRetain[i][j] = new Vector();
                for (int k = 0; k < nextRetainPart2.size(); k++)
                {
                    nextRetain[i][j]
                        .addElement(((DEROctetString)nextRetainPart2
                            .getObjectAt(k)).getOctets());
                }
            }
        }

        // --- Decode .
        ASN1Sequence seqOfLeafs = (ASN1Sequence)mtsPrivateKey.getObjectAt(12);
        ASN1Sequence seqOfLeafStat;
        ASN1Sequence seqOfLeafBytes;
        ASN1Sequence seqOfLeafInts;
        ASN1Sequence seqOfLeafString;

        GMSSLeaf[] nextNextLeaf = new GMSSLeaf[seqOfLeafs.size()];

        for (int i = 0; i < nextNextLeaf.length; i++)
        {
            seqOfLeafStat = (ASN1Sequence)seqOfLeafs.getObjectAt(i);
            // nextNextAuth[i]= new byte[nextNextAuthPart1.size()][];
            seqOfLeafString = (ASN1Sequence)seqOfLeafStat.getObjectAt(0);
            seqOfLeafBytes = (ASN1Sequence)seqOfLeafStat.getObjectAt(1);
            seqOfLeafInts = (ASN1Sequence)seqOfLeafStat.getObjectAt(2);

            String[] name = new String[2];
            name[0] = ((DERIA5String)seqOfLeafString.getObjectAt(0)).getString();
            name[1] = ((DERIA5String)seqOfLeafString.getObjectAt(1)).getString();
            byte[][] statByte = new byte[4][];
            statByte[0] = ((DEROctetString)seqOfLeafBytes.getObjectAt(0))
                .getOctets();
            statByte[1] = ((DEROctetString)seqOfLeafBytes.getObjectAt(1))
                .getOctets();
            statByte[2] = ((DEROctetString)seqOfLeafBytes.getObjectAt(2))
                .getOctets();
            statByte[3] = ((DEROctetString)seqOfLeafBytes.getObjectAt(3))
                .getOctets();
            int[] statInt = new int[4];
            statInt[0] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(0));
            statInt[1] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(1));
            statInt[2] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(2));
            statInt[3] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(3));
            nextNextLeaf[i] = new GMSSLeaf(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
        }

        // --- Decode .
        ASN1Sequence seqOfUpperLeafs = (ASN1Sequence)mtsPrivateKey.getObjectAt(13);
        ASN1Sequence seqOfUpperLeafStat;
        ASN1Sequence seqOfUpperLeafBytes;
        ASN1Sequence seqOfUpperLeafInts;
        ASN1Sequence seqOfUpperLeafString;

        GMSSLeaf[] upperLeaf = new GMSSLeaf[seqOfUpperLeafs.size()];

        for (int i = 0; i < upperLeaf.length; i++)
        {
            seqOfUpperLeafStat = (ASN1Sequence)seqOfUpperLeafs.getObjectAt(i);
            seqOfUpperLeafString = (ASN1Sequence)seqOfUpperLeafStat.getObjectAt(0);
            seqOfUpperLeafBytes = (ASN1Sequence)seqOfUpperLeafStat.getObjectAt(1);
            seqOfUpperLeafInts = (ASN1Sequence)seqOfUpperLeafStat.getObjectAt(2);

            String[] name = new String[2];
            name[0] = ((DERIA5String)seqOfUpperLeafString.getObjectAt(0)).getString();
            name[1] = ((DERIA5String)seqOfUpperLeafString.getObjectAt(1)).getString();
            byte[][] statByte = new byte[4][];
            statByte[0] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(0))
                .getOctets();
            statByte[1] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(1))
                .getOctets();
            statByte[2] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(2))
                .getOctets();
            statByte[3] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(3))
                .getOctets();
            int[] statInt = new int[4];
            statInt[0] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(0));
            statInt[1] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(1));
            statInt[2] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(2));
            statInt[3] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(3));
            upperLeaf[i] = new GMSSLeaf(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
        }

        // --- Decode .
        ASN1Sequence seqOfUpperTHLeafs = (ASN1Sequence)mtsPrivateKey.getObjectAt(14);
        ASN1Sequence seqOfUpperTHLeafStat;
        ASN1Sequence seqOfUpperTHLeafBytes;
        ASN1Sequence seqOfUpperTHLeafInts;
        ASN1Sequence seqOfUpperTHLeafString;

        GMSSLeaf[] upperTHLeaf = new GMSSLeaf[seqOfUpperTHLeafs.size()];

        for (int i = 0; i < upperTHLeaf.length; i++)
        {
            seqOfUpperTHLeafStat = (ASN1Sequence)seqOfUpperTHLeafs.getObjectAt(i);
            seqOfUpperTHLeafString = (ASN1Sequence)seqOfUpperTHLeafStat.getObjectAt(0);
            seqOfUpperTHLeafBytes = (ASN1Sequence)seqOfUpperTHLeafStat.getObjectAt(1);
            seqOfUpperTHLeafInts = (ASN1Sequence)seqOfUpperTHLeafStat.getObjectAt(2);

            String[] name = new String[2];
            name[0] = ((DERIA5String)seqOfUpperTHLeafString.getObjectAt(0))
                .getString();
            name[1] = ((DERIA5String)seqOfUpperTHLeafString.getObjectAt(1))
                .getString();
            byte[][] statByte = new byte[4][];
            statByte[0] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(0))
                .getOctets();
            statByte[1] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(1))
                .getOctets();
            statByte[2] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(2))
                .getOctets();
            statByte[3] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(3))
                .getOctets();
            int[] statInt = new int[4];
            statInt[0] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(0));
            statInt[1] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(1));
            statInt[2] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(2));
            statInt[3] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(3));
            upperTHLeaf[i] = new GMSSLeaf(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
        }

        // --- Decode .
        ASN1Sequence minTreehashPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(15);
        int[] minTreehash = new int[minTreehashPart.size()];
        for (int i = 0; i < minTreehashPart.size(); i++)
        {
            minTreehash[i] = checkBigIntegerInIntRange(minTreehashPart.getObjectAt(i));
        }

        // --- Decode .
        ASN1Sequence seqOfnextRoots = (ASN1Sequence)mtsPrivateKey.getObjectAt(16);
        byte[][] nextRoot = new byte[seqOfnextRoots.size()][];
        for (int i = 0; i < nextRoot.length; i++)
        {
            nextRoot[i] = ((DEROctetString)seqOfnextRoots.getObjectAt(i))
                .getOctets();
        }

        // --- Decode .
        ASN1Sequence seqOfnextNextRoot = (ASN1Sequence)mtsPrivateKey.getObjectAt(17);
        ASN1Sequence seqOfnextNextRootStat;
        ASN1Sequence seqOfnextNextRootBytes;
        ASN1Sequence seqOfnextNextRootInts;
        ASN1Sequence seqOfnextNextRootString;
        ASN1Sequence seqOfnextNextRootTreeH;
        ASN1Sequence seqOfnextNextRootRetain;

        GMSSRootCalc[] nextNextRoot = new GMSSRootCalc[seqOfnextNextRoot.size()];

        for (int i = 0; i < nextNextRoot.length; i++)
        {
            seqOfnextNextRootStat = (ASN1Sequence)seqOfnextNextRoot.getObjectAt(i);
            seqOfnextNextRootString = (ASN1Sequence)seqOfnextNextRootStat
                .getObjectAt(0);
            seqOfnextNextRootBytes = (ASN1Sequence)seqOfnextNextRootStat
                .getObjectAt(1);
            seqOfnextNextRootInts = (ASN1Sequence)seqOfnextNextRootStat.getObjectAt(2);
            seqOfnextNextRootTreeH = (ASN1Sequence)seqOfnextNextRootStat
                .getObjectAt(3);
            seqOfnextNextRootRetain = (ASN1Sequence)seqOfnextNextRootStat
                .getObjectAt(4);

            // decode treehash of nextNextRoot
            // ---------------------------------
            ASN1Sequence seqOfnextNextRootTreeHStat;
            ASN1Sequence seqOfnextNextRootTreeHBytes;
            ASN1Sequence seqOfnextNextRootTreeHInts;
            ASN1Sequence seqOfnextNextRootTreeHString;

            Treehash[] nnRTreehash = new Treehash[seqOfnextNextRootTreeH.size()];

            for (int k = 0; k < nnRTreehash.length; k++)
            {
                seqOfnextNextRootTreeHStat = (ASN1Sequence)seqOfnextNextRootTreeH
                    .getObjectAt(k);
                seqOfnextNextRootTreeHString = (ASN1Sequence)seqOfnextNextRootTreeHStat
                    .getObjectAt(0);
                seqOfnextNextRootTreeHBytes = (ASN1Sequence)seqOfnextNextRootTreeHStat
                    .getObjectAt(1);
                seqOfnextNextRootTreeHInts = (ASN1Sequence)seqOfnextNextRootTreeHStat
                    .getObjectAt(2);

                String[] name = new String[2];
                name[0] = ((DERIA5String)seqOfnextNextRootTreeHString.getObjectAt(0))
                    .getString();
                name[1] = ((DERIA5String)seqOfnextNextRootTreeHString.getObjectAt(1))
                    .getString();

                int tailLength = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(1));

                byte[][] statByte = new byte[3 + tailLength][];
                statByte[0] = ((DEROctetString)seqOfnextNextRootTreeHBytes
                    .getObjectAt(0)).getOctets();
                if (statByte[0].length == 0)
                { // if null was encoded
                    statByte[0] = null;
                }

                statByte[1] = ((DEROctetString)seqOfnextNextRootTreeHBytes
                    .getObjectAt(1)).getOctets();
                statByte[2] = ((DEROctetString)seqOfnextNextRootTreeHBytes
                    .getObjectAt(2)).getOctets();
                for (int j = 0; j < tailLength; j++)
                {
                    statByte[3 + j] = ((DEROctetString)seqOfnextNextRootTreeHBytes
                        .getObjectAt(3 + j)).getOctets();
                }
                int[] statInt = new int[6 + tailLength];
                statInt[0] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(0));

                statInt[1] = tailLength;
                statInt[2] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(2));

                statInt[3] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(3));

                statInt[4] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(4));

                statInt[5] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(5));

                for (int j = 0; j < tailLength; j++)
                {
                    statInt[6 + j] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts
                        .getObjectAt(6 + j));
                }
                nnRTreehash[k] = new Treehash(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
            }
            // ---------------------------------

            // decode retain of nextNextRoot
            // ---------------------------------
            // ASN1Sequence seqOfnextNextRootRetainPart0 =
            // (ASN1Sequence)seqOfnextNextRootRetain.get(0);
            ASN1Sequence seqOfnextNextRootRetainPart1;

            Vector[] nnRRetain = new Vector[seqOfnextNextRootRetain.size()];
            for (int j = 0; j < nnRRetain.length; j++)
            {
                seqOfnextNextRootRetainPart1 = (ASN1Sequence)seqOfnextNextRootRetain
                    .getObjectAt(j);
                nnRRetain[j] = new Vector();
                for (int k = 0; k < seqOfnextNextRootRetainPart1.size(); k++)
                {
                    nnRRetain[j]
                        .addElement(((DEROctetString)seqOfnextNextRootRetainPart1
                            .getObjectAt(k)).getOctets());
                }
            }
            // ---------------------------------

            String[] name = new String[2];
            name[0] = ((DERIA5String)seqOfnextNextRootString.getObjectAt(0))
                .getString();
            name[1] = ((DERIA5String)seqOfnextNextRootString.getObjectAt(1))
                .getString();

            int heightOfTree = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(0));
            int tailLength = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(7));
            byte[][] statByte = new byte[1 + heightOfTree + tailLength][];
            statByte[0] = ((DEROctetString)seqOfnextNextRootBytes.getObjectAt(0))
                .getOctets();
            for (int j = 0; j < heightOfTree; j++)
            {
                statByte[1 + j] = ((DEROctetString)seqOfnextNextRootBytes
                    .getObjectAt(1 + j)).getOctets();
            }
            for (int j = 0; j < tailLength; j++)
            {
                statByte[1 + heightOfTree + j] = ((DEROctetString)seqOfnextNextRootBytes
                    .getObjectAt(1 + heightOfTree + j)).getOctets();
            }
            int[] statInt = new int[8 + heightOfTree + tailLength];
            statInt[0] = heightOfTree;
            statInt[1] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(1));
            statInt[2] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(2));
            statInt[3] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(3));
            statInt[4] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(4));
            statInt[5] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(5));
            statInt[6] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(6));
            statInt[7] = tailLength;
            for (int j = 0; j < heightOfTree; j++)
            {
                statInt[8 + j] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(8 + j));
            }
            for (int j = 0; j < tailLength; j++)
            {
                statInt[8 + heightOfTree + j] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(8
                    + heightOfTree + j));
            }
            nextNextRoot[i] = new GMSSRootCalc(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt,
                nnRTreehash, nnRRetain);
        }

        // --- Decode .
        ASN1Sequence seqOfcurRootSig = (ASN1Sequence)mtsPrivateKey.getObjectAt(18);
        byte[][] curRootSig = new byte[seqOfcurRootSig.size()][];
        for (int i = 0; i < curRootSig.length; i++)
        {
            curRootSig[i] = ((DEROctetString)seqOfcurRootSig.getObjectAt(i))
                .getOctets();
        }

        // --- Decode .
        ASN1Sequence seqOfnextRootSigs = (ASN1Sequence)mtsPrivateKey.getObjectAt(19);
        ASN1Sequence seqOfnRSStats;
        ASN1Sequence seqOfnRSStrings;
        ASN1Sequence seqOfnRSInts;
        ASN1Sequence seqOfnRSBytes;

        GMSSRootSig[] nextRootSig = new GMSSRootSig[seqOfnextRootSigs.size()];

        for (int i = 0; i < nextRootSig.length; i++)
        {
            seqOfnRSStats = (ASN1Sequence)seqOfnextRootSigs.getObjectAt(i);
            // nextNextAuth[i]= new byte[nextNextAuthPart1.size()][];
            seqOfnRSStrings = (ASN1Sequence)seqOfnRSStats.getObjectAt(0);
            seqOfnRSBytes = (ASN1Sequence)seqOfnRSStats.getObjectAt(1);
            seqOfnRSInts = (ASN1Sequence)seqOfnRSStats.getObjectAt(2);

            String[] name = new String[2];
            name[0] = ((DERIA5String)seqOfnRSStrings.getObjectAt(0)).getString();
            name[1] = ((DERIA5String)seqOfnRSStrings.getObjectAt(1)).getString();
            byte[][] statByte = new byte[5][];
            statByte[0] = ((DEROctetString)seqOfnRSBytes.getObjectAt(0))
                .getOctets();
            statByte[1] = ((DEROctetString)seqOfnRSBytes.getObjectAt(1))
                .getOctets();
            statByte[2] = ((DEROctetString)seqOfnRSBytes.getObjectAt(2))
                .getOctets();
            statByte[3] = ((DEROctetString)seqOfnRSBytes.getObjectAt(3))
                .getOctets();
            statByte[4] = ((DEROctetString)seqOfnRSBytes.getObjectAt(4))
                .getOctets();
            int[] statInt = new int[9];
            statInt[0] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(0));
            statInt[1] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(1));
            statInt[2] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(2));
            statInt[3] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(3));
            statInt[4] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(4));
            statInt[5] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(5));
            statInt[6] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(6));
            statInt[7] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(7));
            statInt[8] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(8));
            nextRootSig[i] = new GMSSRootSig(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
        }

        // --- Decode .

        // TODO: Really check, why there are multiple algorithms, we only
        //       use the first one!!!
        ASN1Sequence namePart = (ASN1Sequence)mtsPrivateKey.getObjectAt(20);
        String[] name = new String[namePart.size()];
        for (int i = 0; i < name.length; i++)
        {
            name[i] = ((DERIA5String)namePart.getObjectAt(i)).getString();
        }
        */
    }

    public GMSSPrivateKey(int[] index, byte[][] currentSeed,
                          byte[][] nextNextSeed, byte[][][] currentAuthPath,
                          byte[][][] nextAuthPath, Treehash[][] currentTreehash,
                          Treehash[][] nextTreehash, Vector[] currentStack,
                          Vector[] nextStack, Vector[][] currentRetain,
                          Vector[][] nextRetain, byte[][][] keep, GMSSLeaf[] nextNextLeaf,
                          GMSSLeaf[] upperLeaf, GMSSLeaf[] upperTreehashLeaf,
                          int[] minTreehash, byte[][] nextRoot, GMSSRootCalc[] nextNextRoot,
                          byte[][] currentRootSig, GMSSRootSig[] nextRootSig,
                          GMSSParameters gmssParameterset, AlgorithmIdentifier digestAlg)
    {
        AlgorithmIdentifier[] names = new AlgorithmIdentifier[] { digestAlg };
        this.primitive = encode(index, currentSeed, nextNextSeed, currentAuthPath, nextAuthPath, keep, currentTreehash, nextTreehash, currentStack, nextStack, currentRetain, nextRetain, nextNextLeaf, upperLeaf, upperTreehashLeaf, minTreehash, nextRoot, nextNextRoot, currentRootSig, nextRootSig, gmssParameterset, names);
    }


    // TODO: change method signature to something more integrated into BouncyCastle

    /**
     * @param index             tree indices
     * @param currentSeeds      seed for the generation of private OTS keys for the
     *                          current subtrees (TREE)
     * @param nextNextSeeds     seed for the generation of private OTS keys for the
     *                          subtrees after next (TREE++)
     * @param currentAuthPaths  array of current authentication paths (AUTHPATH)
     * @param nextAuthPaths     array of next authentication paths (AUTHPATH+)
     * @param keep              keep array for the authPath algorithm
     * @param currentTreehash   treehash for authPath algorithm of current tree
     * @param nextTreehash      treehash for authPath algorithm of next tree (TREE+)
     * @param currentStack      shared stack for authPath algorithm of current tree
     * @param nextStack         shared stack for authPath algorithm of next tree (TREE+)
     * @param currentRetain     retain stack for authPath algorithm of current tree
     * @param nextRetain        retain stack for authPath algorithm of next tree (TREE+)
     * @param nextNextLeaf      array of upcoming leafs of the tree after next (LEAF++) of
     *                          each layer
     * @param upperLeaf         needed for precomputation of upper nodes
     * @param upperTreehashLeaf needed for precomputation of upper treehash nodes
     * @param minTreehash       index of next treehash instance to receive an update
     * @param nextRoot          the roots of the next trees (ROOT+)
     * @param nextNextRoot      the roots of the tree after next (ROOT++)
     * @param currentRootSig    array of signatures of the roots of the current subtrees
     *                          (SIG)
     * @param nextRootSig       array of signatures of the roots of the next subtree
     *                          (SIG+)
     * @param gmssParameterset  the GMSS Parameterset
     * @param algorithms        An array of algorithm identifiers, containing the hash function details
     */
    private ASN1Primitive encode(int[] index, byte[][] currentSeeds,
                                byte[][] nextNextSeeds, byte[][][] currentAuthPaths,
                                byte[][][] nextAuthPaths, byte[][][] keep,
                                Treehash[][] currentTreehash, Treehash[][] nextTreehash,
                                Vector[] currentStack, Vector[] nextStack,
                                Vector[][] currentRetain, Vector[][] nextRetain,
                                GMSSLeaf[] nextNextLeaf, GMSSLeaf[] upperLeaf,
                                GMSSLeaf[] upperTreehashLeaf, int[] minTreehash, byte[][] nextRoot,
                                GMSSRootCalc[] nextNextRoot, byte[][] currentRootSig,
                                GMSSRootSig[] nextRootSig, GMSSParameters gmssParameterset,
                                AlgorithmIdentifier[] algorithms)
    {

        ASN1EncodableVector result = new ASN1EncodableVector();

        // --- Encode .
        ASN1EncodableVector indexPart = new ASN1EncodableVector();
        for (int i = 0; i < index.length; i++)
        {
            indexPart.add(new ASN1Integer(index[i]));
        }
        result.add(new DERSequence(indexPart));

        // --- Encode .
        ASN1EncodableVector curSeedsPart = new ASN1EncodableVector();
        for (int i = 0; i < currentSeeds.length; i++)
        {
            curSeedsPart.add(new DEROctetString(currentSeeds[i]));
        }
        result.add(new DERSequence(curSeedsPart));

        // --- Encode .
        ASN1EncodableVector nextNextSeedsPart = new ASN1EncodableVector();
        for (int i = 0; i < nextNextSeeds.length; i++)
        {
            nextNextSeedsPart.add(new DEROctetString(nextNextSeeds[i]));
        }
        result.add(new DERSequence(nextNextSeedsPart));

        // --- Encode .
        ASN1EncodableVector curAuthPart0 = new ASN1EncodableVector();
        ASN1EncodableVector curAuthPart1 = new ASN1EncodableVector();
        for (int i = 0; i < currentAuthPaths.length; i++)
        {
            for (int j = 0; j < currentAuthPaths[i].length; j++)
            {
                curAuthPart0.add(new DEROctetString(currentAuthPaths[i][j]));
            }
            curAuthPart1.add(new DERSequence(curAuthPart0));
            curAuthPart0 = new ASN1EncodableVector();
        }
        result.add(new DERSequence(curAuthPart1));

        // --- Encode .
        ASN1EncodableVector nextAuthPart0 = new ASN1EncodableVector();
        ASN1EncodableVector nextAuthPart1 = new ASN1EncodableVector();
        for (int i = 0; i < nextAuthPaths.length; i++)
        {
            for (int j = 0; j < nextAuthPaths[i].length; j++)
            {
                nextAuthPart0.add(new DEROctetString(nextAuthPaths[i][j]));
            }
            nextAuthPart1.add(new DERSequence(nextAuthPart0));
            nextAuthPart0 = new ASN1EncodableVector();
        }
        result.add(new DERSequence(nextAuthPart1));

        // --- Encode .
        ASN1EncodableVector seqOfTreehash0 = new ASN1EncodableVector();
        ASN1EncodableVector seqOfTreehash1 = new ASN1EncodableVector();
        ASN1EncodableVector seqOfStat = new ASN1EncodableVector();
        ASN1EncodableVector seqOfByte = new ASN1EncodableVector();
        ASN1EncodableVector seqOfInt = new ASN1EncodableVector();

        for (int i = 0; i < currentTreehash.length; i++)
        {
            for (int j = 0; j < currentTreehash[i].length; j++)
            {
                seqOfStat.add(new DERSequence(algorithms[0]));

                int tailLength = currentTreehash[i][j].getStatInt()[1];

                seqOfByte.add(new DEROctetString(currentTreehash[i][j]
                    .getStatByte()[0]));
                seqOfByte.add(new DEROctetString(currentTreehash[i][j]
                    .getStatByte()[1]));
                seqOfByte.add(new DEROctetString(currentTreehash[i][j]
                    .getStatByte()[2]));
                for (int k = 0; k < tailLength; k++)
                {
                    seqOfByte.add(new DEROctetString(currentTreehash[i][j]
                        .getStatByte()[3 + k]));
                }
                seqOfStat.add(new DERSequence(seqOfByte));
                seqOfByte = new ASN1EncodableVector();

                seqOfInt.add(new ASN1Integer(
                    currentTreehash[i][j].getStatInt()[0]));
                seqOfInt.add(new ASN1Integer(tailLength));
                seqOfInt.add(new ASN1Integer(
                    currentTreehash[i][j].getStatInt()[2]));
                seqOfInt.add(new ASN1Integer(
                    currentTreehash[i][j].getStatInt()[3]));
                seqOfInt.add(new ASN1Integer(
                    currentTreehash[i][j].getStatInt()[4]));
                seqOfInt.add(new ASN1Integer(
                    currentTreehash[i][j].getStatInt()[5]));
                for (int k = 0; k < tailLength; k++)
                {
                    seqOfInt.add(new ASN1Integer(currentTreehash[i][j]
                        .getStatInt()[6 + k]));
                }
                seqOfStat.add(new DERSequence(seqOfInt));
                seqOfInt = new ASN1EncodableVector();

                seqOfTreehash1.add(new DERSequence(seqOfStat));
                seqOfStat = new ASN1EncodableVector();
            }
            seqOfTreehash0.add(new DERSequence(seqOfTreehash1));
            seqOfTreehash1 = new ASN1EncodableVector();
        }
        result.add(new DERSequence(seqOfTreehash0));

        // --- Encode .
        seqOfTreehash0 = new ASN1EncodableVector();
        seqOfTreehash1 = new ASN1EncodableVector();
        seqOfStat = new ASN1EncodableVector();
        seqOfByte = new ASN1EncodableVector();
        seqOfInt = new ASN1EncodableVector();

        for (int i = 0; i < nextTreehash.length; i++)
        {
            for (int j = 0; j < nextTreehash[i].length; j++)
            {
                seqOfStat.add(new DERSequence(algorithms[0]));

                int tailLength = nextTreehash[i][j].getStatInt()[1];

                seqOfByte.add(new DEROctetString(nextTreehash[i][j]
                    .getStatByte()[0]));
                seqOfByte.add(new DEROctetString(nextTreehash[i][j]
                    .getStatByte()[1]));
                seqOfByte.add(new DEROctetString(nextTreehash[i][j]
                    .getStatByte()[2]));
                for (int k = 0; k < tailLength; k++)
                {
                    seqOfByte.add(new DEROctetString(nextTreehash[i][j]
                        .getStatByte()[3 + k]));
                }
                seqOfStat.add(new DERSequence(seqOfByte));
                seqOfByte = new ASN1EncodableVector();

                seqOfInt
                    .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[0]));
                seqOfInt.add(new ASN1Integer(tailLength));
                seqOfInt
                    .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[2]));
                seqOfInt
                    .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[3]));
                seqOfInt
                    .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[4]));
                seqOfInt
                    .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[5]));
                for (int k = 0; k < tailLength; k++)
                {
                    seqOfInt.add(new ASN1Integer(nextTreehash[i][j]
                        .getStatInt()[6 + k]));
                }
                seqOfStat.add(new DERSequence(seqOfInt));
                seqOfInt = new ASN1EncodableVector();

                seqOfTreehash1.add(new DERSequence(seqOfStat));
                seqOfStat = new ASN1EncodableVector();
            }
            seqOfTreehash0.add(new DERSequence(new DERSequence(seqOfTreehash1)));
            seqOfTreehash1 = new ASN1EncodableVector();
        }
        result.add(new DERSequence(seqOfTreehash0));

        // --- Encode .
        ASN1EncodableVector keepPart0 = new ASN1EncodableVector();
        ASN1EncodableVector keepPart1 = new ASN1EncodableVector();
        for (int i = 0; i < keep.length; i++)
        {
            for (int j = 0; j < keep[i].length; j++)
            {
                keepPart0.add(new DEROctetString(keep[i][j]));
            }
            keepPart1.add(new DERSequence(keepPart0));
            keepPart0 = new ASN1EncodableVector();
        }
        result.add(new DERSequence(keepPart1));

        // --- Encode .
        ASN1EncodableVector curStackPart0 = new ASN1EncodableVector();
        ASN1EncodableVector curStackPart1 = new ASN1EncodableVector();
        for (int i = 0; i < currentStack.length; i++)
        {
            for (int j = 0; j < currentStack[i].size(); j++)
            {
                curStackPart0.add(new DEROctetString((byte[])currentStack[i]
                    .elementAt(j)));
            }
            curStackPart1.add(new DERSequence(curStackPart0));
            curStackPart0 = new ASN1EncodableVector();
        }
        result.add(new DERSequence(curStackPart1));

        // --- Encode .
        ASN1EncodableVector nextStackPart0 = new ASN1EncodableVector();
        ASN1EncodableVector nextStackPart1 = new ASN1EncodableVector();
        for (int i = 0; i < nextStack.length; i++)
        {
            for (int j = 0; j < nextStack[i].size(); j++)
            {
                nextStackPart0.add(new DEROctetString((byte[])nextStack[i]
                    .elementAt(j)));
            }
            nextStackPart1.add(new DERSequence(nextStackPart0));
            nextStackPart0 = new ASN1EncodableVector();
        }
        result.add(new DERSequence(nextStackPart1));

        // --- Encode .
        ASN1EncodableVector currentRetainPart0 = new ASN1EncodableVector();
        ASN1EncodableVector currentRetainPart1 = new ASN1EncodableVector();
        ASN1EncodableVector currentRetainPart2 = new ASN1EncodableVector();
        for (int i = 0; i < currentRetain.length; i++)
        {
            for (int j = 0; j < currentRetain[i].length; j++)
            {
                for (int k = 0; k < currentRetain[i][j].size(); k++)
                {
                    currentRetainPart0.add(new DEROctetString(
                        (byte[])currentRetain[i][j].elementAt(k)));
                }
                currentRetainPart1.add(new DERSequence(currentRetainPart0));
                currentRetainPart0 = new ASN1EncodableVector();
            }
            currentRetainPart2.add(new DERSequence(currentRetainPart1));
            currentRetainPart1 = new ASN1EncodableVector();
        }
        result.add(new DERSequence(currentRetainPart2));

        // --- Encode .
        ASN1EncodableVector nextRetainPart0 = new ASN1EncodableVector();
        ASN1EncodableVector nextRetainPart1 = new ASN1EncodableVector();
        ASN1EncodableVector nextRetainPart2 = new ASN1EncodableVector();
        for (int i = 0; i < nextRetain.length; i++)
        {
            for (int j = 0; j < nextRetain[i].length; j++)
            {
                for (int k = 0; k < nextRetain[i][j].size(); k++)
                {
                    nextRetainPart0.add(new DEROctetString(
                        (byte[])nextRetain[i][j].elementAt(k)));
                }
                nextRetainPart1.add(new DERSequence(nextRetainPart0));
                nextRetainPart0 = new ASN1EncodableVector();
            }
            nextRetainPart2.add(new DERSequence(nextRetainPart1));
            nextRetainPart1 = new ASN1EncodableVector();
        }
        result.add(new DERSequence(nextRetainPart2));

        // --- Encode .
        ASN1EncodableVector seqOfLeaf = new ASN1EncodableVector();
        seqOfStat = new ASN1EncodableVector();
        seqOfByte = new ASN1EncodableVector();
        seqOfInt = new ASN1EncodableVector();

        for (int i = 0; i < nextNextLeaf.length; i++)
        {
            seqOfStat.add(new DERSequence(algorithms[0]));

            byte[][] tempByte = nextNextLeaf[i].getStatByte();
            seqOfByte.add(new DEROctetString(tempByte[0]));
            seqOfByte.add(new DEROctetString(tempByte[1]));
            seqOfByte.add(new DEROctetString(tempByte[2]));
            seqOfByte.add(new DEROctetString(tempByte[3]));
            seqOfStat.add(new DERSequence(seqOfByte));
            seqOfByte = new ASN1EncodableVector();

            int[] tempInt = nextNextLeaf[i].getStatInt();
            seqOfInt.add(new ASN1Integer(tempInt[0]));
            seqOfInt.add(new ASN1Integer(tempInt[1]));
            seqOfInt.add(new ASN1Integer(tempInt[2]));
            seqOfInt.add(new ASN1Integer(tempInt[3]));
            seqOfStat.add(new DERSequence(seqOfInt));
            seqOfInt = new ASN1EncodableVector();

            seqOfLeaf.add(new DERSequence(seqOfStat));
            seqOfStat = new ASN1EncodableVector();
        }
        result.add(new DERSequence(seqOfLeaf));

        // --- Encode .
        ASN1EncodableVector seqOfUpperLeaf = new ASN1EncodableVector();
        seqOfStat = new ASN1EncodableVector();
        seqOfByte = new ASN1EncodableVector();
        seqOfInt = new ASN1EncodableVector();

        for (int i = 0; i < upperLeaf.length; i++)
        {
            seqOfStat.add(new DERSequence(algorithms[0]));

            byte[][] tempByte = upperLeaf[i].getStatByte();
            seqOfByte.add(new DEROctetString(tempByte[0]));
            seqOfByte.add(new DEROctetString(tempByte[1]));
            seqOfByte.add(new DEROctetString(tempByte[2]));
            seqOfByte.add(new DEROctetString(tempByte[3]));
            seqOfStat.add(new DERSequence(seqOfByte));
            seqOfByte = new ASN1EncodableVector();

            int[] tempInt = upperLeaf[i].getStatInt();
            seqOfInt.add(new ASN1Integer(tempInt[0]));
            seqOfInt.add(new ASN1Integer(tempInt[1]));
            seqOfInt.add(new ASN1Integer(tempInt[2]));
            seqOfInt.add(new ASN1Integer(tempInt[3]));
            seqOfStat.add(new DERSequence(seqOfInt));
            seqOfInt = new ASN1EncodableVector();

            seqOfUpperLeaf.add(new DERSequence(seqOfStat));
            seqOfStat = new ASN1EncodableVector();
        }
        result.add(new DERSequence(seqOfUpperLeaf));

        // encode 
        ASN1EncodableVector seqOfUpperTreehashLeaf = new ASN1EncodableVector();
        seqOfStat = new ASN1EncodableVector();
        seqOfByte = new ASN1EncodableVector();
        seqOfInt = new ASN1EncodableVector();

        for (int i = 0; i < upperTreehashLeaf.length; i++)
        {
            seqOfStat.add(new DERSequence(algorithms[0]));

            byte[][] tempByte = upperTreehashLeaf[i].getStatByte();
            seqOfByte.add(new DEROctetString(tempByte[0]));
            seqOfByte.add(new DEROctetString(tempByte[1]));
            seqOfByte.add(new DEROctetString(tempByte[2]));
            seqOfByte.add(new DEROctetString(tempByte[3]));
            seqOfStat.add(new DERSequence(seqOfByte));
            seqOfByte = new ASN1EncodableVector();

            int[] tempInt = upperTreehashLeaf[i].getStatInt();
            seqOfInt.add(new ASN1Integer(tempInt[0]));
            seqOfInt.add(new ASN1Integer(tempInt[1]));
            seqOfInt.add(new ASN1Integer(tempInt[2]));
            seqOfInt.add(new ASN1Integer(tempInt[3]));
            seqOfStat.add(new DERSequence(seqOfInt));
            seqOfInt = new ASN1EncodableVector();

            seqOfUpperTreehashLeaf.add(new DERSequence(seqOfStat));
            seqOfStat = new ASN1EncodableVector();
        }
        result.add(new DERSequence(seqOfUpperTreehashLeaf));

        // --- Encode .
        ASN1EncodableVector minTreehashPart = new ASN1EncodableVector();
        for (int i = 0; i < minTreehash.length; i++)
        {
            minTreehashPart.add(new ASN1Integer(minTreehash[i]));
        }
        result.add(new DERSequence(minTreehashPart));

        // --- Encode .
        ASN1EncodableVector nextRootPart = new ASN1EncodableVector();
        for (int i = 0; i < nextRoot.length; i++)
        {
            nextRootPart.add(new DEROctetString(nextRoot[i]));
        }
        result.add(new DERSequence(nextRootPart));

        // --- Encode .
        ASN1EncodableVector seqOfnextNextRoot = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnnRStats = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnnRStrings = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnnRBytes = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnnRInts = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnnRTreehash = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnnRRetain = new ASN1EncodableVector();

        for (int i = 0; i < nextNextRoot.length; i++)
        {
            seqOfnnRStats.add(new DERSequence(algorithms[0]));
            seqOfnnRStrings = new ASN1EncodableVector();

            int heightOfTree = nextNextRoot[i].getStatInt()[0];
            int tailLength = nextNextRoot[i].getStatInt()[7];

            seqOfnnRBytes.add(new DEROctetString(
                nextNextRoot[i].getStatByte()[0]));
            for (int j = 0; j < heightOfTree; j++)
            {
                seqOfnnRBytes.add(new DEROctetString(nextNextRoot[i]
                    .getStatByte()[1 + j]));
            }
            for (int j = 0; j < tailLength; j++)
            {
                seqOfnnRBytes.add(new DEROctetString(nextNextRoot[i]
                    .getStatByte()[1 + heightOfTree + j]));
            }

            seqOfnnRStats.add(new DERSequence(seqOfnnRBytes));
            seqOfnnRBytes = new ASN1EncodableVector();

            seqOfnnRInts.add(new ASN1Integer(heightOfTree));
            seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[1]));
            seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[2]));
            seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[3]));
            seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[4]));
            seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[5]));
            seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[6]));
            seqOfnnRInts.add(new ASN1Integer(tailLength));
            for (int j = 0; j < heightOfTree; j++)
            {
                seqOfnnRInts.add(new ASN1Integer(
                    nextNextRoot[i].getStatInt()[8 + j]));
            }
            for (int j = 0; j < tailLength; j++)
            {
                seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[8
                    + heightOfTree + j]));
            }

            seqOfnnRStats.add(new DERSequence(seqOfnnRInts));
            seqOfnnRInts = new ASN1EncodableVector();

            // add treehash of nextNextRoot object
            // ----------------------------
            seqOfStat = new ASN1EncodableVector();
            seqOfByte = new ASN1EncodableVector();
            seqOfInt = new ASN1EncodableVector();

            if (nextNextRoot[i].getTreehash() != null)
            {
                for (int j = 0; j < nextNextRoot[i].getTreehash().length; j++)
                {
                    seqOfStat.add(new DERSequence(algorithms[0]));

                    tailLength = nextNextRoot[i].getTreehash()[j].getStatInt()[1];

                    seqOfByte.add(new DEROctetString(nextNextRoot[i]
                        .getTreehash()[j].getStatByte()[0]));
                    seqOfByte.add(new DEROctetString(nextNextRoot[i]
                        .getTreehash()[j].getStatByte()[1]));
                    seqOfByte.add(new DEROctetString(nextNextRoot[i]
                        .getTreehash()[j].getStatByte()[2]));
                    for (int k = 0; k < tailLength; k++)
                    {
                        seqOfByte.add(new DEROctetString(nextNextRoot[i]
                            .getTreehash()[j].getStatByte()[3 + k]));
                    }
                    seqOfStat.add(new DERSequence(seqOfByte));
                    seqOfByte = new ASN1EncodableVector();

                    seqOfInt.add(new ASN1Integer(
                        nextNextRoot[i].getTreehash()[j].getStatInt()[0]));
                    seqOfInt.add(new ASN1Integer(tailLength));
                    seqOfInt.add(new ASN1Integer(
                        nextNextRoot[i].getTreehash()[j].getStatInt()[2]));
                    seqOfInt.add(new ASN1Integer(
                        nextNextRoot[i].getTreehash()[j].getStatInt()[3]));
                    seqOfInt.add(new ASN1Integer(
                        nextNextRoot[i].getTreehash()[j].getStatInt()[4]));
                    seqOfInt.add(new ASN1Integer(
                        nextNextRoot[i].getTreehash()[j].getStatInt()[5]));
                    for (int k = 0; k < tailLength; k++)
                    {
                        seqOfInt.add(new ASN1Integer(nextNextRoot[i]
                            .getTreehash()[j].getStatInt()[6 + k]));
                    }
                    seqOfStat.add(new DERSequence(seqOfInt));
                    seqOfInt = new ASN1EncodableVector();

                    seqOfnnRTreehash.add(new DERSequence(seqOfStat));
                    seqOfStat = new ASN1EncodableVector();
                }
            }
            // ----------------------------
            seqOfnnRStats.add(new DERSequence(seqOfnnRTreehash));
            seqOfnnRTreehash = new ASN1EncodableVector();

            // encode retain of nextNextRoot
            // ----------------------------
            // --- Encode .
            currentRetainPart0 = new ASN1EncodableVector();
            if (nextNextRoot[i].getRetain() != null)
            {
                for (int j = 0; j < nextNextRoot[i].getRetain().length; j++)
                {
                    for (int k = 0; k < nextNextRoot[i].getRetain()[j].size(); k++)
                    {
                        currentRetainPart0.add(new DEROctetString(
                            (byte[])nextNextRoot[i].getRetain()[j]
                                .elementAt(k)));
                    }
                    seqOfnnRRetain.add(new DERSequence(currentRetainPart0));
                    currentRetainPart0 = new ASN1EncodableVector();
                }
            }
            // ----------------------------
            seqOfnnRStats.add(new DERSequence(seqOfnnRRetain));
            seqOfnnRRetain = new ASN1EncodableVector();

            seqOfnextNextRoot.add(new DERSequence(seqOfnnRStats));
            seqOfnnRStats = new ASN1EncodableVector();
        }
        result.add(new DERSequence(seqOfnextNextRoot));

        // --- Encode .
        ASN1EncodableVector curRootSigPart = new ASN1EncodableVector();
        for (int i = 0; i < currentRootSig.length; i++)
        {
            curRootSigPart.add(new DEROctetString(currentRootSig[i]));
        }
        result.add(new DERSequence(curRootSigPart));

        // --- Encode .
        ASN1EncodableVector seqOfnextRootSigs = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnRSStats = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnRSStrings = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnRSBytes = new ASN1EncodableVector();
        ASN1EncodableVector seqOfnRSInts = new ASN1EncodableVector();

        for (int i = 0; i < nextRootSig.length; i++)
        {
            seqOfnRSStats.add(new DERSequence(algorithms[0]));
            seqOfnRSStrings = new ASN1EncodableVector();

            seqOfnRSBytes.add(new DEROctetString(
                nextRootSig[i].getStatByte()[0]));
            seqOfnRSBytes.add(new DEROctetString(
                nextRootSig[i].getStatByte()[1]));
            seqOfnRSBytes.add(new DEROctetString(
                nextRootSig[i].getStatByte()[2]));
            seqOfnRSBytes.add(new DEROctetString(
                nextRootSig[i].getStatByte()[3]));
            seqOfnRSBytes.add(new DEROctetString(
                nextRootSig[i].getStatByte()[4]));

            seqOfnRSStats.add(new DERSequence(seqOfnRSBytes));
            seqOfnRSBytes = new ASN1EncodableVector();

            seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[0]));
            seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[1]));
            seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[2]));
            seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[3]));
            seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[4]));
            seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[5]));
            seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[6]));
            seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[7]));
            seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[8]));

            seqOfnRSStats.add(new DERSequence(seqOfnRSInts));
            seqOfnRSInts = new ASN1EncodableVector();

            seqOfnextRootSigs.add(new DERSequence(seqOfnRSStats));
            seqOfnRSStats = new ASN1EncodableVector();
        }
        result.add(new DERSequence(seqOfnextRootSigs));

        // --- Encode .
        ASN1EncodableVector parSetPart0 = new ASN1EncodableVector();
        ASN1EncodableVector parSetPart1 = new ASN1EncodableVector();
        ASN1EncodableVector parSetPart2 = new ASN1EncodableVector();
        ASN1EncodableVector parSetPart3 = new ASN1EncodableVector();

        for (int i = 0; i < gmssParameterset.getHeightOfTrees().length; i++)
        {
            parSetPart1.add(new ASN1Integer(
                gmssParameterset.getHeightOfTrees()[i]));
            parSetPart2.add(new ASN1Integer(gmssParameterset
                .getWinternitzParameter()[i]));
            parSetPart3.add(new ASN1Integer(gmssParameterset.getK()[i]));
        }
        parSetPart0.add(new ASN1Integer(gmssParameterset.getNumOfLayers()));
        parSetPart0.add(new DERSequence(parSetPart1));
        parSetPart0.add(new DERSequence(parSetPart2));
        parSetPart0.add(new DERSequence(parSetPart3));
        result.add(new DERSequence(parSetPart0));

        // --- Encode .
        ASN1EncodableVector namesPart = new ASN1EncodableVector();

        for (int i = 0; i < algorithms.length; i++)
        {
            namesPart.add(algorithms[i]);
        }

        result.add(new DERSequence(namesPart));
        return new DERSequence(result);

    }

    private static int checkBigIntegerInIntRange(ASN1Encodable a)
    {
        return ((ASN1Integer)a).intValueExact();
    }

    public ASN1Primitive toASN1Primitive()
    {
        return this.primitive;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy