Exemple #1
0
        /// <summary>
        /// Point addition
        /// </summary>
        /// <param name="p1">point</param>
        /// <param name="p2">point</param>
        /// <returns>result</returns>
        private Ed25519Point PointAdd(Ed25519Point p1, Ed25519Point p2)
        {
            // based on draft-irtf-cfrg-eddsa-08 "Edwards-curve Digital Signature Algorithm (EdDSA)"
            var A  = (this._p + p1.Y - p1.X) * (this._p + p2.Y - p2.X) % this._p;
            var B  = (p1.Y + p1.X) * (p2.Y + p2.X) % this._p;
            var C  = (p1.T << 1) * p2.T * this._d % this._p;
            var D  = (p1.Z << 1) * p2.Z % this._p;
            var E  = this._p + B - A;
            var F  = this._p + D - C;
            var G  = D + C;
            var H  = B + A;
            var X3 = E * F % this._p;
            var Y3 = G * H % this._p;
            var Z3 = F * G % this._p;
            var T3 = E * H % this._p;

            return(new Ed25519Point(X3, Y3, Z3, T3));
        }
Exemple #2
0
        /// <summary>
        /// Encodes a point to the octet string.
        /// </summary>
        /// <param name="q">a point</param>
        /// <param name="data">octet string returned</param>
        /// <returns>true if encoding succeeded, otherwise false.</returns>
        private bool EncodePoint(Ed25519Point q, out byte[] data)
        {
            // based on draft-irtf-cfrg-eddsa-08 "Edwards-curve Digital Signature Algorithm (EdDSA)"

            const int DATALEN = 32;
            var       zinv    = q.Z.ModInverse(this._p);
            var       x       = q.X * zinv % this._p;
            var       y       = q.Y * zinv % this._p;

            byte[] yBytes = y.GetBytes();
            byte[] w      = new byte[DATALEN];
            Buffer.BlockCopy(yBytes, 0, w, w.Length - yBytes.Length, yBytes.Length);
            Array.Reverse(w);   // to little endian
            if (x % 2u != 0)
            {
                w[DATALEN - 1] |= 0x80;   // set MSB
            }
            data = w;
            return(true);
        }
Exemple #3
0
        /// <summary>
        /// Point multiplication
        /// </summary>
        /// <param name="k">scalar value</param>
        /// <param name="p">point</param>
        /// <returns>result</returns>
        private Ed25519Point PointMul(BigInteger k, Ed25519Point p)
        {
            Ed25519Point mp        = p;
            Ed25519Point q         = new Ed25519Point(0, 1, 1, 0); // Neutral element
            int          kBitCount = k.BitCount();

            byte[] kBytes  = k.GetBytes();
            int    kOffset = kBytes.Length - 1;

            for (int i = 0; i < kBitCount; ++i)
            {
                if (i > 0)
                {
                    mp = PointAdd(mp, mp);
                }
                if ((kBytes[kOffset - i / 8] & (byte)(1 << (i % 8))) != 0)
                {
                    q = PointAdd(q, mp);
                }
            }
            return(q);
        }
Exemple #4
0
 /// <summary>
 /// Point multiplication
 /// </summary>
 /// <param name="k">scalar value</param>
 /// <param name="p">point</param>
 /// <returns>result</returns>
 private Ed25519Point PointMul(BigInteger k, Ed25519Point p)
 {
     Ed25519Point mp = p;
     Ed25519Point q = new Ed25519Point(0, 1, 1, 0);  // Neutral element
     int kBitCount = k.BitCount();
     byte[] kBytes = k.GetBytes();
     int kOffset = kBytes.Length - 1;
     for (int i = 0; i < kBitCount; ++i) {
         if (i > 0) {
             mp = PointAdd(mp, mp);
         }
         if ((kBytes[kOffset - i / 8] & (byte)(1 << (i % 8))) != 0) {
             q = PointAdd(q, mp);
         }
     }
     return q;
 }
Exemple #5
0
 /// <summary>
 /// Point addition
 /// </summary>
 /// <param name="p1">point</param>
 /// <param name="p2">point</param>
 /// <returns>result</returns>
 private Ed25519Point PointAdd(Ed25519Point p1, Ed25519Point p2)
 {
     // based on draft-irtf-cfrg-eddsa-08 "Edwards-curve Digital Signature Algorithm (EdDSA)"
     var A = (this._p + p1.Y - p1.X) * (this._p + p2.Y - p2.X) % this._p;
     var B = (p1.Y + p1.X) * (p2.Y + p2.X) % this._p;
     var C = (p1.T << 1) * p2.T * this._d % this._p;
     var D = (p1.Z << 1) * p2.Z % this._p;
     var E = this._p + B - A;
     var F = this._p + D - C;
     var G = D + C;
     var H = B + A;
     var X3 = E * F % this._p;
     var Y3 = G * H % this._p;
     var Z3 = F * G % this._p;
     var T3 = E * H % this._p;
     return new Ed25519Point(X3, Y3, Z3, T3);
 }
Exemple #6
0
        /// <summary>
        /// Encodes a point to the octet string.
        /// </summary>
        /// <param name="q">a point</param>
        /// <param name="data">octet string returned</param>
        /// <returns>true if encoding succeeded, otherwise false.</returns>
        private bool EncodePoint(Ed25519Point q, out byte[] data)
        {
            // based on draft-irtf-cfrg-eddsa-08 "Edwards-curve Digital Signature Algorithm (EdDSA)"

            const int DATALEN = 32;
            var zinv = q.Z.ModInverse(this._p);
            var x = q.X * zinv % this._p;
            var y = q.Y * zinv % this._p;
            byte[] yBytes = y.GetBytes();
            byte[] w = new byte[DATALEN];
            Buffer.BlockCopy(yBytes, 0, w, w.Length - yBytes.Length, yBytes.Length);
            Array.Reverse(w);   // to little endian
            if (x % 2u != 0) {
                w[DATALEN - 1] |= 0x80;   // set MSB
            }
            data = w;
            return true;
        }
Exemple #7
0
        /// <summary>
        /// Decode the octet string to a point.
        /// </summary>
        /// <param name="data">point data</param>
        /// <param name="point"></param>
        /// <returns>true if decoding succeeded, otherwise false.</returns>
        private bool DecodePoint(byte[] data, out Ed25519Point point)
        {
            // based on draft-irtf-cfrg-eddsa-08 "Edwards-curve Digital Signature Algorithm (EdDSA)"

            const int DATALEN = 32;
            if (data.Length != DATALEN) {
                point = null;
                return false;
            }
            // note that the byte order of the data is little endian
            byte[] w = (byte[])data.Clone();
            int sign = w[DATALEN - 1] >> 7; // MSB represents the sign of x
            w[DATALEN - 1] &= 0x7f;
            Array.Reverse(w);   // to big endian
            var y = new BigInteger(w);
            if (y >= _p) {
                point = null;
                return false;
            }
            // recover x
            var y2 = y * y;
            var x2 = (((this._p + y2 - 1) % this._p) * (this._d * y2 + 1).ModInverse(this._p)) % this._p;
            BigInteger x;
            if (x2 == 0) {
                if (sign != 0) {
                    point = null;
                    return false;
                }
                else {
                    x = 0;
                }
            }
            else {
                x = x2.ModPow((this._p + 3) >> 3, this._p);
                if ((x * x) % this._p != x2) {
                    // square root of -1
                    x = x * (new BigInteger(2)).ModPow((this._p - 1) >> 2, this._p) % this._p;
                    if ((x * x) % this._p != x2) {
                        point = null;
                        return false;
                    }
                }
                if ((x % 2u) != (uint)sign) {
                   x = _p - x;
                }
            }

            point = new Ed25519Point(x, y, 1, (x * y) % this._p);
            return true;
        }
Exemple #8
0
        /// <summary>
        /// Decode the octet string to a point.
        /// </summary>
        /// <param name="data">point data</param>
        /// <param name="point"></param>
        /// <returns>true if decoding succeeded, otherwise false.</returns>
        private bool DecodePoint(byte[] data, out Ed25519Point point)
        {
            // based on draft-irtf-cfrg-eddsa-08 "Edwards-curve Digital Signature Algorithm (EdDSA)"

            const int DATALEN = 32;

            if (data.Length != DATALEN)
            {
                point = null;
                return(false);
            }
            // note that the byte order of the data is little endian
            byte[] w    = (byte[])data.Clone();
            int    sign = w[DATALEN - 1] >> 7; // MSB represents the sign of x

            w[DATALEN - 1] &= 0x7f;
            Array.Reverse(w);   // to big endian
            var y = new BigInteger(w);

            if (y >= _p)
            {
                point = null;
                return(false);
            }
            // recover x
            var        y2 = y * y;
            var        x2 = (((this._p + y2 - 1) % this._p) * (this._d * y2 + 1).ModInverse(this._p)) % this._p;
            BigInteger x;

            if (x2 == 0)
            {
                if (sign != 0)
                {
                    point = null;
                    return(false);
                }
                else
                {
                    x = 0;
                }
            }
            else
            {
                x = x2.ModPow((this._p + 3) >> 3, this._p);
                if ((x * x) % this._p != x2)
                {
                    // square root of -1
                    x = x * (new BigInteger(2)).ModPow((this._p - 1) >> 2, this._p) % this._p;
                    if ((x * x) % this._p != x2)
                    {
                        point = null;
                        return(false);
                    }
                }
                if ((x % 2u) != (uint)sign)
                {
                    x = _p - x;
                }
            }

            point = new Ed25519Point(x, y, 1, (x * y) % this._p);
            return(true);
        }