private BigInteger Sqrt(BigInteger x, AnyRng rng) { if (!IsQuadraticResidue(x)) { throw new InvalidOperationException(); } BigInteger z; do { z = rng.NextBigInt(BigInteger.One, P); } while (IsQuadraticResidue(z)); var q = _eulerPower; ulong s = 1; while (q.IsEven) { s++; q /= 2; } var m = s; var c = BigInteger.ModPow(z, q, P); var t = BigInteger.ModPow(x, q, P); var r = BigInteger.ModPow(x, q / 2 + 1, P); while (true) { if (t.IsZero) { return(BigInteger.Zero); } if (t.IsOne) { return(r); } ulong i = 1; while (i < m) { if (BigInteger.ModPow(t, BigInteger.ModPow(2, i, P), P).IsOne) { break; } i++; } if (i == m) { throw new InvalidOperationException(); } var b = BigInteger.ModPow(c, BigInteger.ModPow(2, m - i - 1, P), P); m = i; c = b * b % P; t = t * b * b % P; r = r * b % P; } }
public JacobianEcPoint Multiply(BigInteger k, JacobianEcPoint p, AnyRng rng) { if (k.Sign < 0) { k = -k; p = Negate(p); } if (k.IsZero) { return(JacobianEcPoint.Infinity); } if (k.IsOne) { return(p); } var ks = rng.NextBigInt(BigInteger.One, k); // return MultiplyAndAdd(ks, p, k - ks, p, rng); var(k1, k2) = ToNafBytes(k - ks, ks); var i = 0; while (i < k1.Length - 1) { var c = k1[i].NafValue() + k2[i].NafValue(); if (c != 0) { i++; continue; } if (k2[i + 1].NafValue() > 0) { k2[i + 1] = (byte)((k2[i + 1].H() << 4) | ((k2[i + 1].L() - 1) & 0xF)); k2[i] = (byte)(((k2[i].H() + 2) << 4) | (k2[i].L() & 0xF)); } else { k2[i + 1] = (byte)((k2[i + 1].H() << 4) | ((k2[i + 1].L() + 1) & 0xF)); k2[i] = (byte)(((k2[i].H() - 2) << 4) | (k2[i].L() & 0xF)); } } var lut = new [] { JacobianEcPoint.Infinity, p, Double(p), Add(Double(p), p), Double(Double(p)) }; var r = lut[k1.Back().NafValue() + k2.Back().NafValue()]; for (i = k1.Length - 2; i >= 0; i--) { var c = k1[i].NafValue() + k2[i].NafValue(); r = Add(Double(Double(r)), c < 0 ? Negate(lut[-c]) : lut[c]); } return(r); }