//  [java]
    private AsymmetricCipherKeyPair genKeyPair()
    {
        if (!initialized)
        {
            initializeDefault();
        }

        // initialize authenticationPaths and treehash instances
        byte[][][] currentAuthPaths = new byte[numLayer][][];
        byte[][][] nextAuthPaths = new byte[numLayer - 1][][];
        Treehash[][] currentTreehash = new Treehash[numLayer][];
        Treehash[][] nextTreehash = new Treehash[numLayer - 1][];

        Vector[] currentStack = new Vector[numLayer];
        Vector[] nextStack = new Vector[numLayer - 1];

        Vector[][] currentRetain = new Vector[numLayer][];
        Vector[][] nextRetain = new Vector[numLayer - 1][];

        for (int i = 0; i < numLayer; i++)
        {
            currentAuthPaths[i] = new byte[heightOfTrees[i]][mdLength];
            currentTreehash[i] = new Treehash[heightOfTrees[i] - K[i]];

            if (i > 0)
            {
                nextAuthPaths[i - 1] = new byte[heightOfTrees[i]][mdLength];
                nextTreehash[i - 1] = new Treehash[heightOfTrees[i] - K[i]];
            }

            currentStack[i] = new Vector();
            if (i > 0)
            {
                nextStack[i - 1] = new Vector();
            }
        }

        // initialize roots
        byte[][] currentRoots = new byte[numLayer][mdLength];
        byte[][] nextRoots = new byte[numLayer - 1][mdLength];
        // initialize seeds
        byte[][] seeds = new byte[numLayer][mdLength];
        // initialize seeds[] by copying starting-seeds of first trees of each
        // layer
        for (int i = 0; i < numLayer; i++)
        {
            System.arraycopy(currentSeeds[i], 0, seeds[i], 0, mdLength);
        }

        // initialize rootSigs
        currentRootSigs = new byte[numLayer - 1][mdLength];

        // -------------------------
        // -------------------------
        // --- calculation of current authpaths and current rootsigs (AUTHPATHS,
        // SIG)------
        // from bottom up to the root
        for (int h = numLayer - 1; h >= 0; h--)
        {
            GMSSRootCalc tree = new GMSSRootCalc(this.heightOfTrees[h], this.K[h], digestProvider);
            try
            {
                // on lowest layer no lower root is available, so just call
                // the method with null as first parameter
                if (h == numLayer - 1)
                {
                    tree = this.generateCurrentAuthpathAndRoot(null, currentStack[h], seeds[h], h);
                }
                else
                // otherwise call the method with the former computed root
                // value
                {
                    tree = this.generateCurrentAuthpathAndRoot(currentRoots[h + 1], currentStack[h], seeds[h], h);
                }

            }
            catch (Exception e1)
            {
                e1.printStackTrace();
            }

            // set initial values needed for the private key construction
            for (int i = 0; i < heightOfTrees[h]; i++)
            {
                System.arraycopy(tree.getAuthPath()[i], 0, currentAuthPaths[h][i], 0, mdLength);
            }
            currentRetain[h] = tree.getRetain();
            currentTreehash[h] = tree.getTreehash();
            System.arraycopy(tree.getRoot(), 0, currentRoots[h], 0, mdLength);
        }

        // --- calculation of next authpaths and next roots (AUTHPATHS+, ROOTS+)
        // ------
        for (int h = numLayer - 2; h >= 0; h--)
        {
            GMSSRootCalc tree = this.generateNextAuthpathAndRoot(nextStack[h], seeds[h + 1], h + 1);

            // set initial values needed for the private key construction
            for (int i = 0; i < heightOfTrees[h + 1]; i++)
            {
                System.arraycopy(tree.getAuthPath()[i], 0, nextAuthPaths[h][i], 0, mdLength);
            }
            nextRetain[h] = tree.getRetain();
            nextTreehash[h] = tree.getTreehash();
            System.arraycopy(tree.getRoot(), 0, nextRoots[h], 0, mdLength);

            // create seed for the Merkle tree after next (nextNextSeeds)
            // SEEDs++
            System.arraycopy(seeds[h + 1], 0, this.nextNextSeeds[h], 0, mdLength);
        }
        // ------------

        // generate JDKGMSSPublicKey
        GMSSPublicKeyParameters publicKey = new GMSSPublicKeyParameters(currentRoots[0], gmssPS);

        // generate the JDKGMSSPrivateKey
        GMSSPrivateKeyParameters privateKey = new GMSSPrivateKeyParameters(currentSeeds, nextNextSeeds, currentAuthPaths,
            nextAuthPaths, currentTreehash, nextTreehash, currentStack, nextStack, currentRetain, nextRetain, nextRoots, currentRootSigs, gmssPS, digestProvider);

        // return the KeyPair
        return (new AsymmetricCipherKeyPair(publicKey, privateKey));
    }