/**
   * return true if the value r and s represent a DSA signature for the passed in message for
   * standard DSA the message should be a SHA-1 hash of the real message to be verified.
   */
  public boolean verifySignature(byte[] message, BigInteger r, BigInteger s) {
    BigInteger m = new BigInteger(1, message);
    DSAParameters params = key.getParameters();
    BigInteger zero = BigInteger.valueOf(0);

    if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0) {
      return false;
    }

    if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0) {
      return false;
    }

    BigInteger w = s.modInverse(params.getQ());

    BigInteger u1 = m.multiply(w).mod(params.getQ());
    BigInteger u2 = r.multiply(w).mod(params.getQ());

    u1 = params.getG().modPow(u1, params.getP());
    u2 = ((DSAPublicKeyParameters) key).getY().modPow(u2, params.getP());

    BigInteger v = u1.multiply(u2).mod(params.getP()).mod(params.getQ());

    return v.equals(r);
  }
  public boolean equals(Object obj) {
    if (!(obj instanceof DSAParameters)) {
      return false;
    }

    DSAParameters pm = (DSAParameters) obj;

    return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getG().equals(g));
  }
  /**
   * generate a signature for the given message using the key we were initialised with. For
   * conventional DSA the message should be a SHA-1 hash of the message of interest.
   *
   * @param message the message that will be verified later.
   */
  public BigInteger[] generateSignature(byte[] message) {
    BigInteger m = new BigInteger(1, message);
    DSAParameters params = key.getParameters();
    BigInteger k;

    do {
      k = new BigInteger(params.getQ().bitLength(), random);
    } while (k.compareTo(params.getQ()) >= 0);

    BigInteger r = params.getG().modPow(k, params.getP()).mod(params.getQ());

    k =
        k.modInverse(params.getQ())
            .multiply(m.add(((DSAPrivateKeyParameters) key).getX().multiply(r)));

    BigInteger s = k.mod(params.getQ());

    BigInteger[] res = new BigInteger[2];

    res[0] = r;
    res[1] = s;

    return res;
  }