Ejemplo n.º 1
0
        public override ECPoint TwicePlus(ECPoint b)
        {
            if (this.IsInfinity)
            {
                return(b);
            }
            if (b.IsInfinity)
            {
                return(Twice());
            }

            ECCurve curve = this.Curve;

            ECFieldElement X1 = this.RawXCoord;

            if (X1.IsZero)
            {
                // A point with X == 0 is it's own Additive inverse
                return(b);
            }

            // NOTE: TwicePlus() only optimized for lambda-affine argument
            ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];

            if (X2.IsZero || !Z2.IsOne)
            {
                return(Twice().Add(b));
            }

            ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
            ECFieldElement L2 = b.RawYCoord;

            ECFieldElement X1Sq = X1.Square();
            ECFieldElement L1Sq = L1.Square();
            ECFieldElement Z1Sq = Z1.Square();
            ECFieldElement L1Z1 = L1.Multiply(Z1);

            ECFieldElement T       = L1Sq.Add(L1Z1);
            ECFieldElement L2plus1 = L2.AddOne();
            ECFieldElement A       = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
            ECFieldElement X2Z1Sq  = X2.Multiply(Z1Sq);
            ECFieldElement B       = X2Z1Sq.Add(T).Square();

            if (B.IsZero)
            {
                if (A.IsZero)
                {
                    return(b.Twice());
                }

                return(curve.Infinity);
            }

            if (A.IsZero)
            {
                return(new SecT409K1Point(curve, A, curve.B, IsCompressed));
            }

            ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
            ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
            ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);

            return(new SecT409K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed));
        }
Ejemplo n.º 2
0
            public PreCompInfo Precompute(PreCompInfo existing)
            {
                WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo;

                int reqPreCompLen = 1 << System.Math.Max(0, m_width - 2);

                if (CheckExisting(existingWNaf, reqPreCompLen, m_includeNegated))
                {
                    return(existingWNaf);
                }

                ECCurve c = m_p.Curve;

                ECPoint[] preComp = null, preCompNeg = null;
                ECPoint   twiceP  = null;

                if (existingWNaf != null)
                {
                    preComp    = existingWNaf.PreComp;
                    preCompNeg = existingWNaf.PreCompNeg;
                    twiceP     = existingWNaf.Twice;
                }

                int iniPreCompLen = 0;

                if (preComp == null)
                {
                    preComp = EMPTY_POINTS;
                }
                else
                {
                    iniPreCompLen = preComp.Length;
                }

                if (iniPreCompLen < reqPreCompLen)
                {
                    preComp = WNafUtilities.ResizeTable(preComp, reqPreCompLen);

                    if (reqPreCompLen == 1)
                    {
                        preComp[0] = m_p.Normalize();
                    }
                    else
                    {
                        int curPreCompLen = iniPreCompLen;
                        if (curPreCompLen == 0)
                        {
                            preComp[0]    = m_p;
                            curPreCompLen = 1;
                        }

                        ECFieldElement iso = null;

                        if (reqPreCompLen == 2)
                        {
                            preComp[1] = m_p.ThreeTimes();
                        }
                        else
                        {
                            ECPoint isoTwiceP = twiceP, last = preComp[curPreCompLen - 1];
                            if (isoTwiceP == null)
                            {
                                isoTwiceP = preComp[0].Twice();
                                twiceP    = isoTwiceP;

                                /*
                                 * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism
                                 * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This
                                 * also requires scaling the initial point's X, Y coordinates, and reversing the
                                 * isomorphism as part of the subsequent normalization.
                                 *
                                 *  NOTE: The correctness of this optimization depends on:
                                 *      1) additions do not use the curve's A, B coefficients.
                                 *      2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
                                 */
                                if (!twiceP.IsInfinity && ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64)
                                {
                                    switch (c.CoordinateSystem)
                                    {
                                    case ECCurve.COORD_JACOBIAN:
                                    case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
                                    case ECCurve.COORD_JACOBIAN_MODIFIED:
                                    {
                                        iso       = twiceP.GetZCoord(0);
                                        isoTwiceP = c.CreatePoint(twiceP.XCoord.ToBigInteger(),
                                                                  twiceP.YCoord.ToBigInteger());

                                        ECFieldElement iso2 = iso.Square(), iso3 = iso2.Multiply(iso);
                                        last = last.ScaleX(iso2).ScaleY(iso3);

                                        if (iniPreCompLen == 0)
                                        {
                                            preComp[0] = last;
                                        }
                                        break;
                                    }
                                    }
                                }
                            }

                            while (curPreCompLen < reqPreCompLen)
                            {
                                /*
                                 * Compute the new ECPoints for the precomputation array. The values 1, 3,
                                 * 5, ..., 2^(width-1)-1 times p are computed
                                 */
                                preComp[curPreCompLen++] = last = last.Add(isoTwiceP);
                            }
                        }

                        /*
                         * Having oft-used operands in affine form makes operations faster.
                         */
                        c.NormalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso);
                    }
                }

                if (m_includeNegated)
                {
                    int pos;
                    if (preCompNeg == null)
                    {
                        pos        = 0;
                        preCompNeg = new ECPoint[reqPreCompLen];
                    }
                    else
                    {
                        pos = preCompNeg.Length;
                        if (pos < reqPreCompLen)
                        {
                            preCompNeg = WNafUtilities.ResizeTable(preCompNeg, reqPreCompLen);
                        }
                    }

                    while (pos < reqPreCompLen)
                    {
                        preCompNeg[pos] = preComp[pos].Negate();
                        ++pos;
                    }
                }

                WNafPreCompInfo result = new WNafPreCompInfo();

                result.PreComp    = preComp;
                result.PreCompNeg = preCompNeg;
                result.Twice      = twiceP;
                return(result);
            }
Ejemplo n.º 3
0
        public override ECPoint Add(ECPoint b)
        {
            if (this.IsInfinity)
            {
                return(b);
            }
            if (b.IsInfinity)
            {
                return(this);
            }

            ECCurve curve = this.Curve;

            ECFieldElement X1 = this.RawXCoord;
            ECFieldElement X2 = b.RawXCoord;

            if (X1.IsZero)
            {
                if (X2.IsZero)
                {
                    return(curve.Infinity);
                }

                return(b.Add(this));
            }

            ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
            ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];

            bool           Z1IsOne = Z1.IsOne;
            ECFieldElement U2 = X2, S2 = L2;

            if (!Z1IsOne)
            {
                U2 = U2.Multiply(Z1);
                S2 = S2.Multiply(Z1);
            }

            bool           Z2IsOne = Z2.IsOne;
            ECFieldElement U1 = X1, S1 = L1;

            if (!Z2IsOne)
            {
                U1 = U1.Multiply(Z2);
                S1 = S1.Multiply(Z2);
            }

            ECFieldElement A = S1.Add(S2);
            ECFieldElement B = U1.Add(U2);

            if (B.IsZero)
            {
                if (A.IsZero)
                {
                    return(Twice());
                }

                return(curve.Infinity);
            }

            ECFieldElement X3, L3, Z3;

            if (X2.IsZero)
            {
                // TODO This can probably be optimized quite a bit
                ECPoint p = this.Normalize();
                X1 = p.XCoord;
                ECFieldElement Y1 = p.YCoord;

                ECFieldElement Y2 = L2;
                ECFieldElement L  = Y1.Add(Y2).Divide(X1);

                //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
                X3 = L.Square().Add(L).Add(X1);
                if (X3.IsZero)
                {
                    //return new SecT283K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
                    return(new SecT283K1Point(curve, X3, curve.B, IsCompressed));
                }

                ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
                L3 = Y3.Divide(X3).Add(X3);
                Z3 = curve.FromBigInteger(BigInteger.One);
            }
            else
            {
                B = B.Square();

                ECFieldElement AU1 = A.Multiply(U1);
                ECFieldElement AU2 = A.Multiply(U2);

                X3 = AU1.Multiply(AU2);
                if (X3.IsZero)
                {
                    //return new SecT283K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
                    return(new SecT283K1Point(curve, X3, curve.B, IsCompressed));
                }

                ECFieldElement ABZ2 = A.Multiply(B);
                if (!Z2IsOne)
                {
                    ABZ2 = ABZ2.Multiply(Z2);
                }

                L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));

                Z3 = ABZ2;
                if (!Z1IsOne)
                {
                    Z3 = Z3.Multiply(Z1);
                }
            }

            return(new SecT283K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed));
        }
    public override ECPoint Add(ECPoint b)
    {
        if (base.IsInfinity)
        {
            return(b);
        }
        if (b.IsInfinity)
        {
            return(this);
        }
        ECCurve        curve      = Curve;
        ECFieldElement rawXCoord  = base.RawXCoord;
        ECFieldElement rawXCoord2 = b.RawXCoord;

        if (rawXCoord.IsZero)
        {
            if (rawXCoord2.IsZero)
            {
                return(curve.Infinity);
            }
            return(b.Add(this));
        }
        ECFieldElement rawYCoord       = base.RawYCoord;
        ECFieldElement eCFieldElement  = base.RawZCoords[0];
        ECFieldElement rawYCoord2      = b.RawYCoord;
        ECFieldElement eCFieldElement2 = b.RawZCoords[0];
        bool           isOne           = eCFieldElement.IsOne;
        ECFieldElement eCFieldElement3 = rawXCoord2;
        ECFieldElement eCFieldElement4 = rawYCoord2;

        if (!isOne)
        {
            eCFieldElement3 = eCFieldElement3.Multiply(eCFieldElement);
            eCFieldElement4 = eCFieldElement4.Multiply(eCFieldElement);
        }
        bool           isOne2          = eCFieldElement2.IsOne;
        ECFieldElement eCFieldElement5 = rawXCoord;
        ECFieldElement eCFieldElement6 = rawYCoord;

        if (!isOne2)
        {
            eCFieldElement5 = eCFieldElement5.Multiply(eCFieldElement2);
            eCFieldElement6 = eCFieldElement6.Multiply(eCFieldElement2);
        }
        ECFieldElement eCFieldElement7 = eCFieldElement6.Add(eCFieldElement4);
        ECFieldElement eCFieldElement8 = eCFieldElement5.Add(eCFieldElement3);

        if (eCFieldElement8.IsZero)
        {
            if (eCFieldElement7.IsZero)
            {
                return(Twice());
            }
            return(curve.Infinity);
        }
        ECFieldElement eCFieldElement10;
        ECFieldElement y;
        ECFieldElement eCFieldElement12;

        if (rawXCoord2.IsZero)
        {
            ECPoint eCPoint = Normalize();
            rawXCoord = eCPoint.XCoord;
            ECFieldElement yCoord          = eCPoint.YCoord;
            ECFieldElement b2              = rawYCoord2;
            ECFieldElement eCFieldElement9 = yCoord.Add(b2).Divide(rawXCoord);
            eCFieldElement10 = eCFieldElement9.Square().Add(eCFieldElement9).Add(rawXCoord)
                               .Add(curve.A);
            if (eCFieldElement10.IsZero)
            {
                return(new SecT163R1Point(curve, eCFieldElement10, curve.B.Sqrt(), base.IsCompressed));
            }
            ECFieldElement eCFieldElement11 = eCFieldElement9.Multiply(rawXCoord.Add(eCFieldElement10)).Add(eCFieldElement10).Add(yCoord);
            y = eCFieldElement11.Divide(eCFieldElement10).Add(eCFieldElement10);
            eCFieldElement12 = curve.FromBigInteger(BigInteger.One);
        }
        else
        {
            eCFieldElement8 = eCFieldElement8.Square();
            ECFieldElement eCFieldElement13 = eCFieldElement7.Multiply(eCFieldElement5);
            ECFieldElement eCFieldElement14 = eCFieldElement7.Multiply(eCFieldElement3);
            eCFieldElement10 = eCFieldElement13.Multiply(eCFieldElement14);
            if (eCFieldElement10.IsZero)
            {
                return(new SecT163R1Point(curve, eCFieldElement10, curve.B.Sqrt(), base.IsCompressed));
            }
            ECFieldElement eCFieldElement15 = eCFieldElement7.Multiply(eCFieldElement8);
            if (!isOne2)
            {
                eCFieldElement15 = eCFieldElement15.Multiply(eCFieldElement2);
            }
            y = eCFieldElement14.Add(eCFieldElement8).SquarePlusProduct(eCFieldElement15, rawYCoord.Add(eCFieldElement));
            eCFieldElement12 = eCFieldElement15;
            if (!isOne)
            {
                eCFieldElement12 = eCFieldElement12.Multiply(eCFieldElement);
            }
        }
        return(new SecT163R1Point(curve, eCFieldElement10, y, new ECFieldElement[1]
        {
            eCFieldElement12
        }, base.IsCompressed));
    }
Ejemplo n.º 5
0
        public override ECPoint Add(ECPoint b)
        {
            if (base.IsInfinity)
            {
                return(b);
            }
            if (b.IsInfinity)
            {
                return(this);
            }
            ECCurve        curve          = this.Curve;
            ECFieldElement eCFieldElement = base.RawXCoord;
            ECFieldElement rawXCoord      = b.RawXCoord;

            if (eCFieldElement.IsZero)
            {
                if (rawXCoord.IsZero)
                {
                    return(curve.Infinity);
                }
                return(b.Add(this));
            }
            else
            {
                ECFieldElement rawYCoord       = base.RawYCoord;
                ECFieldElement eCFieldElement2 = base.RawZCoords[0];
                ECFieldElement rawYCoord2      = b.RawYCoord;
                ECFieldElement eCFieldElement3 = b.RawZCoords[0];
                bool           isOne           = eCFieldElement2.IsOne;
                ECFieldElement eCFieldElement4 = rawXCoord;
                ECFieldElement eCFieldElement5 = rawYCoord2;
                if (!isOne)
                {
                    eCFieldElement4 = eCFieldElement4.Multiply(eCFieldElement2);
                    eCFieldElement5 = eCFieldElement5.Multiply(eCFieldElement2);
                }
                bool           isOne2          = eCFieldElement3.IsOne;
                ECFieldElement eCFieldElement6 = eCFieldElement;
                ECFieldElement eCFieldElement7 = rawYCoord;
                if (!isOne2)
                {
                    eCFieldElement6 = eCFieldElement6.Multiply(eCFieldElement3);
                    eCFieldElement7 = eCFieldElement7.Multiply(eCFieldElement3);
                }
                ECFieldElement eCFieldElement8 = eCFieldElement7.Add(eCFieldElement5);
                ECFieldElement eCFieldElement9 = eCFieldElement6.Add(eCFieldElement4);
                if (!eCFieldElement9.IsZero)
                {
                    ECFieldElement eCFieldElement11;
                    ECFieldElement y;
                    ECFieldElement eCFieldElement13;
                    if (rawXCoord.IsZero)
                    {
                        ECPoint eCPoint = this.Normalize();
                        eCFieldElement = eCPoint.XCoord;
                        ECFieldElement yCoord           = eCPoint.YCoord;
                        ECFieldElement b2               = rawYCoord2;
                        ECFieldElement eCFieldElement10 = yCoord.Add(b2).Divide(eCFieldElement);
                        eCFieldElement11 = eCFieldElement10.Square().Add(eCFieldElement10).Add(eCFieldElement).Add(curve.A);
                        if (eCFieldElement11.IsZero)
                        {
                            return(new SecT113R2Point(curve, eCFieldElement11, curve.B.Sqrt(), base.IsCompressed));
                        }
                        ECFieldElement eCFieldElement12 = eCFieldElement10.Multiply(eCFieldElement.Add(eCFieldElement11)).Add(eCFieldElement11).Add(yCoord);
                        y = eCFieldElement12.Divide(eCFieldElement11).Add(eCFieldElement11);
                        eCFieldElement13 = curve.FromBigInteger(BigInteger.One);
                    }
                    else
                    {
                        eCFieldElement9 = eCFieldElement9.Square();
                        ECFieldElement eCFieldElement14 = eCFieldElement8.Multiply(eCFieldElement6);
                        ECFieldElement eCFieldElement15 = eCFieldElement8.Multiply(eCFieldElement4);
                        eCFieldElement11 = eCFieldElement14.Multiply(eCFieldElement15);
                        if (eCFieldElement11.IsZero)
                        {
                            return(new SecT113R2Point(curve, eCFieldElement11, curve.B.Sqrt(), base.IsCompressed));
                        }
                        ECFieldElement eCFieldElement16 = eCFieldElement8.Multiply(eCFieldElement9);
                        if (!isOne2)
                        {
                            eCFieldElement16 = eCFieldElement16.Multiply(eCFieldElement3);
                        }
                        y = eCFieldElement15.Add(eCFieldElement9).SquarePlusProduct(eCFieldElement16, rawYCoord.Add(eCFieldElement2));
                        eCFieldElement13 = eCFieldElement16;
                        if (!isOne)
                        {
                            eCFieldElement13 = eCFieldElement13.Multiply(eCFieldElement2);
                        }
                    }
                    return(new SecT113R2Point(curve, eCFieldElement11, y, new ECFieldElement[]
                    {
                        eCFieldElement13
                    }, base.IsCompressed));
                }
                if (eCFieldElement8.IsZero)
                {
                    return(this.Twice());
                }
                return(curve.Infinity);
            }
        }
Ejemplo n.º 6
0
        public override ECPoint Add(ECPoint b)
        {
            ECFieldElement element13;
            ECFieldElement element14;
            ECFieldElement element15;

            if (base.IsInfinity)
            {
                return(b);
            }
            if (b.IsInfinity)
            {
                return(this);
            }
            ECCurve        curve     = this.Curve;
            ECFieldElement rawXCoord = base.RawXCoord;
            ECFieldElement element2  = b.RawXCoord;

            if (rawXCoord.IsZero)
            {
                if (element2.IsZero)
                {
                    return(curve.Infinity);
                }
                return(b.Add(this));
            }
            ECFieldElement rawYCoord = base.RawYCoord;
            ECFieldElement element4  = base.RawZCoords[0];
            ECFieldElement element5  = b.RawYCoord;
            ECFieldElement element6  = b.RawZCoords[0];
            bool           isOne     = element4.IsOne;
            ECFieldElement element7  = element2;
            ECFieldElement element8  = element5;

            if (!isOne)
            {
                element7 = element7.Multiply(element4);
                element8 = element8.Multiply(element4);
            }
            bool           flag2     = element6.IsOne;
            ECFieldElement element9  = rawXCoord;
            ECFieldElement element10 = rawYCoord;

            if (!flag2)
            {
                element9  = element9.Multiply(element6);
                element10 = element10.Multiply(element6);
            }
            ECFieldElement element11 = element10.Add(element8);
            ECFieldElement element12 = element9.Add(element7);

            if (element12.IsZero)
            {
                if (element11.IsZero)
                {
                    return(this.Twice());
                }
                return(curve.Infinity);
            }
            if (element2.IsZero)
            {
                ECPoint point = this.Normalize();
                rawXCoord = point.XCoord;
                ECFieldElement yCoord    = point.YCoord;
                ECFieldElement element17 = element5;
                ECFieldElement element18 = yCoord.Add(element17).Divide(rawXCoord);
                element13 = element18.Square().Add(element18).Add(rawXCoord).AddOne();
                if (element13.IsZero)
                {
                    return(new SecT283R1Point(curve, element13, curve.B.Sqrt(), base.IsCompressed));
                }
                element14 = element18.Multiply(rawXCoord.Add(element13)).Add(element13).Add(yCoord).Divide(element13).Add(element13);
                element15 = curve.FromBigInteger(BigInteger.One);
            }
            else
            {
                element12 = element12.Square();
                ECFieldElement element20 = element11.Multiply(element9);
                ECFieldElement element21 = element11.Multiply(element7);
                element13 = element20.Multiply(element21);
                if (element13.IsZero)
                {
                    return(new SecT283R1Point(curve, element13, curve.B.Sqrt(), base.IsCompressed));
                }
                ECFieldElement x = element11.Multiply(element12);
                if (!flag2)
                {
                    x = x.Multiply(element6);
                }
                element14 = element21.Add(element12).SquarePlusProduct(x, rawYCoord.Add(element4));
                element15 = x;
                if (!isOne)
                {
                    element15 = element15.Multiply(element4);
                }
            }
            return(new SecT283R1Point(curve, element13, element14, new ECFieldElement[] { element15 }, base.IsCompressed));
        }
    public override ECPoint Twice()
    {
        if (base.IsInfinity)
        {
            return(this);
        }
        ECCurve        curve     = Curve;
        ECFieldElement rawXCoord = base.RawXCoord;

        if (rawXCoord.IsZero)
        {
            return(curve.Infinity);
        }
        ECFieldElement rawYCoord       = base.RawYCoord;
        ECFieldElement eCFieldElement  = base.RawZCoords[0];
        bool           isOne           = eCFieldElement.IsOne;
        ECFieldElement eCFieldElement2 = isOne ? eCFieldElement : eCFieldElement.Square();
        ECFieldElement eCFieldElement3 = (!isOne) ? rawYCoord.Add(eCFieldElement).Multiply(rawYCoord) : rawYCoord.Square().Add(rawYCoord);

        if (eCFieldElement3.IsZero)
        {
            return(new SecT283K1Point(curve, eCFieldElement3, curve.B, base.IsCompressed));
        }
        ECFieldElement eCFieldElement4 = eCFieldElement3.Square();
        ECFieldElement eCFieldElement5 = isOne ? eCFieldElement3 : eCFieldElement3.Multiply(eCFieldElement2);
        ECFieldElement eCFieldElement6 = rawYCoord.Add(rawXCoord).Square();
        ECFieldElement b = isOne ? eCFieldElement : eCFieldElement2.Square();
        ECFieldElement y = eCFieldElement6.Add(eCFieldElement3).Add(eCFieldElement2).Multiply(eCFieldElement6)
                           .Add(b)
                           .Add(eCFieldElement4)
                           .Add(eCFieldElement5);

        return(new SecT283K1Point(curve, eCFieldElement4, y, new ECFieldElement[1]
        {
            eCFieldElement5
        }, base.IsCompressed));
    }
Ejemplo n.º 8
0
        public override ECPoint TwicePlus(ECPoint b)
        {
            if (this.IsInfinity)
            {
                return(b);
            }
            if (b.IsInfinity)
            {
                return(Twice());
            }

            ECCurve curve = this.Curve;

            ECFieldElement X1 = this.RawXCoord;

            if (X1.IsZero)
            {
                // A point with X == 0 is it's own Additive inverse
                return(b);
            }

            ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];

            if (X2.IsZero || !Z2.IsOne)
            {
                return(Twice().Add(b));
            }

            ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
            ECFieldElement L2 = b.RawYCoord;

            ECFieldElement X1Sq = X1.Square();
            ECFieldElement L1Sq = L1.Square();
            ECFieldElement Z1Sq = Z1.Square();
            ECFieldElement L1Z1 = L1.Multiply(Z1);

            //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
            ECFieldElement T       = Z1Sq.Add(L1Sq).Add(L1Z1);
            ECFieldElement L2plus1 = L2.AddOne();
            //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
            ECFieldElement A      = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
            ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
            ECFieldElement B      = X2Z1Sq.Add(T).Square();

            if (B.IsZero)
            {
                if (A.IsZero)
                {
                    return(b.Twice());
                }

                return(curve.Infinity);
            }

            if (A.IsZero)
            {
                //return new SecT571R1Point(curve, A, curve.B.sqrt(), withCompression);
                return(new SecT571R1Point(curve, A, SecT571R1Curve.SecT571R1_B_SQRT, IsCompressed));
            }

            ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
            ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
            ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);

            return(new SecT571R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed));
        }