Exemple #1
0
        /// <summary>
        /// Verifies a signature of <paramref name="Data"/> made by the EdDSA algorithm.
        /// </summary>
        /// <param name="Data">Payload to sign.</param>
        /// <param name="PublicKey">Public Key of the entity that generated the signature.</param>
        /// <param name="HashFunction">Hash function to use.</param>
        /// <param name="Curve">Elliptic curve</param>
        /// <param name="Signature">Signature</param>
        /// <returns>If the signature is valid.</returns>
        public static bool Verify(byte[] Data, byte[] PublicKey, HashFunctionArray HashFunction,
                                  EdwardsCurveBase Curve, byte[] Signature)
        {
            try
            {
                int ScalarBytes = Signature.Length;
                if ((ScalarBytes & 1) != 0)
                {
                    return(false);
                }

                ScalarBytes >>= 1;

                byte[] R = new byte[ScalarBytes];
                Array.Copy(Signature, 0, R, 0, ScalarBytes);
                PointOnCurve r = Decode(R, Curve);
                byte[]       S = new byte[ScalarBytes];
                Array.Copy(Signature, ScalarBytes, S, 0, ScalarBytes);
                BigInteger s = EllipticCurve.ToInt(S);

                if (s >= Curve.Order)
                {
                    return(false);
                }

                int    c   = Data.Length;
                byte[] Bin = new byte[(ScalarBytes << 1) + c];              // dom2(F, C) = blank string
                Array.Copy(R, 0, Bin, 0, ScalarBytes);
                Array.Copy(PublicKey, 0, Bin, ScalarBytes, ScalarBytes);
                Array.Copy(Data, 0, Bin, ScalarBytes << 1, c);              // PH(M)=M

                byte[] h = HashFunction(Bin);

                BigInteger   k  = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
                PointOnCurve P1 = Curve.ScalarMultiplication(s, Curve.BasePoint, false);
                PointOnCurve P2 = Curve.ScalarMultiplication(k, Curve.Decode(PublicKey), false);
                Curve.AddTo(ref P2, r);

                P1.Normalize(Curve);
                P2.Normalize(Curve);

                return(P1.Equals(P2));
            }
            catch (ArgumentException)
            {
                return(false);
            }
        }
Exemple #2
0
        /// <summary>
        /// Converts a pair of (X,Y) coordinates for the birational Edwards curve
        /// to a pair of (U,V) coordinates.
        /// </summary>
        /// <param name="XY">(X,Y) coordinates.</param>
        /// <returns>(U,V) coordinates.</returns>
        public override PointOnCurve ToUV(PointOnCurve XY)
        {
            BigInteger U = this.modP.Divide(XY.Y + BigInteger.One, BigInteger.One - XY.Y);
            BigInteger V = this.modP.Multiply(SqrtMinus486664, this.modP.Divide(U, XY.X));

            if (U.Sign < 0)
            {
                U += this.p;
            }

            if (V.Sign < 0)
            {
                V += this.p;
            }

            return(new PointOnCurve(U, V));
        }
Exemple #3
0
        /// <summary>
        /// Converts a pair of (U,V) coordinates to a pair of (X,Y) coordinates
        /// in the birational Edwards curve.
        /// </summary>
        /// <param name="UV">(U,V) coordinates.</param>
        /// <returns>(X,Y) coordinates.</returns>
        public override PointOnCurve ToXY(PointOnCurve UV)
        {
            BigInteger X = this.modP.Multiply(SqrtMinus486664, this.modP.Divide(UV.X, UV.Y));
            BigInteger Y = this.modP.Divide(UV.X - BigInteger.One, UV.X + BigInteger.One);

            if (X.Sign < 0)
            {
                X += this.p;
            }

            if (Y.Sign < 0)
            {
                Y += this.p;
            }

            return(new PointOnCurve(X, Y));
        }
Exemple #4
0
        /// <summary>
        /// Gets a shared key using the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
        /// </summary>
        /// <param name="LocalPrivateKey">Local private key.</param>
        /// <param name="RemotePublicKey">Public key of the remote party.</param>
        /// <param name="HashFunction">A Hash function is applied to the derived key to generate the shared secret.
        /// The derived key, as a byte array of equal size as the order of the prime field, ordered by most significant byte first,
        /// is passed on to the hash function before being returned as the shared key.</param>
        /// <param name="Curve">Elliptic curve used.</param>
        /// <returns>Shared secret.</returns>
        public static byte[] GetSharedKey(byte[] LocalPrivateKey, byte[] RemotePublicKey,
                                          HashFunctionArray HashFunction, EllipticCurve Curve)
        {
            PointOnCurve PublicKey = Curve.Decode(RemotePublicKey);
            PointOnCurve P         = Curve.ScalarMultiplication(LocalPrivateKey, PublicKey, true);

            byte[] B = P.X.ToByteArray();

            if (B.Length != Curve.OrderBytes)
            {
                Array.Resize <byte>(ref B, Curve.OrderBytes);
            }

            Array.Reverse(B);   // Most significant byte first.

            return(HashFunction(B));
        }
Exemple #5
0
        /// <summary>
        /// Doubles a point on the curve.
        /// </summary>
        /// <param name="P">Point</param>
        public override void Double(ref PointOnCurve P)
        {
            if (!P.IsHomogeneous)
            {
                P.Z = BigInteger.One;
            }

            BigInteger A = this.modP.Add(P.X, P.Y);
            BigInteger B = this.modP.Multiply(A, A);
            BigInteger C = this.modP.Multiply(P.X, P.X);
            BigInteger D = this.modP.Multiply(P.Y, P.Y);
            BigInteger E = this.modP.Add(C, D);
            BigInteger H = this.modP.Multiply(P.Z, P.Z);
            BigInteger J = this.modP.Subtract(E, H << 1);

            P.X = this.modP.Multiply(B - E, J);
            P.Y = this.modP.Multiply(E, C - D);
            P.Z = this.modP.Multiply(E, J);
        }
Exemple #6
0
        /// <summary>
        /// Creates the Edwards Curve pair.
        /// </summary>
        /// <returns>Edwards curve.</returns>
        public override EdwardsCurveBase CreatePair()
        {
            PointOnCurve PublicKeyUV = this.PublicKeyPoint;
            PointOnCurve PublicKeyXY = this.ToXY(PublicKeyUV);

            Edwards448   Candidate    = new Edwards448(this.PrivateKey, false);
            PointOnCurve PublicKeyXY2 = Candidate.PublicKeyPoint;

            PublicKeyXY2 = Candidate.ScalarMultiplication(4, PublicKeyXY2, true);

            if (PublicKeyXY.Y.Equals(PublicKeyXY2.Y))
            {
                return(Candidate);
            }
            else
            {
                throw new InvalidOperationException("Unable to create pair curve.");
            }
        }
Exemple #7
0
        /// <summary>
        /// Converts a pair of (X,Y) coordinates for the birational Edwards curve
        /// to a pair of (U,V) coordinates.
        /// </summary>
        /// <param name="XY">(X,Y) coordinates.</param>
        /// <returns>(U,V) coordinates.</returns>
        public override PointOnCurve ToUV(PointOnCurve XY)
        {
            BigInteger X2 = this.modP.Multiply(XY.X, XY.X);
            BigInteger Y2 = this.modP.Multiply(XY.Y, XY.Y);
            BigInteger U  = this.modP.Divide(Y2, X2);
            BigInteger X3 = this.modP.Multiply(XY.X, X2);
            BigInteger V  = this.modP.Divide(this.modP.Multiply(Two - X2 - Y2, XY.Y), X3);

            if (U.Sign < 0)
            {
                U += this.p;
            }

            if (V.Sign < 0)
            {
                V += this.p;
            }

            return(new PointOnCurve(U, V));
        }
Exemple #8
0
        /// <summary>
        /// Performs the scalar multiplication of <paramref name="N"/>*<paramref name="P"/>.
        /// </summary>
        /// <param name="N">Scalar</param>
        /// <param name="P">Point</param>
        /// <returns><paramref name="N"/>*<paramref name="P"/></returns>
        public PointOnCurve ScalarMultiplication(BigInteger N, PointOnCurve P)
        {
            PointOnCurve Result = PointOnCurve.Zero;

            byte[] Bin = N.ToByteArray();
            int    i;
            int    c = Math.Min(this.orderBits, Bin.Length << 3);

            for (i = 0; i < c; i++)
            {
                if ((Bin[i >> 3] & (1 << (i & 7))) != 0)
                {
                    this.AddTo(ref Result, P);
                }

                this.Double(ref P);
            }

            return(Result);
        }
Exemple #9
0
        /// <summary>
        /// Encodes a point on the curve.
        /// </summary>
        /// <param name="Point">Normalized point to encode.</param>
        /// <returns>Encoded point.</returns>
        public virtual byte[] Encode(PointOnCurve Point)
        {
            byte[] X = Point.X.ToByteArray();
            byte[] Y = Point.Y.ToByteArray();

            if (X.Length != this.orderBytes)
            {
                Array.Resize <byte>(ref X, this.orderBytes);
            }

            if (Y.Length != this.orderBytes)
            {
                Array.Resize <byte>(ref Y, this.orderBytes);
            }

            byte[] Result = new byte[this.orderBytes << 1];

            Array.Copy(X, 0, Result, 0, this.orderBytes);
            Array.Copy(Y, 0, Result, this.orderBytes, this.orderBytes);

            return(Result);
        }
        /// <summary>
        /// Base class of Elliptic curves over a prime field.
        /// </summary>
        /// <param name="Prime">Prime base of field.</param>
        /// <param name="BasePoint">Base-point.</param>
        /// <param name="A">a Coefficient in the definition of the curve E:	y^2=x^3+a*x+b</param>
        /// <param name="Order">Order of base-point.</param>
        /// <param name="OrderBits">Number of bits used to encode order.</param>
        /// <param name="D">Private key.</param>
        public CurvePrimeField(BigInteger Prime, PointOnCurve BasePoint, BigInteger A,
                               BigInteger Order, int OrderBits, BigInteger?D)
            : base(Prime)
        {
            if (Prime <= BigInteger.One)
            {
                throw new ArgumentException("Invalid prime base.", nameof(Prime));
            }

            this.g          = BasePoint;
            this.a          = A;
            this.n          = Order;
            this.orderBits  = OrderBits;
            this.orderBytes = (OrderBits + 7) >> 3;
            this.modN       = new ModulusP(Order);

            this.msbMask = 0xff;
            int MaskBits = (8 - OrderBits) & 7;

            if (MaskBits == 0)
            {
                this.orderBytes++;
                this.msbMask = 0;
            }
            else
            {
                this.msbMask >>= MaskBits;
            }

            if (D.HasValue)
            {
                this.publicKey = this.ScalarMultiplication(D.Value, this.g);
                this.d         = D.Value;
            }
            else
            {
                this.GenerateKeys();
            }
        }
Exemple #11
0
        /// <summary>
        /// Adds <paramref name="Q"/> to <paramref name="P"/>.
        /// </summary>
        /// <param name="P">Point 1.</param>
        /// <param name="Q">Point 2.</param>
        /// <returns>P+Q</returns>
        public void AddTo(ref PointOnCurve P, PointOnCurve Q)
        {
            if (P.IsZero)
            {
                P.X      = Q.X;
                P.Y      = Q.Y;
                P.IsZero = Q.IsZero;
            }
            else if (!Q.IsZero)
            {
                BigInteger sDividend = this.Subtract(P.Y, Q.Y);
                BigInteger sDivisor = this.Subtract(P.X, Q.X);
                BigInteger s, xR, yR;

                if (sDivisor.IsZero)
                {
                    if (sDividend.IsZero)                       // P=Q
                    {
                        this.Double(ref P);
                    }
                    else
                    {
                        P.X      = BigInteger.Zero;
                        P.Y      = BigInteger.Zero;
                        P.IsZero = true;
                    }
                }
                else
                {
                    s  = this.Divide(sDividend, sDivisor);
                    xR = this.Subtract(this.Multiply(s, s), this.Add(P.X, Q.X));
                    yR = this.Add(P.Y, this.Multiply(s, this.Subtract(xR, P.X)));

                    P.X = xR;
                    P.Y = this.p - yR;
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// Performs the scalar multiplication of <paramref name="N"/>*<paramref name="P"/>.
        /// </summary>
        /// <param name="N">Scalar, in binary, little-endian form.</param>
        /// <param name="P">Point</param>
        /// <param name="Normalize">If normalized output is expected.</param>
        /// <returns><paramref name="N"/>*<paramref name="P"/></returns>
        public virtual PointOnCurve ScalarMultiplication(byte[] N, PointOnCurve P, bool Normalize)
        {
            PointOnCurve Result = this.Zero;
            int          i, c = N.Length;
            byte         b, Bit;

            for (i = 0; i < c; i++)
            {
                b = N[i];

                for (Bit = 1; Bit != 0; Bit <<= 1)
                {
                    if ((b & Bit) != 0)
                    {
                        this.AddTo(ref Result, P);
                    }

                    this.Double(ref P);
                }
            }

            return(Result);
        }
        /// <summary>
        /// Adds <paramref name="Q"/> to <paramref name="P"/>.
        /// </summary>
        /// <param name="P">Point 1.</param>
        /// <param name="Q">Point 2.</param>
        /// <returns>P+Q</returns>
        public override void AddTo(ref PointOnCurve P, PointOnCurve Q)
        {
            if (P.NonZero)
            {
                if (Q.NonZero)
                {
                    BigInteger sDividend = this.modP.Subtract(P.Y, Q.Y);
                    BigInteger sDivisor = this.modP.Subtract(P.X, Q.X);
                    BigInteger s, xR, yR;

                    if (sDivisor.IsZero)
                    {
                        if (sDividend.IsZero)   // P=Q
                        {
                            this.Double(ref P);
                        }
                        else
                        {
                            P = this.Zero;
                        }
                    }
                    else
                    {
                        s  = this.modP.Divide(sDividend, sDivisor);
                        xR = this.modP.Subtract(this.modP.Multiply(s, s), this.modP.Add(P.X, Q.X));
                        yR = this.modP.Add(P.Y, this.modP.Multiply(s, this.modP.Subtract(xR, P.X)));

                        P.X = xR;
                        P.Y = this.p - yR;
                    }
                }
            }
            else
            {
                P.CopyFrom(Q);
            }
        }
Exemple #14
0
        /// <summary>
        /// Encodes a point on the curve in accordance with §5.1.2 of RFC 8032.
        /// </summary>
        /// <param name="P">Point</param>
        /// <param name="Curve">Edwards curve.</param>
        /// <returns>Encoding</returns>
        public static byte[] Encode(PointOnCurve P, EdwardsCurveBase Curve)
        {
            int ScalarBits  = Curve.CoordinateBits;
            int ScalarBytes = (ScalarBits + 9) >> 3;

            byte[] y = P.Y.ToByteArray();
            if (y.Length != ScalarBytes)
            {
                Array.Resize <byte>(ref y, ScalarBytes);
            }

            byte[] x   = P.X.ToByteArray();
            int    Msb = (ScalarBits + 1) & 7;

            byte Mask = (byte)(0xff >> (8 - Msb));

            y[ScalarBytes - 1] &= Mask;

            if ((x[0] & 1) != 0)
            {
                y[ScalarBytes - 1] |= 0x80;     // Always MSB
            }
            return(y);
        }
Exemple #15
0
 /// <summary>
 /// Base class of Edwards curves (x²+y²=1+dx²y²) over a prime field.
 /// </summary>
 /// <param name="Prime">Prime base of field.</param>
 /// <param name="BasePoint">Base-point in (X,Y) coordinates.</param>
 /// <param name="d">Coefficient in the curve equation (x²+y²=1+dx²y²)</param>
 /// <param name="Order">Order of base-point.</param>
 /// <param name="Cofactor">Cofactor of curve.</param>
 public EdwardsCurve(BigInteger Prime, PointOnCurve BasePoint, BigInteger d,
                     BigInteger Order, int Cofactor)
     : this(Prime, BasePoint, d, Order, Cofactor, null)
 {
 }
Exemple #16
0
 /// <summary>
 /// Negates a point on the curve.
 /// </summary>
 /// <param name="P">Point</param>
 public void Negate(ref PointOnCurve P)
 {
     P.Y = this.p - P.Y;
 }
 /// <summary>
 /// Base class of Elliptic curves over a prime field defined by NIST.
 /// </summary>
 /// <param name="Prime">Prime base of field.</param>
 /// <param name="BasePoint">Base-point.</param>
 /// <param name="Order">Order of base-point.</param>
 /// <param name="Secret">Secret.</param>
 public NistPrimeCurve(BigInteger Prime, PointOnCurve BasePoint, BigInteger Order,
                       byte[] Secret)
     : base(Prime, BasePoint, -3, Order, 1, Secret)
 {
 }
Exemple #18
0
 /// <summary>
 /// Doubles a point on the curve.
 /// </summary>
 /// <param name="P">Point</param>
 public override void Double(ref PointOnCurve P)
 {
     throw new NotSupportedException("Scalar  multiplication is performed using a Montgomery ladder.");
 }
Exemple #19
0
 /// <summary>
 /// Performs the scalar multiplication of <paramref name="N"/>*<paramref name="P"/>.
 /// </summary>
 /// <param name="N">Scalar</param>
 /// <param name="P">Point</param>
 /// <param name="Normalize">If normalized output is expected.</param>
 /// <returns><paramref name="N"/>*<paramref name="P"/></returns>
 public PointOnCurve ScalarMultiplication(BigInteger N, PointOnCurve P, bool Normalize)
 {
     return(this.ScalarMultiplication(N.ToByteArray(), P, Normalize));
 }
Exemple #20
0
 /// <summary>
 /// Converts a pair of (X,Y) coordinates for the birational Edwards curve
 /// to a pair of (U,V) coordinates.
 /// </summary>
 /// <param name="XY">(X,Y) coordinates.</param>
 /// <returns>(U,V) coordinates.</returns>
 public abstract PointOnCurve ToUV(PointOnCurve XY);
Exemple #21
0
 /// <summary>
 /// Adds <paramref name="Q"/> to <paramref name="P"/>.
 /// </summary>
 /// <param name="P">Point 1.</param>
 /// <param name="Q">Point 2.</param>
 /// <returns>P+Q</returns>
 public override void AddTo(ref PointOnCurve P, PointOnCurve Q)
 {
     this.Double(ref P);
 }
Exemple #22
0
 /// <summary>
 /// Base class of Montgomery curves, with biratinal Edwards equivalent
 /// over a prime field.
 /// </summary>
 /// <param name="Prime">Prime base of field.</param>
 /// <param name="BasePoint">Base-point in (U,V) coordinates.</param>
 /// <param name="Order">Order of base-point.</param>
 /// <param name="Cofactor">Cofactor of curve.</param>
 /// <param name="Secret">Secret.</param>
 public MontgomeryCurve(BigInteger Prime, PointOnCurve BasePoint, BigInteger Order,
                        int Cofactor, byte[] Secret)
     : base(Prime, BasePoint, Order, Cofactor, Secret)
 {
 }
Exemple #23
0
 /// <summary>
 /// Converts a pair of (U,V) coordinates to a pair of (X,Y) coordinates
 /// in the birational Edwards curve.
 /// </summary>
 /// <param name="UV">(U,V) coordinates.</param>
 /// <returns>(X,Y) coordinates.</returns>
 public abstract PointOnCurve ToXY(PointOnCurve UV);
Exemple #24
0
 /// <summary>
 /// Base class of Montgomery curves (y²=x³+Ax²+x), with biratinal Edwards equivalent
 /// over a prime field.
 /// </summary>
 /// <param name="Prime">Prime base of field.</param>
 /// <param name="BasePoint">Base-point in (U,V) coordinates.</param>
 /// <param name="Order">Order of base-point.</param>
 /// <param name="Cofactor">Cofactor of curve.</param>
 public MontgomeryCurve(BigInteger Prime, PointOnCurve BasePoint, BigInteger Order,
                        int Cofactor)
     : base(Prime, BasePoint, Order, Cofactor)
 {
 }
Exemple #25
0
 /// <summary>
 /// Performs the scalar multiplication of <paramref name="N"/>*<paramref name="P"/>.
 /// </summary>
 /// <param name="N">Scalar, in binary, little-endian form.</param>
 /// <param name="P">Point</param>
 /// <param name="Normalize">If normalized output is expected.</param>
 /// <returns><paramref name="N"/>*<paramref name="P"/></returns>
 public override PointOnCurve ScalarMultiplication(byte[] N, PointOnCurve P, bool Normalize)
 {
     return(new PointOnCurve(this.ScalarMultiplication(N, P.X), BigInteger.Zero));
 }
Exemple #26
0
 /// <summary>
 /// Adds <paramref name="Q"/> to <paramref name="P"/>.
 /// </summary>
 /// <param name="P">Point 1.</param>
 /// <param name="Q">Point 2.</param>
 /// <returns>P+Q</returns>
 public abstract void AddTo(ref PointOnCurve P, PointOnCurve Q);
Exemple #27
0
 /// <summary>
 /// Doubles a point on the curve.
 /// </summary>
 /// <param name="P">Point</param>
 public abstract void Double(ref PointOnCurve P);
Exemple #28
0
 /// <summary>
 /// Abstract base class for elliptic curves.
 /// </summary>
 /// <param name="BasePoint">Base-point.</param>
 /// <param name="Order">Order of base-point.</param>
 /// <param name="Cofactor">Cofactor of curve.</param>
 public EllipticCurve(PointOnCurve BasePoint, BigInteger Order, int Cofactor)
     : this(BasePoint, Order, Cofactor, null)
 {
 }
Exemple #29
0
        /// <summary>
        /// Signs data using the EdDSA algorithm.
        /// </summary>
        /// <param name="Data">Data to be signed.</param>
        /// <param name="PrivateKey">Private key.</param>
        /// <param name="Prefix">Prefix</param>
        /// <param name="HashFunction">Hash function to use</param>
        /// <param name="Curve">Elliptic curve</param>
        /// <returns>Signature</returns>
        public static byte[] Sign(Stream Data, byte[] PrivateKey, byte[] Prefix,
                                  HashFunctionStream HashFunction, EdwardsCurveBase Curve)
        {
            // 5.1.6 of RFC 8032

            int ScalarBytes = PrivateKey.Length;

            if (Prefix.Length != ScalarBytes)
            {
                throw new ArgumentException("Invalid prefix.", nameof(Prefix));
            }

            BigInteger   a = EllipticCurve.ToInt(PrivateKey);
            PointOnCurve P = Curve.ScalarMultiplication(PrivateKey, Curve.BasePoint, true);

            byte[] A = Encode(P, Curve);
            byte[] h;

            using (TemporaryStream TempFile = new TemporaryStream()) // dom2(F, C) = blank string
            {
                TempFile.Write(Prefix, 0, ScalarBytes);              // prefix

                Data.Position = 0;
                Data.CopyTo(TempFile);                              // PH(M)=M

                TempFile.Position = 0;
                h = HashFunction(TempFile);
            }

            BigInteger   r = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
            PointOnCurve R = Curve.ScalarMultiplication(r, Curve.BasePoint, true);

            byte[] Rs = Encode(R, Curve);

            using (TemporaryStream TempFile = new TemporaryStream())    // dom2(F, C) = blank string
            {
                TempFile.Write(Rs, 0, ScalarBytes);
                TempFile.Write(A, 0, ScalarBytes);

                Data.Position = 0;
                Data.CopyTo(TempFile);                              // PH(M)=M

                TempFile.Position = 0;
                h = HashFunction(TempFile);
            }

            BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
            BigInteger s = Curve.ModulusN.Add(r, Curve.ModulusN.Multiply(k, a));

            byte[] Bin = s.ToByteArray();
            if (Bin.Length != ScalarBytes)
            {
                Array.Resize <byte>(ref Bin, ScalarBytes);
            }

            byte[] Signature = new byte[ScalarBytes << 1];

            Array.Copy(Rs, 0, Signature, 0, ScalarBytes);
            Array.Copy(Bin, 0, Signature, ScalarBytes, ScalarBytes);

            return(Signature);
        }
Exemple #30
0
 /// <summary>
 /// Base class of Edwards curves (x²+y²=1+dx²y²) over a prime field.
 /// </summary>
 /// <param name="Prime">Prime base of field.</param>
 /// <param name="BasePoint">Base-point in (X,Y) coordinates.</param>
 /// <param name="d">Coefficient in the curve equation (x²+y²=1+dx²y²)</param>
 /// <param name="Order">Order of base-point.</param>
 /// <param name="Cofactor">Cofactor of curve.</param>
 /// <param name="Secret">Secret.</param>
 public EdwardsCurve(BigInteger Prime, PointOnCurve BasePoint, BigInteger d,
                     BigInteger Order, int Cofactor, byte[] Secret)
     : base(Prime, BasePoint, d, Order, Cofactor, Secret)
 {
     this.p34 = (this.p - 3) / 4;
 }