public static BigInteger sqrtMod(BigInteger val, BigInteger modulus) {
    BigInteger b, x, y, exp, exp2;
    BigInteger[] lm;
    int i, n;
    int K[] = new int[300];

    val = val.mod(modulus);
    if (val.equals(ZERO))
      return ZERO;
    if (modulus.equals(TWO))
      return ONE;
    do {
      b = randomBetween(ONE, modulus);
      // Choose random number b with 1 <= b < p.
    } while ((b.modPow(modulus.subtract(ONE).shiftRight(1), modulus)).compareTo(ONE) == 0);
    /* Erfolg hat der Algorithmus bei Nichterfuellung der while-Bedingung */

    // Im Erfolgsfalle bestimme l, m aus N, m ungerade, mit "p-1 = (2^l)*m"
    lm = sucheLM(modulus);
    y = val;
    n = 1;
    // Suche das kleinste K[n] >= 0 mit y^((2^k[n])*m) mod modulus = 1
    K[n] = sucheKN(y, lm[1], modulus);
    while (K[n] != 0) {
      exp = ONE.shiftLeft((lm[0].subtract(BigInteger.valueOf(K[n]))).intValue());
      y = (y.multiply(b.modPow(exp, modulus))).mod(modulus);
      K[++n] = sucheKN(y, lm[1], modulus);
    }
    x = y.modPow(lm[1].add(ONE).shiftRight(1), modulus);
    for (i = n; i > 1; i--) {
      exp = ONE.shiftLeft((lm[0].subtract(BigInteger.valueOf(K[i - 1])).subtract(ONE)).intValue());
      exp2 = b.pow(exp.intValue());
      x = (x.multiply(exp2.modInverse(modulus))).mod(modulus);
    }

    return x;
  }