code: function verify(params, yKey, sign, message, generateHash) {
      // Reject the signature if 0<r<q or 0<s<q is not satisfied.
      // Calculate w = s ^ (-1) mod q
      // Calculate u_1 = H(m) * w mod q
      // Calculate u_2 = r * w mod q
      // Calculate v = ( (g^u_1 * y^u_2) mod p) mod q
      // The signature is valid if and only if v = r
      const hash = generateHash(message);
      if (sign.length !== hash.length) return false;
  
      return sign.every(({r, s}, i) => {
          if (!(0 < r && r < params.q && 0 < s && s < params.q)) return false;
  
          let w = myNumbers.mInverse(s, params.q);
          let u2 = r * w % params.q;
          let keyU2Mod = myNumbers.modPow(yKey, u2, params.p);
  
          let h = hash[i];
          if (h === null) return false;
  
          let u1 = (h + 1) * w % params.q;
          let v = ((myNumbers.modPow(params.g, u1, params.p) * keyU2Mod) % params.p) % params.q;
  
          return v === r;
      });
  
  }
docs: verifies digital signature for data and hash function using public key and shared DSA params
  @param {{q: number, p: number, g: number}} params shared DSA params
  @param {{number}} yKey - public key
  @param {[{r: number, s: number}]} sign - digital signature
  @param {string} message - data to sign
  @param {function} generateHash - hash function (should accept {string} and return [number])
  @returns {boolean}