예제 #1
0
  /** generate a signature for the loaded message using the key we were initialised with. */
  public byte[] generateSignature() throws CryptoException {
    int digSize = digest.getDigestSize();

    int t = 0;
    int delta = 0;

    if (trailer == TRAILER_IMPLICIT) {
      t = 8;
      delta = block.length - digSize - 1;
      digest.doFinal(block, delta);
      block[block.length - 1] = (byte) TRAILER_IMPLICIT;
    } else {
      t = 16;
      delta = block.length - digSize - 2;
      digest.doFinal(block, delta);
      block[block.length - 2] = (byte) (trailer >>> 8);
      block[block.length - 1] = (byte) trailer;
    }

    byte header = 0;
    int x = (digSize + messageLength) * 8 + t + 4 - keyBits;

    if (x > 0) {
      int mR = messageLength - ((x + 7) / 8);
      header = 0x60;

      delta -= mR;

      System.arraycopy(mBuf, 0, block, delta, mR);
    } else {
      header = 0x40;
      delta -= messageLength;

      System.arraycopy(mBuf, 0, block, delta, messageLength);
    }

    if ((delta - 1) > 0) {
      for (int i = delta - 1; i != 0; i--) {
        block[i] = (byte) 0xbb;
      }
      block[delta - 1] ^= (byte) 0x01;
      block[0] = (byte) 0x0b;
      block[0] |= header;
    } else {
      block[0] = (byte) 0x0a;
      block[0] |= header;
    }

    byte[] b = cipher.processBlock(block, 0, block.length);

    clearBlock(mBuf);
    clearBlock(block);

    return b;
  }
  /** the derived key function, the ith hash of the password and the salt. */
  private byte[] generateDerivedKey() {
    byte[] digestBytes = new byte[digest.getDigestSize()];

    digest.update(password, 0, password.length);
    digest.update(salt, 0, salt.length);

    digest.doFinal(digestBytes, 0);
    for (int i = 1; i < iterationCount; i++) {
      digest.update(digestBytes, 0, digestBytes.length);
      digest.doFinal(digestBytes, 0);
    }

    return digestBytes;
  }
예제 #3
0
 public static byte[] hashContents(byte[] contents) {
   final Digest digest = new SHA256Digest();
   digest.update(contents, 0, contents.length);
   final byte[] digestValue = new byte[digest.getDigestSize()];
   digest.doFinal(digestValue, 0);
   return digestValue;
 }
예제 #4
0
  protected byte[] engineSign() throws SignatureException {
    byte[] hash = new byte[digest.getDigestSize()];

    digest.doFinal(hash, 0);

    try {
      byte[] sigBytes = new byte[64];
      BigInteger[] sig = signer.generateSignature(hash);
      byte[] r = sig[0].toByteArray();
      byte[] s = sig[1].toByteArray();

      if (s[0] != 0) {
        System.arraycopy(s, 0, sigBytes, 32 - s.length, s.length);
      } else {
        System.arraycopy(s, 1, sigBytes, 32 - (s.length - 1), s.length - 1);
      }

      if (r[0] != 0) {
        System.arraycopy(r, 0, sigBytes, 64 - r.length, r.length);
      } else {
        System.arraycopy(r, 1, sigBytes, 64 - (r.length - 1), r.length - 1);
      }

      return sigBytes;
    } catch (Exception e) {
      throw new SignatureException(e.toString());
    }
  }
예제 #5
0
  private void appendHash(BitString m, byte[] hash) {
    hashAlg.update(seed, 0, seed.length);

    putInt(hashAlg, counter);

    hashAlg.doFinal(hash, 0);

    m.appendBits(hash);
  }
  /**
   * fill len bytes of the output buffer with bytes generated from the derivation function.
   *
   * @throws IllegalArgumentException if the size of the request will cause an overflow.
   * @throws DataLengthException if the out buffer is too small.
   */
  public int generateBytes(byte[] out, int outOff, int len)
      throws DataLengthException, IllegalArgumentException {
    if ((out.length - len) < outOff) {
      throw new DataLengthException("output buffer too small");
    }

    long oBytes = len;
    int outLen = digest.getDigestSize();

    //
    // this is at odds with the standard implementation, the
    // maximum value should be hBits * (2^32 - 1) where hBits
    // is the digest output size in bits. We can't have an
    // array with a long index at the moment...
    //
    if (oBytes > ((2L << 32) - 1)) {
      throw new IllegalArgumentException("Output length too large");
    }

    int cThreshold = (int) ((oBytes + outLen - 1) / outLen);

    byte[] dig = new byte[digest.getDigestSize()];

    byte[] C = new byte[4];
    Pack.intToBigEndian(counterStart, C, 0);

    int counterBase = counterStart & ~0xFF;

    for (int i = 0; i < cThreshold; i++) {
      digest.update(shared, 0, shared.length);
      digest.update(C, 0, C.length);

      if (iv != null) {
        digest.update(iv, 0, iv.length);
      }

      digest.doFinal(dig, 0);

      if (len > outLen) {
        System.arraycopy(dig, 0, out, outOff, outLen);
        outOff += outLen;
        len -= outLen;
      } else {
        System.arraycopy(dig, 0, out, outOff, len);
      }

      if (++C[3] == 0) {
        counterBase += 0x100;
        Pack.intToBigEndian(counterBase, C, 0);
      }
    }

    digest.reset();

    return (int) oBytes;
  }
  /**
   * Some key wrap algorithms make use of the Key Checksum defined in CMS [CMS-Algorithms]. This is
   * used to provide an integrity check value for the key being wrapped. The algorithm is
   *
   * <p>- Compute the 20 octet SHA-1 hash on the key being wrapped. - Use the first 8 octets of this
   * hash as the checksum value.
   *
   * @param key
   * @return the CMS checksum.
   * @throws RuntimeException
   * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
   */
  private byte[] calculateCMSKeyChecksum(byte[] key) {
    byte[] result = new byte[8];

    sha1.update(key, 0, key.length);
    sha1.doFinal(digest, 0);

    System.arraycopy(digest, 0, result, 0, 8);

    return result;
  }
예제 #8
0
  /**
   * Computes the digest for the given data in a single operation.
   *
   * @param input Data to be digested.
   * @return Message digest as byte array.
   */
  public byte[] digest(final byte[] input) {
    if (salt != null) {
      digest.update(salt, 0, salt.length);
    }
    digest.update(input, 0, input.length);

    final byte[] hash = new byte[digest.getDigestSize()];
    digest.doFinal(hash, 0);
    return hash;
  }
예제 #9
0
  private void testDetachedRSA() throws Exception {
    Digest md = new SHA1Digest();
    List certList = new ArrayList();
    CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes());

    certList.add(_origCert);
    certList.add(_signCert);

    Store certs = new CollectionStore(certList);

    CMSSignedDataGenerator gen = new CMSSignedDataGenerator();

    byte[] digValue = new byte[md.getDigestSize()];
    byte[] data = "Hello world!".getBytes();

    md.update(data, 0, data.length);
    md.doFinal(digValue, 0);

    Attribute attr =
        new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(digValue)));

    ASN1EncodableVector v = new ASN1EncodableVector();

    v.add(attr);

    AsymmetricKeyParameter privKey = (AsymmetricKeyParameter) _origKP.getPrivate();

    AlgorithmIdentifier sigAlgId =
        new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA");
    AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);

    BcContentSignerBuilder contentSignerBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId);

    gen.addSignerInfoGenerator(
        new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider())
            .setSignedAttributeGenerator(
                new DefaultSignedAttributeTableGenerator(new AttributeTable(v)))
            .build(contentSignerBuilder.build(privKey), _origCert));

    gen.addCertificates(certs);

    CMSSignedData s = gen.generate(new CMSAbsentContent(), false);

    //
    // the signature is detached, so need to add msg before passing on
    //
    s = new CMSSignedData(msg, s.getEncoded());
    //
    // compute expected content digest
    //

    verifyRSASignatures(s, digValue);
  }
예제 #10
0
 public boolean isPublicKeyBlackListed(PublicKey publicKey) {
   byte[] encoded = publicKey.getEncoded();
   Digest digest = AndroidDigestFactory.getSHA1();
   digest.update(encoded, 0, encoded.length);
   byte[] out = new byte[digest.getDigestSize()];
   digest.doFinal(out, 0);
   for (byte[] blacklisted : pubkeyBlacklist) {
     if (Arrays.equals(blacklisted, Hex.encode(out))) {
       return true;
     }
   }
   return false;
 }
예제 #11
0
  /**
   * Calculates the MacKey (i.e. the key to use when calculating the MagTag for key confirmation).
   *
   * <p>
   *
   * <p>
   *
   * <pre>
   * MacKey = H(K || "JPAKE_KC")
   * </pre>
   */
  private static byte[] calculateMacKey(BigInteger keyingMaterial, Digest digest) {
    digest.reset();

    updateDigest(digest, keyingMaterial);
    /*
     * This constant is used to ensure that the macKey is NOT the same as the derived key.
     */
    updateDigest(digest, "JPAKE_KC");

    byte[] output = new byte[digest.getDigestSize()];
    digest.doFinal(output, 0);

    return output;
  }
예제 #12
0
  private static BigInteger calculateHashForZeroKnowledgeProof(
      BigInteger g, BigInteger gr, BigInteger gx, String participantId, Digest digest) {
    digest.reset();

    updateDigestIncludingSize(digest, g);

    updateDigestIncludingSize(digest, gr);

    updateDigestIncludingSize(digest, gx);

    updateDigestIncludingSize(digest, participantId);

    byte[] output = new byte[digest.getDigestSize()];
    digest.doFinal(output, 0);

    return new BigInteger(output);
  }
예제 #13
0
  /**
   * Computes the digest for all the data in the stream by reading data and hashing it in chunks.
   *
   * @param in Input stream containing data to be digested.
   * @return Message digest as byte array.
   * @throws IOException On input stream read errors.
   */
  public byte[] digest(final InputStream in) throws IOException {
    if (in == null) {
      throw new IllegalArgumentException("Input stream cannot be null.");
    }

    final byte[] buffer = new byte[CHUNK_SIZE];
    int count;
    if (salt != null) {
      digest.update(salt, 0, salt.length);
    }
    while ((count = in.read(buffer, 0, CHUNK_SIZE)) > 0) {
      digest.update(buffer, 0, count);
    }

    final byte[] hash = new byte[digest.getDigestSize()];
    digest.doFinal(hash, 0);
    return hash;
  }
  public byte[] calculateFingerprint(PublicKeyPacket publicPk) throws PGPException {
    BCPGKey key = publicPk.getKey();
    Digest digest;

    if (publicPk.getVersion() <= 3) {
      RSAPublicBCPGKey rK = (RSAPublicBCPGKey) key;

      try {
        digest = new MD5Digest();

        byte[] bytes = new MPInteger(rK.getModulus()).getEncoded();
        digest.update(bytes, 2, bytes.length - 2);

        bytes = new MPInteger(rK.getPublicExponent()).getEncoded();
        digest.update(bytes, 2, bytes.length - 2);
      } catch (IOException e) {
        throw new PGPException("can't encode key components: " + e.getMessage(), e);
      }
    } else {
      try {
        byte[] kBytes = publicPk.getEncodedContents();

        digest = new SHA1Digest();

        digest.update((byte) 0x99);
        digest.update((byte) (kBytes.length >> 8));
        digest.update((byte) kBytes.length);
        digest.update(kBytes, 0, kBytes.length);
      } catch (IOException e) {
        throw new PGPException("can't encode key components: " + e.getMessage(), e);
      }
    }

    byte[] digBuf = new byte[digest.getDigestSize()];

    digest.doFinal(digBuf, 0);

    return digBuf;
  }
예제 #15
0
  protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
    byte[] hash = new byte[digest.getDigestSize()];

    digest.doFinal(hash, 0);

    BigInteger[] sig;

    try {
      byte[] r = new byte[32];
      byte[] s = new byte[32];

      System.arraycopy(sigBytes, 0, s, 0, 32);

      System.arraycopy(sigBytes, 32, r, 0, 32);

      sig = new BigInteger[2];
      sig[0] = new BigInteger(1, r);
      sig[1] = new BigInteger(1, s);
    } catch (Exception e) {
      throw new SignatureException("error decoding signature bytes.");
    }

    return signer.verifySignature(hash, sig[0], sig[1]);
  }
  /**
   * Computes the upcoming currentAuthpath of layer <code>layer</code> using the revisited
   * authentication path computation of Dahmen/Schneider 2008
   *
   * @param layer the actual layer
   */
  private void computeAuthPaths(int layer) {

    int Phi = index[layer];
    int H = heightOfTrees[layer];
    int K = this.K[layer];

    // update all nextSeeds for seed scheduling
    for (int i = 0; i < H - K; i++) {
      currentTreehash[layer][i].updateNextSeed(gmssRandom);
    }

    // STEP 1 of Algorithm
    int Tau = heightOfPhi(Phi);

    byte[] OTSseed = new byte[mdLength];
    OTSseed = gmssRandom.nextSeed(currentSeeds[layer]);

    // STEP 2 of Algorithm
    // if phi's parent on height tau + 1 if left node, store auth_tau
    // in keep_tau.
    // TODO check it, formerly was
    // int L = Phi / (int) Math.floor(Math.pow(2, Tau + 1));
    // L %= 2;
    int L = (Phi >>> (Tau + 1)) & 1;

    byte[] tempKeep = new byte[mdLength];
    // store the keep node not in keep[layer][tau/2] because it might be in
    // use
    // wait until the space is freed in step 4a
    if (Tau < H - 1 && L == 0) {
      System.arraycopy(currentAuthPaths[layer][Tau], 0, tempKeep, 0, mdLength);
    }

    byte[] help = new byte[mdLength];
    // STEP 3 of Algorithm
    // if phi is left child, compute and store leaf for next currentAuthPath
    // path,
    // (obtained by veriying current signature)
    if (Tau == 0) {
      // LEAFCALC !!!
      if (layer == numLayer - 1) { // lowest layer computes the
        // necessary leaf completely at this
        // time
        WinternitzOTSignature ots =
            new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[layer]);
        help = ots.getPublicKey();
      } else { // other layers use the precomputed leafs in
        // nextNextLeaf
        byte[] dummy = new byte[mdLength];
        System.arraycopy(currentSeeds[layer], 0, dummy, 0, mdLength);
        gmssRandom.nextSeed(dummy);
        help = upperLeaf[layer].getLeaf();
        this.upperLeaf[layer].initLeafCalc(dummy);

        // WinternitzOTSVerify otsver = new
        // WinternitzOTSVerify(algNames, otsIndex[layer]);
        // byte[] help2 = otsver.Verify(currentRoot[layer],
        // currentRootSig[layer]);
        // System.out.println(" --- " + layer + " " +
        // ByteUtils.toHexString(help) + " " +
        // ByteUtils.toHexString(help2));
      }
      System.arraycopy(help, 0, currentAuthPaths[layer][0], 0, mdLength);
    } else {
      // STEP 4a of Algorithm
      // get new left currentAuthPath node on height tau
      byte[] toBeHashed = new byte[mdLength << 1];
      System.arraycopy(currentAuthPaths[layer][Tau - 1], 0, toBeHashed, 0, mdLength);
      // free the shared keep[layer][tau/2]
      System.arraycopy(
          keep[layer][(int) Math.floor((Tau - 1) / 2)], 0, toBeHashed, mdLength, mdLength);
      messDigestTrees.update(toBeHashed, 0, toBeHashed.length);
      currentAuthPaths[layer][Tau] = new byte[messDigestTrees.getDigestSize()];
      messDigestTrees.doFinal(currentAuthPaths[layer][Tau], 0);

      // STEP 4b and 4c of Algorithm
      // copy right nodes to currentAuthPath on height 0..Tau-1
      for (int i = 0; i < Tau; i++) {

        // STEP 4b of Algorithm
        // 1st: copy from treehashs
        if (i < H - K) {
          if (currentTreehash[layer][i].wasFinished()) {
            System.arraycopy(
                currentTreehash[layer][i].getFirstNode(),
                0,
                currentAuthPaths[layer][i],
                0,
                mdLength);
            currentTreehash[layer][i].destroy();
          } else {
            System.err.println(
                "Treehash ("
                    + layer
                    + ","
                    + i
                    + ") not finished when needed in AuthPathComputation");
          }
        }

        // 2nd: copy precomputed values from Retain
        if (i < H - 1 && i >= H - K) {
          if (currentRetain[layer][i - (H - K)].size() > 0) {
            // pop element from retain
            System.arraycopy(
                currentRetain[layer][i - (H - K)].lastElement(),
                0,
                currentAuthPaths[layer][i],
                0,
                mdLength);
            currentRetain[layer][i - (H - K)].removeElementAt(
                currentRetain[layer][i - (H - K)].size() - 1);
          }
        }

        // STEP 4c of Algorithm
        // initialize new stack at heights 0..Tau-1
        if (i < H - K) {
          // create stacks anew
          int startPoint = Phi + 3 * (1 << i);
          if (startPoint < numLeafs[layer]) {
            // if (layer < 2) {
            // System.out.println("initialized TH " + i + " on layer
            // " + layer);
            // }
            currentTreehash[layer][i].initialize();
          }
        }
      }
    }

    // now keep space is free to use
    if (Tau < H - 1 && L == 0) {
      System.arraycopy(tempKeep, 0, keep[layer][(int) Math.floor(Tau / 2)], 0, mdLength);
    }

    // only update empty stack at height h if all other stacks have
    // tailnodes with height >h
    // finds active stack with lowest node height, choses lower index in
    // case of tie

    // on the lowest layer leafs must be computed at once, no precomputation
    // is possible. So all treehash updates are done at once here
    if (layer == numLayer - 1) {
      for (int tmp = 1; tmp <= (H - K) / 2; tmp++) {
        // index of the treehash instance that receives the next update
        int minTreehash = getMinTreehashIndex(layer);

        // if active treehash is found update with a leaf
        if (minTreehash >= 0) {
          try {
            byte[] seed = new byte[mdLength];
            System.arraycopy(
                this.currentTreehash[layer][minTreehash].getSeedActive(), 0, seed, 0, mdLength);
            byte[] seed2 = gmssRandom.nextSeed(seed);
            WinternitzOTSignature ots =
                new WinternitzOTSignature(seed2, this.digestProvider.get(), this.otsIndex[layer]);
            byte[] leaf = ots.getPublicKey();
            currentTreehash[layer][minTreehash].update(this.gmssRandom, leaf);
          } catch (Exception e) {
            System.out.println(e);
          }
        }
      }
    } else { // on higher layers the updates are done later
      this.minTreehash[layer] = getMinTreehashIndex(layer);
    }
  }
예제 #17
0
  /** return true if the signature represents a ISO9796-2 signature for the passed in message. */
  public boolean verifySignature(byte[] signature) {
    byte[] block = null;
    boolean updateWithRecoveredCalled;

    if (preSig == null) {
      updateWithRecoveredCalled = false;
      try {
        block = cipher.processBlock(signature, 0, signature.length);
      } catch (Exception e) {
        return false;
      }
    } else {
      if (!Arrays.areEqual(preSig, signature)) {
        throw new IllegalStateException("updateWithRecoveredMessage called on different signature");
      }

      updateWithRecoveredCalled = true;
      block = preBlock;

      preSig = null;
      preBlock = null;
    }

    if (((block[0] & 0xC0) ^ 0x40) != 0) {
      return returnFalse(block);
    }

    if (((block[block.length - 1] & 0xF) ^ 0xC) != 0) {
      return returnFalse(block);
    }

    int delta = 0;

    if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0) {
      delta = 1;
    } else {
      int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
      Integer trailerObj = (Integer) trailerMap.get(digest.getAlgorithmName());

      if (trailerObj != null) {
        if (sigTrail != trailerObj.intValue()) {
          throw new IllegalStateException(
              "signer initialised with wrong digest for trailer " + sigTrail);
        }
      } else {
        throw new IllegalArgumentException("unrecognised hash in signature");
      }

      delta = 2;
    }

    //
    // find out how much padding we've got
    //
    int mStart = 0;

    for (mStart = 0; mStart != block.length; mStart++) {
      if (((block[mStart] & 0x0f) ^ 0x0a) == 0) {
        break;
      }
    }

    mStart++;

    //
    // check the hashes
    //
    byte[] hash = new byte[digest.getDigestSize()];

    int off = block.length - delta - hash.length;

    //
    // there must be at least one byte of message string
    //
    if ((off - mStart) <= 0) {
      return returnFalse(block);
    }

    //
    // if we contain the whole message as well, check the hash of that.
    //
    if ((block[0] & 0x20) == 0) {
      fullMessage = true;

      // check right number of bytes passed in.
      if (messageLength > off - mStart) {
        return returnFalse(block);
      }

      digest.reset();
      digest.update(block, mStart, off - mStart);
      digest.doFinal(hash, 0);

      boolean isOkay = true;

      for (int i = 0; i != hash.length; i++) {
        block[off + i] ^= hash[i];
        if (block[off + i] != 0) {
          isOkay = false;
        }
      }

      if (!isOkay) {
        return returnFalse(block);
      }

      recoveredMessage = new byte[off - mStart];
      System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
    } else {
      fullMessage = false;

      digest.doFinal(hash, 0);

      boolean isOkay = true;

      for (int i = 0; i != hash.length; i++) {
        block[off + i] ^= hash[i];
        if (block[off + i] != 0) {
          isOkay = false;
        }
      }

      if (!isOkay) {
        return returnFalse(block);
      }

      recoveredMessage = new byte[off - mStart];
      System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
    }

    //
    // if they've input a message check what we've recovered against
    // what was input.
    //
    if (messageLength != 0 && !updateWithRecoveredCalled) {
      if (!isSameAs(mBuf, recoveredMessage)) {
        return returnFalse(block);
      }
    }

    clearBlock(mBuf);
    clearBlock(block);

    return true;
  }
예제 #18
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;
  }
예제 #19
0
 private void doHash(byte[] input, byte[] output) {
   _digest.update(input, 0, input.length);
   _digest.doFinal(output, 0);
 }
예제 #20
0
 private static void hash(Digest d, byte[] input, byte[] output) {
   d.update(input, 0, input.length);
   d.doFinal(output, 0);
 }