Beispiel #1
0
  /** Initializes the signature algorithm for signing a message. */
  private void initSign() {
    messDigestTrees.reset();
    // set private key and take from it ots key, auth, tree and key
    // counter, rootSign
    GMSSPrivateKeyParameters gmssPrivateKey = (GMSSPrivateKeyParameters) key;

    if (gmssPrivateKey.isUsed()) {
      throw new IllegalStateException("Private key already used");
    }

    // check if last signature has been generated
    if (gmssPrivateKey.getIndex(0) >= gmssPrivateKey.getNumLeafs(0)) {
      throw new IllegalStateException("No more signatures can be generated");
    }

    // get Parameterset
    this.gmssPS = gmssPrivateKey.getParameters();
    // get numLayer
    this.numLayer = gmssPS.getNumOfLayers();

    // get OTS Instance of lowest layer
    byte[] seed = gmssPrivateKey.getCurrentSeeds()[numLayer - 1];
    byte[] OTSSeed = new byte[mdLength];
    byte[] dummy = new byte[mdLength];
    System.arraycopy(seed, 0, dummy, 0, mdLength);
    OTSSeed =
        gmssRandom.nextSeed(
            dummy); // secureRandom.nextBytes(currentSeeds[currentSeeds.length-1]);secureRandom.nextBytes(OTSseed);
    this.ots =
        new WinternitzOTSignature(
            OTSSeed, digestProvider.get(), gmssPS.getWinternitzParameter()[numLayer - 1]);

    byte[][][] helpCurrentAuthPaths = gmssPrivateKey.getCurrentAuthPaths();
    currentAuthPaths = new byte[numLayer][][];

    // copy the main tree authentication path
    for (int j = 0; j < numLayer; j++) {
      currentAuthPaths[j] = new byte[helpCurrentAuthPaths[j].length][mdLength];
      for (int i = 0; i < helpCurrentAuthPaths[j].length; i++) {
        System.arraycopy(helpCurrentAuthPaths[j][i], 0, currentAuthPaths[j][i], 0, mdLength);
      }
    }

    // copy index
    index = new int[numLayer];
    System.arraycopy(gmssPrivateKey.getIndex(), 0, index, 0, numLayer);

    // copy subtreeRootSig
    byte[] helpSubtreeRootSig;
    subtreeRootSig = new byte[numLayer - 1][];
    for (int i = 0; i < numLayer - 1; i++) {
      helpSubtreeRootSig = gmssPrivateKey.getSubtreeRootSig(i);
      subtreeRootSig[i] = new byte[helpSubtreeRootSig.length];
      System.arraycopy(helpSubtreeRootSig, 0, subtreeRootSig[i], 0, helpSubtreeRootSig.length);
    }

    gmssPrivateKey.markUsed();
  }
Beispiel #2
0
  /** Initializes the signature algorithm for verifying a signature. */
  private void initVerify() {
    messDigestTrees.reset();

    GMSSPublicKeyParameters gmssPublicKey = (GMSSPublicKeyParameters) key;
    pubKeyBytes = gmssPublicKey.getPublicKey();
    gmssPS = gmssPublicKey.getParameters();
    // get numLayer
    this.numLayer = gmssPS.getNumOfLayers();
  }
Beispiel #3
0
  /**
   * This function verifies the signature of the message that has been updated, with the aid of the
   * public key.
   *
   * @param message the message
   * @param signature the signature associated with the message
   * @return true if the signature has been verified, false otherwise.
   */
  public boolean verifySignature(byte[] message, byte[] signature) {

    boolean success = false;
    // int halfSigLength = signature.length >>> 1;
    messDigestOTS.reset();
    WinternitzOTSVerify otsVerify;
    int otsSigLength;

    byte[] help = message;

    byte[] otsSig;
    byte[] otsPublicKey;
    byte[][] authPath;
    byte[] dest;
    int nextEntry = 0;
    int index;
    // Verify signature

    // --- begin with message = 'message that was signed'
    // and then in each step message = subtree root
    for (int j = numLayer - 1; j >= 0; j--) {
      otsVerify = new WinternitzOTSVerify(digestProvider.get(), gmssPS.getWinternitzParameter()[j]);
      otsSigLength = otsVerify.getSignatureLength();

      message = help;
      // get the subtree index
      index = gmssUtil.bytesToIntLittleEndian(signature, nextEntry);

      // 4 is the number of bytes in integer
      nextEntry += 4;

      // get one-time signature
      otsSig = new byte[otsSigLength];
      System.arraycopy(signature, nextEntry, otsSig, 0, otsSigLength);
      nextEntry += otsSigLength;

      // compute public OTS key from the one-time signature
      otsPublicKey = otsVerify.Verify(message, otsSig);

      // test if OTSsignature is correct
      if (otsPublicKey == null) {
        System.err.println("OTS Public Key is null in GMSSSignature.verify");
        return false;
      }

      // get authentication path from the signature
      authPath = new byte[gmssPS.getHeightOfTrees()[j]][mdLength];
      for (int i = 0; i < authPath.length; i++) {
        System.arraycopy(signature, nextEntry, authPath[i], 0, mdLength);
        nextEntry = nextEntry + mdLength;
      }

      // compute the root of the subtree from the authentication path
      help = new byte[mdLength];

      help = otsPublicKey;

      int count = 1 << authPath.length;
      count = count + index;

      for (int i = 0; i < authPath.length; i++) {
        dest = new byte[mdLength << 1];

        if ((count % 2) == 0) {
          System.arraycopy(help, 0, dest, 0, mdLength);
          System.arraycopy(authPath[i], 0, dest, mdLength, mdLength);
          count = count / 2;
        } else {
          System.arraycopy(authPath[i], 0, dest, 0, mdLength);
          System.arraycopy(help, 0, dest, mdLength, help.length);
          count = (count - 1) / 2;
        }
        messDigestTrees.update(dest, 0, dest.length);
        help = new byte[messDigestTrees.getDigestSize()];
        messDigestTrees.doFinal(help, 0);
      }
    }

    // now help contains the root of the maintree

    // test if help is equal to the GMSS public key
    if (Arrays.areEqual(pubKeyBytes, help)) {
      success = true;
    }

    return success;
  }
  /**
   * /**
   *
   * @param index tree indices
   * @param currentSeed seed for the generation of private OTS keys for the current subtrees (TREE)
   * @param nextNextSeed seed for the generation of private OTS keys for the subtrees after next
   *     (TREE++)
   * @param currentAuthPath array of current authentication paths (AUTHPATH)
   * @param nextAuthPath 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 digestClass An array of strings, containing the name of the used hash function and the
   *     name of the corresponding provider
   */
  public GMSSPrivateKeyParameters(
      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,
      GMSSDigestProvider digestProvider) {

    super(true, gmssParameterset);

    // construct message digest

    this.messDigestTrees = digestProvider.get();
    this.mdLength = messDigestTrees.getDigestSize();

    // Parameter
    this.gmssPS = gmssParameterset;
    this.otsIndex = gmssParameterset.getWinternitzParameter();
    this.K = gmssParameterset.getK();
    this.heightOfTrees = gmssParameterset.getHeightOfTrees();
    // initialize numLayer
    this.numLayer = gmssPS.getNumOfLayers();

    // initialize index if null
    if (index == null) {
      this.index = new int[numLayer];
      for (int i = 0; i < numLayer; i++) {
        this.index[i] = 0;
      }
    } else {
      this.index = index;
    }

    this.currentSeeds = currentSeeds;
    this.nextNextSeeds = nextNextSeeds;

    this.currentAuthPaths = currentAuthPaths;
    this.nextAuthPaths = nextAuthPaths;

    // initialize keep if null
    if (keep == null) {
      this.keep = new byte[numLayer][][];
      for (int i = 0; i < numLayer; i++) {
        this.keep[i] = new byte[(int) Math.floor(heightOfTrees[i] / 2)][mdLength];
      }
    } else {
      this.keep = keep;
    }

    // initialize stack if null
    if (currentStack == null) {
      this.currentStack = new Vector[numLayer];
      for (int i = 0; i < numLayer; i++) {
        this.currentStack[i] = new Vector();
      }
    } else {
      this.currentStack = currentStack;
    }

    // initialize nextStack if null
    if (nextStack == null) {
      this.nextStack = new Vector[numLayer - 1];
      for (int i = 0; i < numLayer - 1; i++) {
        this.nextStack[i] = new Vector();
      }
    } else {
      this.nextStack = nextStack;
    }

    this.currentTreehash = currentTreehash;
    this.nextTreehash = nextTreehash;

    this.currentRetain = currentRetain;
    this.nextRetain = nextRetain;

    this.nextRoot = nextRoot;

    this.digestProvider = digestProvider;

    if (nextNextRoot == null) {
      this.nextNextRoot = new GMSSRootCalc[numLayer - 1];
      for (int i = 0; i < numLayer - 1; i++) {
        this.nextNextRoot[i] =
            new GMSSRootCalc(this.heightOfTrees[i + 1], this.K[i + 1], this.digestProvider);
      }
    } else {
      this.nextNextRoot = nextNextRoot;
    }
    this.currentRootSig = currentRootSig;

    // calculate numLeafs
    numLeafs = new int[numLayer];
    for (int i = 0; i < numLayer; i++) {
      numLeafs[i] = 1 << heightOfTrees[i];
    }
    // construct PRNG
    this.gmssRandom = new GMSSRandom(messDigestTrees);

    if (numLayer > 1) {
      // construct the nextNextLeaf (LEAFs++) array for upcoming leafs in
      // tree after next (TREE++)
      if (nextNextLeaf == null) {
        this.nextNextLeaf = new GMSSLeaf[numLayer - 2];
        for (int i = 0; i < numLayer - 2; i++) {
          this.nextNextLeaf[i] =
              new GMSSLeaf(digestProvider.get(), otsIndex[i + 1], numLeafs[i + 2]);
          this.nextNextLeaf[i].initLeafCalc(this.nextNextSeeds[i]);
        }
      } else {
        this.nextNextLeaf = nextNextLeaf;
      }
    } else {
      this.nextNextLeaf = new GMSSLeaf[0];
    }

    // construct the upperLeaf array for upcoming leafs in tree over the
    // actual
    if (upperLeaf == null) {
      this.upperLeaf = new GMSSLeaf[numLayer - 1];
      for (int i = 0; i < numLayer - 1; i++) {
        this.upperLeaf[i] = new GMSSLeaf(digestProvider.get(), otsIndex[i], numLeafs[i + 1]);
        this.upperLeaf[i].initLeafCalc(this.currentSeeds[i]);
      }
    } else {
      this.upperLeaf = upperLeaf;
    }

    // construct the leafs for upcoming leafs in treehashs in tree over the
    // actual
    if (upperTreehashLeaf == null) {
      this.upperTreehashLeaf = new GMSSLeaf[numLayer - 1];
      for (int i = 0; i < numLayer - 1; i++) {
        this.upperTreehashLeaf[i] =
            new GMSSLeaf(digestProvider.get(), otsIndex[i], numLeafs[i + 1]);
      }
    } else {
      this.upperTreehashLeaf = upperTreehashLeaf;
    }

    if (minTreehash == null) {
      this.minTreehash = new int[numLayer - 1];
      for (int i = 0; i < numLayer - 1; i++) {
        this.minTreehash[i] = -1;
      }
    } else {
      this.minTreehash = minTreehash;
    }

    // construct the nextRootSig (RootSig++)
    byte[] dummy = new byte[mdLength];
    byte[] OTSseed = new byte[mdLength];
    if (nextRootSig == null) {
      this.nextRootSig = new GMSSRootSig[numLayer - 1];
      for (int i = 0; i < numLayer - 1; i++) {
        System.arraycopy(currentSeeds[i], 0, dummy, 0, mdLength);
        gmssRandom.nextSeed(dummy);
        OTSseed = gmssRandom.nextSeed(dummy);
        this.nextRootSig[i] =
            new GMSSRootSig(digestProvider.get(), otsIndex[i], heightOfTrees[i + 1]);
        this.nextRootSig[i].initSign(OTSseed, nextRoot[i]);
      }
    } else {
      this.nextRootSig = nextRootSig;
    }
  }