code:     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));
      }
  
      /**
       * calculates the authpath for tree in layer h which starts with seed[h]
       * additionally computes the rootSignature of underlaying root
       *
       * @param currentStack stack used for the treehash instance created by this method
       * @param lowerRoot    stores the root of the lower tree
       * @param seed        starting seeds
       * @param h            actual layer
       */
  