public void VerifyCert(StringBuilder sb, BackgroundWorker bw, Certificate cert)
        {
            BigInteger[]  args  = null;
            ECPoint       point = ECPoint.POINT_INFINITY;
            ECPoint       P     = ECPoint.POINT_INFINITY;
            EllipticCurve curve = null;

            while ((args = cert.Read()) != null)
            {
                if (bw.CancellationPending)
                {
                    return;
                }
                curve = new EllipticCurve(args[0], args[1], args[2], args[3]);
                sb.AppendFormat("N = {0}\n", args[2].ToString());
                sb.AppendFormat("a = {0}", args[0].ToString());
                sb.AppendLine();
                sb.AppendFormat("b = {0}", args[1].ToString());
                sb.AppendLine();
                sb.AppendFormat("m = {0}", args[3].ToString());
                sb.AppendLine();
                sb.AppendFormat("q = {0}", args[4].ToString());
                sb.AppendLine();
                point = new ECPoint(args[5], args[6]);
                sb.AppendFormat("P = ({0}, {1})", point.GetAffineX().ToString(), point.GetAffineY().ToString());
                sb.AppendLine();
                P = ECMath.Multiply(curve, args[3] / args[4], point);
                sb.AppendFormat("Q = ({0}, {1})", P.GetAffineX().ToString(), P.GetAffineY().ToString());
                sb.AppendLine();
                P = ECMath.Multiply(curve, args[4], P);
                sb.Append("R = (0, 1)\n");
                sb.AppendLine();
            }
        }
        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);
        }