示例#1
0
 private void btnVerify_Click(object sender, EventArgs e)
 {
     BInteger p = new BInteger("6277101735386680763835789423207666416083908700390324961279", 10);
     BInteger a = new BInteger("-3", 10);
     BInteger b = new BInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16);
     byte[] xG = FromHexStringToByte("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012");
     BInteger n = new BInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16);
     DSGost DS = new DSGost(p, a, b, n, xG);
     GOST hash = new GOST(256);
     long start = DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
     byte[] H = hash.GetHash(System.Text.Encoding.Default.GetBytes(textBoxText.Text));
     bool result = DS.SingVer(H, textBox2Hash.Text, Q);
     long finish = DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
     long time = finish - start;
     if (result)
     {
         labelIsCorrect.ForeColor = Color.Green;
         labelIsCorrect.Text = "Correct";
     }
     else
     {
         labelIsCorrect.ForeColor = Color.Red;
         labelIsCorrect.Text = "Wrong";
     }
 }
示例#2
0
 private void btnSign_Click(object sender, EventArgs e)
 {
     BInteger p = new BInteger("6277101735386680763835789423207666416083908700390324961279", 10);
     BInteger a = new BInteger("-3", 10);
     BInteger b = new BInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16);
     byte[] xG = FromHexStringToByte("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012");
     BInteger n = new BInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16);
     DSGost DS = new DSGost(p, a, b, n, xG);
     d = DS.GenPrivateKey(192);
     Q = DS.GenPublicKey(d);
     GOST hash = new GOST(256);
     byte[] H = hash.GetHash(System.Text.Encoding.Default.GetBytes(textBoxText.Text));
     string sign = DS.SingGen(H, d);
     textBox2Hash.Text = sign;
     bool result = DS.SingVer(H, sign, Q);
 }
示例#3
0
 private void btnTest_Click(object sender, EventArgs e)
 {
     BInteger p = new BInteger("3623986102229003635907788753683874306021320925534678605086546150450856166624002482588482022271496854025090823603058735163734263822371964987228582907372403", 10);
     BInteger x = new BInteger("1928356944067022849399309401243137598997786635459507974357075491307766592685835441065557681003184874819658004903212332884252335830250729527632383493573274", 10);
     BInteger y = new BInteger("2288728693371972859970012155529478416353562327329506180314497425931102860301572814141997072271708807066593850650334152381857347798885864807605098724013854", 10);
     BInteger a = new BInteger(7);
     BInteger b = new BInteger("1518655069210828534508950034714043154928747527740206436194018823352809982443793732829756914785974674866041605397883677596626326413990136959047435811826396", 10);
     BInteger k = new BInteger("175516356025850499540628279921125280333451031747737791650208144243182057075034446102986750962508909227235866126872473516807810541747529710309879958632945", 10);
     ECPoint P1 = new ECPoint();
     P1.a = a;
     P1.b = b;
     P1.FieldChar = p;
     P1.x = x;
     P1.y = y;
     ECPoint P3 = ECPoint.multiply(k, P1);
     BInteger r = P3.x % p;
     /////// DS forming
     BInteger q = new BInteger("3623986102229003635907788753683874306021320925534678605086546150450856166623969164898305032863068499961404079437936585455865192212970734808812618120619743", 10);
     BInteger d = new BInteger("610081804136373098219538153239847583006845519069531562982388135354890606301782255383608393423372379057665527595116827307025046458837440766121180466875860", 10);
     BInteger E = new BInteger("2897963881682868575562827278553865049173745197871825199562947419041388950970536661109553499954248733088719748844538964641281654463513296973827706272045964", 10);
     BInteger s = ((r * d) + (k * E)) % q;
     //////// DS verification
     BInteger v = E.modInverse(q);
     BInteger z = (s * v) % q;
     BInteger z2 = q + ((-(r * v)) % q);
     BInteger x1 = new BInteger("909546853002536596556690768669830310006929272546556281596372965370312498563182320436892870052842808608262832456858223580713780290717986855863433431150561", 10);
     BInteger y1 = new BInteger(" 2921457203374425620632449734248415455640700823559488705164895837509539134297327397380287741428246088626609329139441895016863758984106326600572476822372076", 10);
     ECPoint Q = new ECPoint();
     Q.a = a;
     Q.b = b;
     Q.x = x1;
     Q.y = y1;
     Q.FieldChar = p;
     ECPoint A = ECPoint.multiply(z, P1);
     ECPoint B = ECPoint.multiply(z2, Q);
     ECPoint C = A + B;
 }
示例#4
0
        public BInteger(BInteger bi)
        {
            data = new uint[maxLength];

            dataLength = bi.dataLength;

            for (int i = 0; i < dataLength; i++)
                data[i] = bi.data[i];
        }
示例#5
0
        private static void multiByteDivide(BInteger bi1, BInteger bi2,
                                            BInteger outQuotient, BInteger outRemainder)
        {
            uint[] result = new uint[maxLength];

            int remainderLen = bi1.dataLength + 1;
            uint[] remainder = new uint[remainderLen];

            uint mask = 0x80000000;
            uint val = bi2.data[bi2.dataLength - 1];
            int shift = 0, resultPos = 0;

            while (mask != 0 && (val & mask) == 0)
            {
                shift++; mask >>= 1;
            }

            for (int i = 0; i < bi1.dataLength; i++)
                remainder[i] = bi1.data[i];
            shiftLeft(remainder, shift);
            bi2 = bi2 << shift;


            int j = remainderLen - bi2.dataLength;
            int pos = remainderLen - 1;

            ulong firstDivisorByte = bi2.data[bi2.dataLength - 1];
            ulong secondDivisorByte = bi2.data[bi2.dataLength - 2];

            int divisorLen = bi2.dataLength + 1;
            uint[] dividendPart = new uint[divisorLen];

            while (j > 0)
            {
                ulong dividend = ((ulong)remainder[pos] << 32) + remainder[pos - 1];
                //Console.WriteLine("dividend = {0}", dividend);

                ulong q_hat = dividend / firstDivisorByte;
                ulong r_hat = dividend % firstDivisorByte;

                //Console.WriteLine("q_hat = {0:X}, r_hat = {1:X}", q_hat, r_hat);

                bool done = false;
                while (!done)
                {
                    done = true;

                    if (q_hat == 0x100000000 ||
                       (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder[pos - 2]))
                    {
                        q_hat--;
                        r_hat += firstDivisorByte;

                        if (r_hat < 0x100000000)
                            done = false;
                    }
                }

                for (int h = 0; h < divisorLen; h++)
                    dividendPart[h] = remainder[pos - h];

                BInteger kk = new BInteger(dividendPart);
                BInteger ss = bi2 * (long)q_hat;

                //Console.WriteLine("ss before = " + ss);
                while (ss > kk)
                {
                    q_hat--;
                    ss -= bi2;
                    //Console.WriteLine(ss);
                }
                BInteger yy = kk - ss;

                for (int h = 0; h < divisorLen; h++)
                    remainder[pos - h] = yy.data[bi2.dataLength - h];

                result[resultPos++] = (uint)q_hat;

                pos--;
                j--;
            }

            outQuotient.dataLength = resultPos;
            int y = 0;
            for (int x = outQuotient.dataLength - 1; x >= 0; x--, y++)
                outQuotient.data[y] = result[x];
            for (; y < maxLength; y++)
                outQuotient.data[y] = 0;

            while (outQuotient.dataLength > 1 && outQuotient.data[outQuotient.dataLength - 1] == 0)
                outQuotient.dataLength--;

            if (outQuotient.dataLength == 0)
                outQuotient.dataLength = 1;

            outRemainder.dataLength = shiftRight(remainder, shift);

            for (y = 0; y < outRemainder.dataLength; y++)
                outRemainder.data[y] = remainder[y];
            for (; y < maxLength; y++)
                outRemainder.data[y] = 0;
        }
示例#6
0
        public static BInteger operator ~(BInteger bi1)
        {
            BInteger result = new BInteger(bi1);

            for (int i = 0; i < maxLength; i++)
                result.data[i] = ~(bi1.data[i]);

            result.dataLength = maxLength;

            while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
                result.dataLength--;

            return result;
        }
示例#7
0
        public static BInteger operator <<(BInteger bi1, int shiftVal)
        {
            BInteger result = new BInteger(bi1);
            result.dataLength = shiftLeft(result.data, shiftVal);

            return result;
        }
示例#8
0
        public static BInteger operator --(BInteger bi1)
        {
            BInteger result = new BInteger(bi1);

            long val;
            bool carryIn = true;
            int index = 0;

            while (carryIn && index < maxLength)
            {
                val = result.data[index];
                val--;

                result.data[index] = (uint)(val & 0xFFFFFFFF);

                if (val >= 0)
                    carryIn = false;

                index++;
            }

            if (index > result.dataLength)
                result.dataLength = index;

            while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
                result.dataLength--;

            int lastPos = maxLength - 1;


            if ((bi1.data[lastPos] & 0x80000000) != 0 &&
               (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))
            {
                throw (new ArithmeticException("Underflow in --."));
            }

            return result;
        }
示例#9
0
 //проверяем подпись 
 public bool SingVer(byte[] H, string sing, ECPoint Q)
 {
     string Rvector = sing.Substring(0, n.bitCount() / 4);
     string Svector = sing.Substring(n.bitCount() / 4, n.bitCount() / 4);
     BInteger r = new BInteger(Rvector, 16);
     BInteger s = new BInteger(Svector, 16);
     if ((r < 1) || (r > (n - 1)) || (s < 1) || (s > (n - 1)))
         return false;
     BInteger alpha = new BInteger(H);
     BInteger e = alpha % n;
     if (e == 0)
         e = 1;
     BInteger v = e.modInverse(n);
     BInteger z1 = (s * v) % n;
     BInteger z2 = n + ((-(r * v)) % n);
     this.G = GDecompression();
     ECPoint A = ECPoint.multiply(z1, G);
     ECPoint B = ECPoint.multiply(z2, Q);
     ECPoint C = A + B;
     BInteger R = C.x % n;
     if (R == r)
         return true;
     else
         return false;
 }
示例#10
0
        //умножение точки на число x, по сути своей представляет x сложений точки самой с собой
        public static ECPoint multiply(BInteger x, ECPoint p)
        {
            ECPoint temp = p;
            x = x - 1;
            while (x != 0)
            {

                if ((x % 2) != 0)
                {
                    if ((temp.x == p.x) || (temp.y == p.y))
                        temp = Double(temp);
                    else
                        temp = temp + p;
                    x = x - 1;
                }
                x = x / 2;
                p = Double(p);
            }
            return temp;
        }
示例#11
0
 public ECPoint()
 {
     x = new BInteger();
     y = new BInteger();
     a = new BInteger();
     b = new BInteger();
     FieldChar = new BInteger();
 }
示例#12
0
 public ECPoint(ECPoint p)
 {
     x = p.x;
     y = p.y;
     a = p.a;
     b = p.b;
     FieldChar = p.FieldChar;
 }
示例#13
0
        public static void SqrtTest(int rounds)
        {
            Random rand = new Random();
            for (int count = 0; count < rounds; count++)
            {
                // generate data of random length
                int t1 = 0;
                while (t1 == 0)
                    t1 = (int)(rand.NextDouble() * 1024);

                Console.Write("Round = " + count);

                BInteger a = new BInteger();
                a.genRandomBits(t1, rand);

                BInteger b = a.sqrt();
                BInteger c = (b + 1) * (b + 1);

                // check that b is the largest integer such that b*b <= a
                if (c <= a)
                {
                    Console.WriteLine("\nError at round " + count);
                    Console.WriteLine(a + "\n");
                    return;
                }
                Console.WriteLine(" <PASSED>.");
            }
        }
示例#14
0
        public static void RSATest2(int rounds)
        {
            Random rand = new Random();
            byte[] val = new byte[64];

            byte[] pseudoPrime1 = {
                        0x85, 0x84, 0x64, 0xFD, 0x70, 0x6A,
                        0x9F, 0xF0, 0x94, 0x0C, 0x3E, 0x2C,
                        0x74, 0x34, 0x05, 0xC9, 0x55, 0xB3,
                        0x85, 0x32, 0x98, 0x71, 0xF9, 0x41,
                        0x21, 0x5F, 0x02, 0x9E, 0xEA, 0x56,
                        0x8D, 0x8C, 0x44, 0xCC, 0xEE, 0xEE,
                        0x3D, 0x2C, 0x9D, 0x2C, 0x12, 0x41,
                        0x1E, 0xF1, 0xC5, 0x32, 0xC3, 0xAA,
                        0x31, 0x4A, 0x52, 0xD8, 0xE8, 0xAF,
                        0x42, 0xF4, 0x72, 0xA1, 0x2A, 0x0D,
                        0x97, 0xB1, 0x31, 0xB3,
                };

            byte[] pseudoPrime2 = {
                        0x99, 0x98, 0xCA, 0xB8, 0x5E, 0xD7,
                        0xE5, 0xDC, 0x28, 0x5C, 0x6F, 0x0E,
                        0x15, 0x09, 0x59, 0x6E, 0x84, 0xF3,
                        0x81, 0xCD, 0xDE, 0x42, 0xDC, 0x93,
                        0xC2, 0x7A, 0x62, 0xAC, 0x6C, 0xAF,
                        0xDE, 0x74, 0xE3, 0xCB, 0x60, 0x20,
                        0x38, 0x9C, 0x21, 0xC3, 0xDC, 0xC8,
                        0xA2, 0x4D, 0xC6, 0x2A, 0x35, 0x7F,
                        0xF3, 0xA9, 0xE8, 0x1D, 0x7B, 0x2C,
                        0x78, 0xFA, 0xB8, 0x02, 0x55, 0x80,
                        0x9B, 0xC2, 0xA5, 0xCB,
                };


            BInteger bi_p = new BInteger(pseudoPrime1);
            BInteger bi_q = new BInteger(pseudoPrime2);
            BInteger bi_pq = (bi_p - 1) * (bi_q - 1);
            BInteger bi_n = bi_p * bi_q;

            for (int count = 0; count < rounds; count++)
            {
                // generate private and public key
                BInteger bi_e = bi_pq.genCoPrime(512, rand);
                BInteger bi_d = bi_e.modInverse(bi_pq);

                Console.WriteLine("\ne =\n" + bi_e.ToString(10));
                Console.WriteLine("\nd =\n" + bi_d.ToString(10));
                Console.WriteLine("\nn =\n" + bi_n.ToString(10) + "\n");

                // generate data of random length
                int t1 = 0;
                while (t1 == 0)
                    t1 = (int)(rand.NextDouble() * 65);

                bool done = false;
                while (!done)
                {
                    for (int i = 0; i < 64; i++)
                    {
                        if (i < t1)
                            val[i] = (byte)(rand.NextDouble() * 256);
                        else
                            val[i] = 0;

                        if (val[i] != 0)
                            done = true;
                    }
                }

                while (val[0] == 0)
                    val[0] = (byte)(rand.NextDouble() * 256);

                Console.Write("Round = " + count);

                // encrypt and decrypt data
                BInteger bi_data = new BInteger(val, t1);
                BInteger bi_encrypted = bi_data.modPow(bi_e, bi_n);
                BInteger bi_decrypted = bi_encrypted.modPow(bi_d, bi_n);

                // compare
                if (bi_decrypted != bi_data)
                {
                    Console.WriteLine("\nError at round " + count);
                    Console.WriteLine(bi_data + "\n");
                    return;
                }
                Console.WriteLine(" <PASSED>.");
            }

        }
示例#15
0
        public static void RSATest(int rounds)
        {
            Random rand = new Random(1);
            byte[] val = new byte[64];

            // private and public key
            BInteger bi_e = new BInteger("a932b948feed4fb2b692609bd22164fc9edb59fae7880cc1eaff7b3c9626b7e5b241c27a974833b2622ebe09beb451917663d47232488f23a117fc97720f1e7", 16);
            BInteger bi_d = new BInteger("4adf2f7a89da93248509347d2ae506d683dd3a16357e859a980c4f77a4e2f7a01fae289f13a851df6e9db5adaa60bfd2b162bbbe31f7c8f828261a6839311929d2cef4f864dde65e556ce43c89bbbf9f1ac5511315847ce9cc8dc92470a747b8792d6a83b0092d2e5ebaf852c85cacf34278efa99160f2f8aa7ee7214de07b7", 16);
            BInteger bi_n = new BInteger("e8e77781f36a7b3188d711c2190b560f205a52391b3479cdb99fa010745cbeba5f2adc08e1de6bf38398a0487c4a73610d94ec36f17f3f46ad75e17bc1adfec99839589f45f95ccc94cb2a5c500b477eb3323d8cfab0c8458c96f0147a45d27e45a4d11d54d77684f65d48f15fafcc1ba208e71e921b9bd9017c16a5231af7f", 16);

            Console.WriteLine("e =\n" + bi_e.ToString(10));
            Console.WriteLine("\nd =\n" + bi_d.ToString(10));
            Console.WriteLine("\nn =\n" + bi_n.ToString(10) + "\n");

            for (int count = 0; count < rounds; count++)
            {
                // generate data of random length
                int t1 = 0;
                while (t1 == 0)
                    t1 = (int)(rand.NextDouble() * 65);

                bool done = false;
                while (!done)
                {
                    for (int i = 0; i < 64; i++)
                    {
                        if (i < t1)
                            val[i] = (byte)(rand.NextDouble() * 256);
                        else
                            val[i] = 0;

                        if (val[i] != 0)
                            done = true;
                    }
                }

                while (val[0] == 0)
                    val[0] = (byte)(rand.NextDouble() * 256);

                Console.Write("Round = " + count);

                // encrypt and decrypt data
                BInteger bi_data = new BInteger(val, t1);
                BInteger bi_encrypted = bi_data.modPow(bi_e, bi_n);
                BInteger bi_decrypted = bi_encrypted.modPow(bi_d, bi_n);

                // compare
                if (bi_decrypted != bi_data)
                {
                    Console.WriteLine("\nError at round " + count);
                    Console.WriteLine(bi_data + "\n");
                    return;
                }
                Console.WriteLine(" <PASSED>.");
            }

        }
示例#16
0
 //Вычисляем символ Лежандра
 public BInteger Legendre(BInteger a, BInteger q)
 {
     return a.modPow((q - 1) / 2, q);
 }
示例#17
0
 //подписываем сообщение
 public string SingGen(byte[] h, BInteger d)
 {
     BInteger alpha = new BInteger(h);
     BInteger e = alpha % n;
     if (e == 0)
         e = 1;
     BInteger k = new BInteger();
     ECPoint C = new ECPoint();
     BInteger r = new BInteger();
     BInteger s = new BInteger();
     do
     {
         do
         {
             k.genRandomBits(n.bitCount(), new Random());
         } while ((k < 0) || (k > n));
         C = ECPoint.multiply(k, G);
         r = C.x % n;
         s = ((r * d) + (k * e)) % n;
     } while ((r == 0) || (s == 0));
     string Rvector = padding(r.ToHexString(), n.bitCount() / 4);
     string Svector = padding(s.ToHexString(), n.bitCount() / 4);
     return Rvector + Svector;
 }
示例#18
0
        public static BInteger operator +(BInteger bi1, BInteger bi2)
        {
            BInteger result = new BInteger();

            result.dataLength = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;

            long carry = 0;
            for (int i = 0; i < result.dataLength; i++)
            {
                long sum = bi1.data[i] + (long)bi2.data[i] + carry;
                carry = sum >> 32;
                result.data[i] = (uint)(sum & 0xFFFFFFFF);
            }

            if (carry != 0 && result.dataLength < maxLength)
            {
                result.data[result.dataLength] = (uint)(carry);
                result.dataLength++;
            }

            while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
                result.dataLength--;


            // overflow check
            int lastPos = maxLength - 1;
            if ((bi1.data[lastPos] & 0x80000000) == (bi2.data[lastPos] & 0x80000000) &&
               (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))
            {
                throw (new ArithmeticException());
            }

            return result;
        }
示例#19
0
        public static BInteger operator -(BInteger bi1, BInteger bi2)
        {
            BInteger result = new BInteger();

            result.dataLength = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;

            long carryIn = 0;
            for (int i = 0; i < result.dataLength; i++)
            {
                long diff;

                diff = bi1.data[i] - (long)bi2.data[i] - carryIn;
                result.data[i] = (uint)(diff & 0xFFFFFFFF);

                if (diff < 0)
                    carryIn = 1;
                else
                    carryIn = 0;
            }

            if (carryIn != 0)
            {
                for (int i = result.dataLength; i < maxLength; i++)
                    result.data[i] = 0xFFFFFFFF;
                result.dataLength = maxLength;
            }
            while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
                result.dataLength--;

            int lastPos = maxLength - 1;
            if ((bi1.data[lastPos] & 0x80000000) != (bi2.data[lastPos] & 0x80000000) &&
               (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))
            {
                throw (new ArithmeticException());
            }

            return result;
        }
示例#20
0
 public DSGost(BInteger p, BInteger a, BInteger b, BInteger n, byte[] xG)
 {
     this.a = a;
     this.b = b;
     this.n = n;
     this.p = p;
     this.xG = xG;
 }
示例#21
0
        public static BInteger operator *(BInteger bi1, BInteger bi2)
        {
            int lastPos = maxLength - 1;
            bool bi1Neg = false, bi2Neg = false;
            try
            {
                if ((bi1.data[lastPos] & 0x80000000) != 0)     // bi1 negative
                {
                    bi1Neg = true; bi1 = -bi1;
                }
                if ((bi2.data[lastPos] & 0x80000000) != 0)     // bi2 negative
                {
                    bi2Neg = true; bi2 = -bi2;
                }
            }
            catch (Exception) { }

            BInteger result = new BInteger();
            try
            {
                for (int i = 0; i < bi1.dataLength; i++)
                {
                    if (bi1.data[i] == 0) continue;

                    ulong mcarry = 0;
                    for (int j = 0, k = i; j < bi2.dataLength; j++, k++)
                    {
                        // k = i + j
                        ulong val = bi1.data[i] * (ulong)bi2.data[j] +
                                     result.data[k] + mcarry;

                        result.data[k] = (uint)(val & 0xFFFFFFFF);
                        mcarry = (val >> 32);
                    }

                    if (mcarry != 0)
                        result.data[i + bi2.dataLength] = (uint)mcarry;
                }
            }
            catch (Exception)
            {
                throw (new ArithmeticException("Multiplication overflow."));
            }


            result.dataLength = bi1.dataLength + bi2.dataLength;
            if (result.dataLength > maxLength)
                result.dataLength = maxLength;

            while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
                result.dataLength--;

            if ((result.data[lastPos] & 0x80000000) != 0)
            {
                if (bi1Neg != bi2Neg && result.data[lastPos] == 0x80000000)    // different sign
                {

                    if (result.dataLength == 1)
                        return result;
                    else
                    {
                        bool isMaxNeg = true;
                        for (int i = 0; i < result.dataLength - 1 && isMaxNeg; i++)
                        {
                            if (result.data[i] != 0)
                                isMaxNeg = false;
                        }

                        if (isMaxNeg)
                            return result;
                    }
                }

                throw (new ArithmeticException("Multiplication overflow."));
            }

            if (bi1Neg != bi2Neg)
                return -result;

            return result;
        }
示例#22
0
 //Генерируем секретный ключ заданной длины
 public BInteger GenPrivateKey(int BitSize)
 {
     BInteger d = new BInteger();
     do
     {
         d.genRandomBits(BitSize, new Random());
     } while ((d < 0) || (d > n));
     return d;
 }
示例#23
0
        public static BInteger operator >>(BInteger bi1, int shiftVal)
        {
            BInteger result = new BInteger(bi1);
            result.dataLength = shiftRight(result.data, shiftVal);


            if ((bi1.data[maxLength - 1] & 0x80000000) != 0) // negative
            {
                for (int i = maxLength - 1; i >= result.dataLength; i--)
                    result.data[i] = 0xFFFFFFFF;

                uint mask = 0x80000000;
                for (int i = 0; i < 32; i++)
                {
                    if ((result.data[result.dataLength - 1] & mask) != 0)
                        break;

                    result.data[result.dataLength - 1] |= mask;
                    mask >>= 1;
                }
                result.dataLength = maxLength;
            }

            return result;
        }
示例#24
0
 //С помощью секретного ключа d вычисляем точку Q=d*G, это и будет наш публичный ключ
 public ECPoint GenPublicKey(BInteger d)
 {
     ECPoint G = GDecompression();
     ECPoint Q = ECPoint.multiply(d, G);
     return Q;
 }
示例#25
0
        public static BInteger operator -(BInteger bi1)
        {
            // handle neg of zero separately since it'll cause an overflow
            // if we proceed.

            if (bi1.dataLength == 1 && bi1.data[0] == 0)
                return (new BInteger());

            BInteger result = new BInteger(bi1);

            // 1's complement
            for (int i = 0; i < maxLength; i++)
                result.data[i] = ~(bi1.data[i]);

            // add one to result of 1's complement
            long val, carry = 1;
            int index = 0;

            while (carry != 0 && index < maxLength)
            {
                val = result.data[index];
                val++;

                result.data[index] = (uint)(val & 0xFFFFFFFF);
                carry = val >> 32;

                index++;
            }

            if ((bi1.data[maxLength - 1] & 0x80000000) == (result.data[maxLength - 1] & 0x80000000))
                throw (new ArithmeticException("Overflow in negation.\n"));

            result.dataLength = maxLength;

            while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
                result.dataLength--;
            return result;
        }
示例#26
0
        public static BInteger operator ++(BInteger bi1)
        {
            BInteger result = new BInteger(bi1);

            long val, carry = 1;
            int index = 0;

            while (carry != 0 && index < maxLength)
            {
                val = result.data[index];
                val++;

                result.data[index] = (uint)(val & 0xFFFFFFFF);
                carry = val >> 32;

                index++;
            }

            if (index > result.dataLength)
                result.dataLength = index;
            else
            {
                while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
                    result.dataLength--;
            }
            int lastPos = maxLength - 1;


            if ((bi1.data[lastPos] & 0x80000000) == 0 &&
               (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))
            {
                throw (new ArithmeticException("Overflow in ++."));
            }
            return result;
        }
示例#27
0
        private static void singleByteDivide(BInteger bi1, BInteger bi2,
                                             BInteger outQuotient, BInteger outRemainder)
        {
            uint[] result = new uint[maxLength];
            int resultPos = 0;

            // copy dividend to reminder
            for (int i = 0; i < maxLength; i++)
                outRemainder.data[i] = bi1.data[i];
            outRemainder.dataLength = bi1.dataLength;

            while (outRemainder.dataLength > 1 && outRemainder.data[outRemainder.dataLength - 1] == 0)
                outRemainder.dataLength--;

            ulong divisor = bi2.data[0];
            int pos = outRemainder.dataLength - 1;
            ulong dividend = outRemainder.data[pos];

            //Console.WriteLine("divisor = " + divisor + " dividend = " + dividend);
            //Console.WriteLine("divisor = " + bi2 + "\ndividend = " + bi1);

            if (dividend >= divisor)
            {
                ulong quotient = dividend / divisor;
                result[resultPos++] = (uint)quotient;

                outRemainder.data[pos] = (uint)(dividend % divisor);
            }
            pos--;

            while (pos >= 0)
            {
                //Console.WriteLine(pos);

                dividend = ((ulong)outRemainder.data[pos + 1] << 32) + outRemainder.data[pos];
                ulong quotient = dividend / divisor;
                result[resultPos++] = (uint)quotient;

                outRemainder.data[pos + 1] = 0;
                outRemainder.data[pos--] = (uint)(dividend % divisor);
                //Console.WriteLine(">>>> " + bi1);
            }

            outQuotient.dataLength = resultPos;
            int j = 0;
            for (int i = outQuotient.dataLength - 1; i >= 0; i--, j++)
                outQuotient.data[j] = result[i];
            for (; j < maxLength; j++)
                outQuotient.data[j] = 0;

            while (outQuotient.dataLength > 1 && outQuotient.data[outQuotient.dataLength - 1] == 0)
                outQuotient.dataLength--;

            if (outQuotient.dataLength == 0)
                outQuotient.dataLength = 1;

            while (outRemainder.dataLength > 1 && outRemainder.data[outRemainder.dataLength - 1] == 0)
                outRemainder.dataLength--;
        }
示例#28
0
 //Восстанавливаем координату y из координаты x и бита четности y 
 private ECPoint GDecompression()
 {
     byte y = xG[0];
     byte[] x = new byte[xG.Length - 1];
     Array.Copy(xG, 1, x, 0, xG.Length - 1);
     BInteger Xcord = new BInteger(x);
     BInteger temp = (Xcord * Xcord * Xcord + a * Xcord + b) % p;
     BInteger beta = ModSqrt(temp, p);
     BInteger Ycord = new BInteger();
     if ((beta % 2) == (y % 2))
         Ycord = beta;
     else
         Ycord = p - beta;
     ECPoint G = new ECPoint();
     G.a = a;
     G.b = b;
     G.FieldChar = p;
     G.x = Xcord;
     G.y = Ycord;
     this.G = G;
     return G;
 }
示例#29
0
        public static BInteger operator %(BInteger bi1, BInteger bi2)
        {
            BInteger quotient = new BInteger();
            BInteger remainder = new BInteger(bi1);

            int lastPos = maxLength - 1;
            bool dividendNeg = false;

            if ((bi1.data[lastPos] & 0x80000000) != 0)     // bi1 negative
            {
                bi1 = -bi1;
                dividendNeg = true;
            }
            if ((bi2.data[lastPos] & 0x80000000) != 0)     // bi2 negative
                bi2 = -bi2;

            if (bi1 < bi2)
            {
                return remainder;
            }

            else
            {
                if (bi2.dataLength == 1)
                    singleByteDivide(bi1, bi2, quotient, remainder);
                else
                    multiByteDivide(bi1, bi2, quotient, remainder);

                if (dividendNeg)
                    return -remainder;

                return remainder;
            }
        }
示例#30
0
 //функция вычисления квадратоного корня по модулю простого числа q
 public BInteger ModSqrt(BInteger a, BInteger q)
 {
     BInteger b = new BInteger();
     do
     {
         b.genRandomBits(255, new Random());
     } while (Legendre(b, q) == 1);
     BInteger s = 0;
     BInteger t = q - 1;
     while ((t & 1) != 1)
     {
         s++;
         t = t >> 1;
     }
     BInteger InvA = a.modInverse(q);
     BInteger c = b.modPow(t, q);
     BInteger r = a.modPow(((t + 1) / 2), q);
     BInteger d = new BInteger();
     for (int i = 1; i < s; i++)
     {
         BInteger temp = 2;
         temp = temp.modPow((s - i - 1), q);
         d = (r.modPow(2, q) * InvA).modPow(temp, q);
         if (d == (q - 1))
             r = (r * c) % q;
         c = c.modPow(2, q);
     }
     return r;
 }