code: async function millerRabin(n, k, rand) {
    const len = n.bitLength();
    const red = BN.mont(n);
    const rone = new BN(1).toRed(red);
  
    if (!k) {
      k = Math.max(1, (len / 48) | 0);
    }
  
    const n1 = n.subn(1);
    const rn1 = n1.toRed(red);
  
    // Find d and s, (n - 1) = (2 ^ s) * d;
    let s = 0;
    while (!n1.testn(s)) { s++; }
    const d = n.shrn(s);
  
    for (; k > 0; k--) {
      const a = rand ? rand() : await random.getRandomBN(new BN(2), n1);
  
      let x = a.toRed(red).redPow(d);
      if (x.eq(rone) || x.eq(rn1)) {
        continue;
      }
  
      let i;
      for (i = 1; i < s; i++) {
        x = x.redSqr();
  
        if (x.eq(rone)) {
          return false;
        }
        if (x.eq(rn1)) {
          break;
        }
      }
  
      if (i === s) {
        return false;
      }
    }
  
    return true;
  }
docs: Sample syntax for Fixed-Base Miller-Rabin: millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) 
  Tests whether n is probably prime or not using the Miller-Rabin test.
  See HAC Remark 4.28.
  @param {BN}       n    Number to test
  @param {Integer}  k    Optional number of iterations of Miller-Rabin test
  @param {Function} rand Optional function to generate potential witnesses
  @returns {boolean}
  @async