예제 #1
0
  protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
    CipherParameters param;

    if (publicKey instanceof ECPublicKey) {
      param = ECUtil.generatePublicKeyParameter(publicKey);
    } else if (publicKey instanceof GOST3410Key) {
      param = GOST3410Util.generatePublicKeyParameter(publicKey);
    } else {
      try {
        byte[] bytes = publicKey.getEncoded();

        publicKey = BouncyCastleProvider.getPublicKey(SubjectPublicKeyInfo.getInstance(bytes));

        if (publicKey instanceof ECPublicKey) {
          param = ECUtil.generatePublicKeyParameter(publicKey);
        } else {
          throw new InvalidKeyException("can't recognise key type in DSA based signer");
        }
      } catch (Exception e) {
        throw new InvalidKeyException("can't recognise key type in DSA based signer");
      }
    }

    digest.reset();
    signer.init(false, param);
  }
예제 #2
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();
  }
예제 #3
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();
  }
  /**
   * 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;
  }
예제 #5
0
  /** reset the internal state */
  public void reset() {
    digest.reset();
    messageLength = 0;
    clearBlock(mBuf);

    if (recoveredMessage != null) {
      clearBlock(recoveredMessage);
    }

    recoveredMessage = null;
    fullMessage = false;
  }
예제 #6
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;
  }
예제 #7
0
  protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
    CipherParameters param;

    if (privateKey instanceof ECKey) {
      param = ECUtil.generatePrivateKeyParameter(privateKey);
    } else {
      param = GOST3410Util.generatePrivateKeyParameter(privateKey);
    }

    digest.reset();

    if (random != null) {
      signer.init(true, new ParametersWithRandom(param, random));
    } else {
      signer.init(true, param);
    }
  }
예제 #8
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);
  }
예제 #9
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;
  }
예제 #10
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;
  }