package org.bouncycastle.pqc.asn1; import java.math.BigInteger; 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.crypto.gmss.GMSSLeaf; import org.bouncycastle.pqc.crypto.gmss.GMSSParameters; import org.bouncycastle.pqc.crypto.gmss.GMSSRootCalc; import org.bouncycastle.pqc.crypto.gmss.GMSSRootSig; import org.bouncycastle.pqc.crypto.gmss.Treehash; public class GMSSPrivateKey extends ASN1Object { private ASN1Primitive primitive; private GMSSPrivateKey(ASN1Sequence mtsPrivateKey) { // --- Decode <index>. 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 <curSeeds>. 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 <nextNextSeeds>. 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 <curAuth>. 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 <nextAuth>. 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 <curTreehash>. 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 <nextTreehash>. 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 <keep>. 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 <curStack>. 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 <nextStack>. 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 <curRetain>. 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 <nextRetain>. 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 <nextNextLeaf>. 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 <upperLeaf>. 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 <upperTreehashLeaf>. 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 <minTreehash>. 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 <nextRoot>. 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 <nextNextRoot>. 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 <curRootSig>. 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 <nextRootSig>. 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 <name>. // 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 <index>. ASN1EncodableVector indexPart = new ASN1EncodableVector(); for (int i = 0; i < index.length; i++) { indexPart.add(new ASN1Integer(index[i])); } result.add(new DERSequence(indexPart)); // --- Encode <curSeeds>. ASN1EncodableVector curSeedsPart = new ASN1EncodableVector(); for (int i = 0; i < currentSeeds.length; i++) { curSeedsPart.add(new DEROctetString(currentSeeds[i])); } result.add(new DERSequence(curSeedsPart)); // --- Encode <nextNextSeeds>. ASN1EncodableVector nextNextSeedsPart = new ASN1EncodableVector(); for (int i = 0; i < nextNextSeeds.length; i++) { nextNextSeedsPart.add(new DEROctetString(nextNextSeeds[i])); } result.add(new DERSequence(nextNextSeedsPart)); // --- Encode <curAuth>. 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 <nextAuth>. 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 <curTreehash>. 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 <nextTreehash>. 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 <keep>. 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 <curStack>. 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 <nextStack>. 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 <curRetain>. 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 <nextRetain>. 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 <nextNextLeaf>. 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 <upperLEAF>. 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 <upperTreehashLeaf> 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 <minTreehash>. ASN1EncodableVector minTreehashPart = new ASN1EncodableVector(); for (int i = 0; i < minTreehash.length; i++) { minTreehashPart.add(new ASN1Integer(minTreehash[i])); } result.add(new DERSequence(minTreehashPart)); // --- Encode <nextRoot>. ASN1EncodableVector nextRootPart = new ASN1EncodableVector(); for (int i = 0; i < nextRoot.length; i++) { nextRootPart.add(new DEROctetString(nextRoot[i])); } result.add(new DERSequence(nextRootPart)); // --- Encode <nextNextRoot>. 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 <curRetain>. 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 <curRootSig>. ASN1EncodableVector curRootSigPart = new ASN1EncodableVector(); for (int i = 0; i < currentRootSig.length; i++) { curRootSigPart.add(new DEROctetString(currentRootSig[i])); } result.add(new DERSequence(curRootSigPart)); // --- Encode <nextRootSig>. 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 <parameterset>. 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 <names>. 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) { BigInteger b = ((ASN1Integer)a).getValue(); if ((b.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) || (b.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0)) { throw new IllegalArgumentException("BigInteger not in Range: " + b.toString()); } return b.intValue(); } public ASN1Primitive toASN1Primitive() { return this.primitive; } }