private BigInteger Sqrt(BigInteger val, BigInteger field) { if ((field & 3) == 3) { return(BigInteger.Pow(val, (field + 1) >> 2, field)); } BigInteger root = 0; BigInteger delta = ((field - 4) * (field - val)) % field; BigInteger temp = 1; BigInteger qnr = 0; BigInteger buf = 0; int ID = 1; switch (ID) { case 1: root = TonelliShanks(val, field); if (val == (root * root) % field) { return(root); } goto case 2; case 2: qnr = BigInteger.Next(rand, 2, field - 1); if (BigInteger.Jacobi(qnr, field) != -1) { goto case 2; } BigInteger square = (qnr * qnr) % field; delta = (delta * square) % field; temp = (temp * qnr) % field; buf = TonelliShanks(delta, field); if (delta != (buf * buf) % field) { goto case 2; } goto case 3; case 3: BigInteger vtemp = (2 * temp) % field; BigInteger inv = vtemp.Inverse(field); root = (buf * inv) % field; break; } return(root); }
private BigInteger TonelliShanks(BigInteger val, BigInteger field) { long e = 0, r, s; BigInteger b = 0, bp = 0, q = field - 1, m = 0, n = 0; BigInteger p1 = field - 1, t = 0, x = 0, y = 0, z = 0; while ((q & 1) == 0) { q >>= 1; e++; } int JSymbol = 0; do { n = BigInteger.Next(rand, 1, field - 1); JSymbol = BigInteger.Jacobi(n, field); } while (JSymbol == -1); z = BigInteger.Pow(n, q, field); y = z; r = e; x = BigInteger.Pow(val, (q - 1) >> 1, field); b = (((val * x) % field) * x) % field; x = (val * x) % field; while (true) { if (b == 1 || b == p1) { return(x); } s = 1; do { bp = BigInteger.Pow(b, (long)Math.Pow(2, s), field); s++; } while (bp != 1 && bp != p1 && s < r); if (s == r) { return(0); } t = BigInteger.Pow(y, (long)Math.Pow(2, r - s - 1), field); y = (t * t) % field; x = (x * t) % field; b = (b * y) % field; r = s; } }
private bool ModifiedCornacchia(BigInteger field, ref BigInteger u, ref BigInteger v, long D) { BigInteger root = 0; if (BigInteger.Jacobi(field + D, field) == 1) { root = Sqrt(field + D, field); if ((root & 1) != (D & 1)) { root = field - root; } } else { return(false); } BigInteger a = field << 1; BigInteger b = root; BigInteger t = 0; BigInteger c = field.Sqrt(); c <<= 1; while (b > c) { t = a % b; a = b; b = t; } a = b * b; c = field << 2; t = c - a; a = Math.Abs(D); c = t / a; a = t % a; root = c.Sqrt(); if (a == 0 && (root * root) == c) { u = b; v = c; return(true); } return(false); }
public SchnorrSignature Sign(uint256 m, BigInteger secret) { var k = new BigInteger(1, Hashes.SHA256(Utils.BigIntegerToBytes(secret, 32).Concat(m.ToBytes()))); var R = Secp256k1.G.Multiply(k).Normalize(); var Xr = R.XCoord.ToBigInteger(); var Yr = R.YCoord.ToBigInteger(); if (BigInteger.Jacobi(Yr, PP) != 1) { k = Secp256k1.N.Subtract(k); } var P = Secp256k1.G.Multiply(secret); var keyPrefixedM = Utils.BigIntegerToBytes(Xr, 32).Concat(P.GetEncoded(true), m.ToBytes()); var e = new BigInteger(1, Hashes.SHA256(keyPrefixedM)); var s = k.Add(e.Multiply(secret)).Mod(Secp256k1.N); return(new SchnorrSignature(Xr, s)); }
public void TestJacobi() { // Value generated from http://math.fau.edu/richman/jacobi.htm int[,] jcbTbl = { { 1236, 20003, 1 }, { 4513022, 3436547, -1 }, { 9325399, 4679869, -1 }, { 30, 5, 0 } }; BigInteger a, b; for (int i = 0; i < jcbTbl.Length / 3; i++) { a = new BigInteger(jcbTbl[i, 0]); b = new BigInteger(jcbTbl[i, 1]); Assert.AreEqual(jcbTbl[i, 2], BigInteger.Jacobi(a, b)); } }
public bool Verify(uint256 m, PubKey pubkey, SchnorrSignature sig) { if (sig.R.CompareTo(PP) >= 0 || sig.S.CompareTo(Secp256k1.N) >= 0) { return(false); } var e = new BigInteger(1, Hashes.SHA256(Utils.BigIntegerToBytes(sig.R, 32).Concat(pubkey.ToBytes(), m.ToBytes()))).Mod(Secp256k1.N); var q = pubkey.ECKey.GetPublicKeyParameters().Q.Normalize(); var P = Secp256k1.Curve.CreatePoint(q.XCoord.ToBigInteger(), q.YCoord.ToBigInteger()); var R = Secp256k1.G.Multiply(sig.S).Add(P.Multiply(Secp256k1.N.Subtract(e))).Normalize(); if (R.IsInfinity || R.XCoord.ToBigInteger().CompareTo(sig.R) != 0 || BigInteger.Jacobi(R.YCoord.ToBigInteger(), PP) != 1) { return(false); } return(true); }
public int Start(BigInteger field, StringBuilder sb, BackgroundWorker bw, Certificate cert) { long D = 0; int ID = 1; int k = 0; Random rng = new Random(Environment.TickCount); BigInteger val = field; ECPoint point = null; EllipticCurve curve = null; ECPoint P = null, Q = null; Hilbert hp = new Hilbert(); BigInteger u = 0, v = 0; BigInteger order = 0; BigInteger factor = 0; BigInteger a = 0, b = 0; Hilbert.SetModulus(val); BigInteger g = 1; switch (ID) { case 1: if (bw.CancellationPending) { return(-1); } D = hp.NextDiscriminant(); if (D == -1) { return(-2); } if (BigInteger.Jacobi(D, val) == -1) { goto case 1; } if (!ModifiedCornacchia(val, ref u, ref v, D)) { goto case 1; } goto case 2; case 2: if (bw.CancellationPending) { return(-1); } if (D == -3) { order = val + 1 + (u + 3 * v); factor = FindFactor(order); if (factor != -1) { goto case 3; } order = val + 1 - (u + 3 * v); factor = FindFactor(order); if (factor != -1) { goto case 3; } order = val + 1 + (u - 3 * v); factor = FindFactor(order); if (factor != -1) { goto case 3; } order = val + 1 - (u - 3 * v); factor = FindFactor(order); if (factor != -1) { goto case 3; } } else if (D == -4) { order = val + 1 + 2 * v; factor = FindFactor(order); if (factor != -1) { goto case 3; } order = val + 1 - 2 * v; factor = FindFactor(order); if (factor != -1) { goto case 3; } } else { order = val + 1 + u; factor = FindFactor(order); if (factor != -1) { goto case 3; } order = val + 1 - u; factor = FindFactor(order); if (factor != -1) { goto case 3; } } goto case 1; case 3: if (bw.CancellationPending) { return(-1); } if (D == -3) { a = 0; b = val - 1; } else if (D == -4) { a = val - 1; b = 0; } else { Polynomial poly = hp.GetHilbertPolynomial(D); List <BigInteger> roots = new List <BigInteger>(); if (poly.Degree > 1) { poly.FindRoots(ref roots); } else { roots.Add(val - poly.coeffs[0]); } BigInteger J = roots[rng.Next(roots.Count)]; a = J - 1728; BigInteger inv = a.Inverse(val); BigInteger c = (J * inv) % val; if (c == 0) { goto case 1; } a = (-3 * c) % val; if (a < 0) { a += val; } b = (2 * c) % val; } goto case 4; case 4: if (bw.CancellationPending) { return(-1); } g = BigInteger.Next(rand, 1, val - 1); if (D == -3) { if (BigInteger.Pow(g, (val - 1) / 3, val) == 1) { goto case 4; } } else { if (BigInteger.Jacobi(g, val) != -1) { goto case 4; } } k = 0; goto case 5; case 5: if (bw.CancellationPending) { return(-1); } curve = new EllipticCurve(a, b, val, order); point = curve.BasePoint; goto case 6; case 6: P = ECMath.Multiply(curve, order / factor, point); Q = ECMath.Multiply(curve, factor, P); if (Q == ECPoint.POINT_INFINITY) { goto case 9; } goto case 7; case 7: if (bw.CancellationPending) { return(-1); } k++; if (k >= w(D)) { goto case 9; } if (D == -3) { b = (b * g) % val; } else if (D == -4) { a = (a * g) % val; } else { BigInteger g2 = (g * g) % val; a = (a * g2) % val; g2 = (g2 * g) % val; b = (b * g2) % val; } goto case 5; case 8: if (bw.CancellationPending) { return(-1); } point = curve.BasePoint; P = ECMath.Multiply(curve, order / factor, point); if (P == ECPoint.POINT_INFINITY) { goto case 8; } Q = ECMath.Multiply(curve, factor, P); if (Q != ECPoint.POINT_INFINITY) { goto case 7; } goto case 9; case 9: if (bw.CancellationPending) { return(-1); } if (P == ECPoint.POINT_INFINITY) { goto case 8; } sb.AppendFormat("N = {0}", val.ToString()); sb.AppendLine(); sb.AppendFormat("a = {0}", a.ToString()); sb.AppendLine(); sb.AppendFormat("b = {0}", b.ToString()); sb.AppendLine(); sb.AppendFormat("m = {0}", order.ToString()); sb.AppendLine(); sb.AppendFormat("q = {0}", factor.ToString()); sb.AppendLine(); sb.AppendFormat("P = ({0}, {1})", point.GetAffineX().ToString(), point.GetAffineY().ToString()); sb.AppendLine(); sb.AppendFormat("Q = ({0}, {1})", P.GetAffineX().ToString(), P.GetAffineY().ToString()); sb.AppendLine(); sb.Append("R = (0, 1)\n"); sb.AppendLine(); cert.Write(a, b, val, order, factor, point.GetAffineX(), point.GetAffineY()); goto case 10; case 10: if (bw.CancellationPending) { return(-1); } val = factor; Hilbert.SetModulus(val); hp.Reset(); if (val.GetBits() <= 64) { return(1); } goto case 1; } return(0); }