Пример #1
0
        /// <summary>
        /// Returns the final point via summation. This method is very slow. Do not use big value for Sk.
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="G"></param>
        /// <param name="Sk"></param>
        /// <returns></returns>
        public static EcModPoint EcSlowKeyPairGeneratorByClassicPointSum(BigInteger P, BigInteger A, BigInteger B, EcModPoint G, int Sk)
        {
            var delta = 4 * A * A * A + 27 * B * B;

            if (0 == delta)
            {
                throw new Exception("Delta cannot be zero.");
            }

            int        cnt  = 2;
            bool       inf  = false;
            EcModPoint qMod = null;

            while (cnt <= Sk && !inf)
            {
                qMod = computePointSum(A, G, qMod, P);
                inf  = G.x == qMod.x;
                if (inf)
                {
                    qMod.IsInf  = true;
                    qMod.OrderN = cnt;
                }
                ++cnt;
            }

            return(qMod);
        }
Пример #2
0
        private static EcModPoint pointAdd(EcModPoint pointP, EcModPoint pointQ, BigInteger p)
        {
            // compute m = (y1 - y0) / (x1 - x0) (mod p)
            var x0 = pointP.x;
            var y0 = pointP.y;

            var x1 = pointQ.x;
            var y1 = pointQ.y;

            // compute m mod p
            BigInteger dy = (y1 - y0) % p;
            BigInteger dx = (x1 - x0) % p;

            dy = (dy + p) % p;
            dx = (dx + p) % p;

            BigInteger inv_dx = dx.ModInv(p);
            BigInteger m      = BigInteger.Multiply(dy, inv_dx) % p;

            m = (m + p) % p;

            var x = (m * m - x0 - x1) % p;

            x = (x + p) % p;
            var y = (m * (x0 - x) - y0) % p;  //(-m * m * m + 3 * m * x0 - y0) % p;

            y = (y + p) % p;

            EcModPoint ret = new EcModPoint {
                x = x, y = y
            };

            return(ret);
        }
Пример #3
0
        /// <summary>
        /// Encrypt text on elliptic curve and return a list of points on the elliptic curve in Json format (string)
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="PubKey"></param>
        /// <returns></returns>
        public static string EcEncryptJson(string Text, EcModPoint PubKey, EllipticCurveType EcType)
        {
            var lstEncr = EcEncrypt(Text, PubKey, EcType);
            var json    = JsonConvert.SerializeObject(lstEncr);

            return(json);
        }
Пример #4
0
        /// <summary>
        /// Returns the list of points by addition (P + Q). This method is very slow. Do not use big value for Sk.
        /// </summary>
        /// <param name="P"></param>
        /// <param name="A"></param>
        /// <param name="B></param>
        /// <param name="G"></param>
        /// <param name="Sk"></param>
        /// <returns></returns>
        public static List <EcModPoint> EcSlowPointListByAddition(BigInteger P, BigInteger A, BigInteger B, EcModPoint G, int Sk)
        {
            var delta = 4 * A * A * A + 27 * B * B;

            if (0 == delta)
            {
                throw new Exception("Delta cannot be zero.");
            }

            var ret = new List <EcModPoint>();

            ret.Add(G);
            int        cnt  = 2;
            bool       inf  = false;
            EcModPoint qMod = null;

            while (cnt <= Sk && !inf)
            {
                qMod = computePointSum(A, G, qMod, P);
                inf  = G.x == qMod.x;
                if (inf)
                {
                    qMod.IsInf  = true;
                    qMod.OrderN = cnt;
                }
                ret.Add(qMod);
                ++cnt;
            }

            return(ret);
        }
Пример #5
0
        private static EcModPoint pointDouble(EcModPoint point, BigInteger a, BigInteger p)
        {
            // compute m = dy/dx = dy * dx^-1 (mod p)
            var x0 = point.x;
            var y0 = point.y;

            BigInteger dy = (3 * x0 * x0 + a) % p;
            BigInteger dx = (2 * y0) % p;

            dy = (dy + p) % p;
            dx = (dx + p) % p;

            // compute inverse of dx mod p
            BigInteger inv_dx = dx.ModInv(p);

            // compute m mod p
            BigInteger m = BigInteger.Multiply(dy, inv_dx) % p;

            m = (m + p) % p;

            var x = (m * m - 2 * x0) % p;

            x = (x + p) % p;
            var y = (m * (x0 - x) - y0) % p;  //(-m * m * m + 3 * m * x0 - y0) % p;

            y = (y + p) % p;

            EcModPoint ret = new EcModPoint {
                x = x, y = y
            };

            return(ret);
        }
Пример #6
0
        /// <summary>
        /// Returns the final point via summation. This method is very slow. Do not use big value for Sk.
        /// </summary>
        /// <param name="A"></param>
        /// <param name="G"></param>
        /// <param name="Sk"></param>
        /// <returns></returns>
        public static EcModPoint EcSlowKeyPairGeneratorByClassicPointSum(BigInteger P, BigInteger A, EcModPoint G, int Sk)
        {
            int        cnt  = 2;
            bool       inf  = false;
            EcModPoint qMod = null;

            while (cnt <= Sk && !inf)
            {
                qMod = computePointSum(A, G, qMod, P);
                inf  = G.x == qMod.x;
                ++cnt;
            }

            return(qMod);
        }
Пример #7
0
        private static EcModPoint computeECPointMultiply(BigInteger a, EcModPoint g, BigInteger p, BigInteger sk)
        {
            var        bitString = sk.ToBinaryString();
            EcModPoint q         = g;

            foreach (var bit in bitString)
            {
                q = pointDouble(q, a, p);
                if (bit == '1')
                {
                    q = pointAdd(q, g, p);
                }
            }

            return(q);
        }
Пример #8
0
        private static EcModPoint computePointSum(BigInteger a, EcModPoint pointP, EcModPoint pointQ, BigInteger p)
        {
            BigInteger x2  = 0;
            BigInteger y2  = 0;
            BigInteger m   = 0;
            EcModPoint ret = null;

            if (null == pointQ) // P1 = P0, P2 = P0 + P1 = 2P0
            {
                ret = pointDouble(pointP, a, p);
            }
            else // P2 = P0 + P1
            {
                ret = pointAdd(pointP, pointQ, p);
            }

            return(ret);
        }
Пример #9
0
        /// <summary>
        /// Return point Q coords representing public key pair (see specs for secp256k1 parameters)
        /// </summary>
        /// <returns></returns>
        public static EcModPoint SecP256k1KeyPairGenerator(BigInteger Sk)
        {
            // Big prime
            var p = BigInteger.Parse("115792089237316195423570985008687907853269984665640564039457584007908834671663");
            // Elliptic curve equation: y^2 = x^3 + a*x + b => y^2 = x^3 + 7
            var a = 0;
            var b = 7;
            // Generator coordinates
            EcModPoint G = new EcModPoint
            {
                x = BigInteger.Parse("55066263022277343669578718895168534326250603453777594175500187360389116729240"),
                y = BigInteger.Parse("32670510020758816978083085130507043184471273380659243275938904335757337482424")
            };
            // Order of G
            var ordG = BigInteger.Parse("115792089237316195423570985008687907852837564279074904382605163141518161494337");

            return(ECKeyPairGenerator(p, a, b, G, ordG, Sk));
        }
Пример #10
0
        /// <summary>
        /// Returns the list of points by addition (P + Q). This method is very slow. Do not use big value for Sk.
        /// </summary>
        /// <param name="P"></param>
        /// <param name="A"></param>
        /// <param name="G"></param>
        /// <param name="Sk"></param>
        /// <returns></returns>
        public static List <EcModPoint> EcSlowPointListByAddition(BigInteger P, BigInteger A, EcModPoint G, int Sk)
        {
            var ret = new List <EcModPoint>();

            ret.Add(G);
            int        cnt  = 2;
            bool       inf  = false;
            EcModPoint qMod = null;

            while (cnt <= Sk && !inf)
            {
                qMod = computePointSum(A, G, qMod, P);
                inf  = G.x == qMod.x;
                ret.Add(qMod);
                ++cnt;
            }

            return(ret);
        }
Пример #11
0
        /// <summary>
        /// Dencrypt text on elliptic curve and return the message
        /// </summary>
        /// <param name="LstEncr"></param>
        /// <param name="SecretKey"></param>
        /// <returns></returns>
        public static string EcDecrypt(List <EcModPoint> LstEncr, BigInteger SecretKey, EllipticCurveType EcType)
        {
            BigInteger p;
            BigInteger n;
            BigInteger a;
            BigInteger b;

            // Set params
            switch (EcType)
            {
            case EllipticCurveType.SEC256K1:
                p = SEC256K1_P;
                n = SEC256K1_N;
                a = SEC256K1_A;
                b = SEC256K1_B;
                break;

            case EllipticCurveType.M383:
                p = M383_P;
                n = M383_N;
                a = M383_A;
                b = M383_B;
                break;

            case EllipticCurveType.E521:
                p = E521_P;
                n = E521_N;
                a = E521_A;
                b = E521_B;
                break;

            default:
                break;
            }

            // 1) get kG
            var kG = LstEncr.First();
            // 2) compute kPb = k(SkG) = Sk(kG)
            var kPb = ECKeyPairGenerator(p, a, b, kG, n, SecretKey);
            // set -kPb
            var negkPb = new EcModPoint {
                x = kPb.x, y = -kPb.y
            };

            // remove kG from the list
            LstEncr.RemoveAt(0);

            // 3) decrypt - compute Pc - kPb = Pm (plain message)
            var strMsg = string.Empty;

            foreach (var pnt in LstEncr)
            {
                var decPnt = pointAdd(pnt, negkPb, p);
                // data from x coord
                var arrUShort = Base65536Helper.ToArray(decPnt.x);
                var bytes     = arrUShort.ToByteArray();
                var str       = Encoding.Unicode.GetString(bytes);
                strMsg = string.Concat(strMsg, str);
                // data from y coord
                arrUShort = Base65536Helper.ToArray(decPnt.y);
                bytes     = arrUShort.ToByteArray();
                str       = Encoding.Unicode.GetString(bytes);
                strMsg    = string.Concat(strMsg, str);
            }

            return(strMsg);
        }
Пример #12
0
        /// <summary>
        /// Encrypt text on elliptic curve and return a list of points on the elliptic curve
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="PubKey"></param>
        /// <returns></returns>
        public static List <EcModPoint> EcEncrypt(string Text, EcModPoint PubKey, EllipticCurveType EcType)
        {
            BigInteger p;
            BigInteger n;
            BigInteger a;
            BigInteger b;

            // Set params
            switch (EcType)
            {
            case EllipticCurveType.SEC256K1:
                p = SEC256K1_P;
                n = SEC256K1_N;
                a = SEC256K1_A;
                b = SEC256K1_B;
                break;

            case EllipticCurveType.M383:
                p = M383_P;
                n = M383_N;
                a = M383_A;
                b = M383_B;
                break;

            case EllipticCurveType.E521:
                p = E521_P;
                n = E521_N;
                a = E521_A;
                b = E521_B;
                break;

            default:
                break;
            }

            // return the digits of P base 65536
            ushort[] digits       = Base65536Helper.ToArray(p);
            var      partitionLen = digits.Length - 1;

            // return a string array with string spit in groups of digits
            var partitionStrings = Text.SplitInGroup(partitionLen);

            // 1) create a list of big integers out of partitioned message
            List <BigInteger> lstBiMsg = new List <BigInteger>();

            foreach (var partitionStr in partitionStrings)
            {
                // encode the partioned str in Unicode
                var encUtf8 = Encoding.Unicode.GetBytes(partitionStr);
                // convert to ushort array
                var arrShort = encUtf8.ToUShortArray();
                // convert to Base 65536 big integer
                var bi65536 = Base65536Helper.FromArray(arrShort);
                // add to the list
                lstBiMsg.Add(bi65536);
            }

            // 2) pair with ascii 32 (space) if list count is odd
            var lstCnt = lstBiMsg.Count;

            if (0 != lstCnt % 2)
            {
                lstBiMsg.Add(32);
                lstCnt++;
            }
            // 3) build the pairs
            List <EcModPoint> lstPm = new List <EcModPoint>();

            for (int i = 0; i < lstCnt; i += 2)
            {
                var pnt = new EcModPoint {
                    x = lstBiMsg[i], y = lstBiMsg[i + 1]
                };
                lstPm.Add(pnt);
            }

            // get a random big integer k
            var k = BigIntegerExtensions.NextBigInteger(185, DateTime.Now.Millisecond);
            // 4) compute k*G for the chosen curve
            EcModPoint kG = null;

            switch (EcType)
            {
            case EllipticCurveType.SEC256K1:
                kG = SecP256k1KeyPairGenerator(k);
                break;

            case EllipticCurveType.M383:
                kG = M383KeyPairGenerator(k);
                break;

            case EllipticCurveType.E521:
                kG = E521KeyPairGenerator(k);
                break;

            default:
                break;
            }

            // 5) compute kPb = k(SkG)
            var kPb = ECKeyPairGenerator(p, a, b, PubKey, n, k);

            // 6) compute Pm + kPb = Pc (encrypted data)
            List <EcModPoint> lstEncr = new List <EcModPoint>();

            // first row is kG
            lstEncr.Add(kG);
            foreach (var pnt in lstPm)
            {
                var pntAdded = pointAdd(pnt, kPb, p);
                lstEncr.Add(pntAdded);
            }

            return(lstEncr);
        }
Пример #13
0
        /// <summary>
        /// Returns the key pair
        /// </summary>
        /// <param name="P"></param>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="G"></param>
        /// <param name="N"></param>
        /// <param name="SecretKey"></param>
        /// <returns></returns>
        public static EcModPoint ECKeyPairGenerator(BigInteger P, BigInteger A, BigInteger B, EcModPoint G, BigInteger N, BigInteger SecretKey)
        {
            // If private key Sk is not in the range 0 < Sk < N (order of G) then error
            if (SecretKey < 1 || SecretKey >= N)
            {
                throw new Exception("Private key is not in the range.");
            }

            // Check the discriminant for the eliptic curve y^2 = x^3 + a*x + b: -16(4a^3 + 27b^2) != 0
            var delta = 4 * A * A * A + 27 * B * B;

            if (0 == delta)
            {
                throw new Exception("Delta cannot be zero.");
            }

            return(computeECPointMultiply(A, G, P, SecretKey));
        }