예제 #1
0
파일: EdDSA.cs 프로젝트: iamr8/IoTGateway
        /// <summary>
        /// Decodes a point on the curve in accordance with §5.1.3 of RFC 8032.
        /// </summary>
        /// <param name="Encoded">Encoded point.</param>
        /// <param name="Curve">Elliptic curve</param>
        /// <returns>Point on curve.</returns>
        public static PointOnCurve Decode(byte[] Encoded, EdwardsCurveBase Curve)
        {
            int ScalarBits  = Curve.CoordinateBits;
            int ScalarBytes = (ScalarBits + 9) >> 3;

            if (Encoded.Length != ScalarBytes)
            {
                throw new ArgumentException("Not encoded properly.", nameof(Encoded));
            }

            bool x0 = (Encoded[ScalarBytes - 1] & 0x80) != 0;

            if (x0)
            {
                Encoded[ScalarBytes - 1] &= 0x7f;
            }

            BigInteger y = EllipticCurve.ToInt(Encoded);

            if (y >= Curve.Prime)
            {
                throw new ArgumentException("Not a valid point.", nameof(Encoded));
            }

            if (x0)
            {
                Encoded[ScalarBytes - 1] |= 0x80;
            }

            BigInteger x = Curve.GetX(y, x0);

            return(new PointOnCurve(x, y));
        }
예제 #2
0
파일: EdDSA.cs 프로젝트: iamr8/IoTGateway
        /// <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(Stream Data, byte[] PublicKey, HashFunctionStream 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);
                byte[]     h;

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

                using (TemporaryStream TempFile = new TemporaryStream())        // dom2(F, C) = blank string
                {
                    TempFile.Write(R, 0, ScalarBytes);
                    TempFile.Write(PublicKey, 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);
                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);
            }
        }
예제 #3
0
파일: EdDSA.cs 프로젝트: iamr8/IoTGateway
        /// <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(byte[] Data, byte[] PrivateKey, byte[] Prefix,
                                  HashFunctionArray 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);
            int    c = Data.Length;

            byte[] Bin = new byte[ScalarBytes + c];             // dom2(F, C) = blank string
            Array.Copy(Prefix, 0, Bin, 0, ScalarBytes);         // prefix
            Array.Copy(Data, 0, Bin, ScalarBytes, c);           // PH(M)=M

            byte[]       h = HashFunction(Bin);
            BigInteger   r = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
            PointOnCurve R = Curve.ScalarMultiplication(r, Curve.BasePoint, true);

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

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

            h = HashFunction(Bin);

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

            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);
        }
예제 #4
0
파일: EdDSA.cs 프로젝트: iamr8/IoTGateway
        /// <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);
            }
        }
예제 #5
0
파일: EdDSA.cs 프로젝트: iamr8/IoTGateway
        /// <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);
        }
예제 #6
0
파일: EdDSA.cs 프로젝트: iamr8/IoTGateway
        /// <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);
        }
예제 #7
0
 /// <summary>
 /// Sets the private key (and therefore also the public key) of the curve.
 /// </summary>
 /// <param name="Secret">Secret</param>
 public override void SetPrivateKey(byte[] Secret)
 {
     base.SetPrivateKey(Secret);
     this.pair = null;
 }