c#rsa 非对称加密

[csharp] view plain copy
  1.   
[csharp] view plain copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace RSATest  
  7. {  
  8.     public class BigInteger  
  9.     {  
  10.         // maximum length of the BigInteger in uint (4 bytes)  
  11.         // change this to suit the required level of precision.  
  12.   
  13.         private const int maxLength = 70;  
  14.   
  15.         // primes smaller than 2000 to test the generated prime number  
  16.   
  17.         public static readonly int[] primesBelow2000 = {  
  18.         2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,  
  19.         101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,  
  20.     211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293,  
  21.     307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397,  
  22.     401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499,  
  23.     503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599,  
  24.     601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691,  
  25.     701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797,  
  26.     809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887,  
  27.     907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,  
  28.     1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097,  
  29.     1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193,  
  30.     1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297,  
  31.     1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,  
  32.     1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499,  
  33.     1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597,  
  34.     1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699,  
  35.     1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789,  
  36.     1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,  
  37.     1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999 };  
  38.   
  39.   
  40.         private uint[] data = null;             // stores bytes from the Big Integer  
  41.         public int dataLength;                 // number of actual chars used  
  42.   
  43.   
  44.         //***********************************************************************  
  45.         // Constructor (Default value for BigInteger is 0  
  46.         //***********************************************************************  
  47.   
  48.         public BigInteger()  
  49.         {  
  50.             data = new uint[maxLength];  
  51.             dataLength = 1;  
  52.         }  
  53.   
  54.   
  55.         //***********************************************************************  
  56.         // Constructor (Default value provided by long)  
  57.         //***********************************************************************  
  58.   
  59.         public BigInteger(long value)  
  60.         {  
  61.             data = new uint[maxLength];  
  62.             long tempVal = value;  
  63.   
  64.             // copy bytes from long to BigInteger without any assumption of  
  65.             // the length of the long datatype  
  66.   
  67.             dataLength = 0;  
  68.             while (value != 0 && dataLength < maxLength)  
  69.             {  
  70.                 data[dataLength] = (uint)(value & 0xFFFFFFFF);  
  71.                 value >>= 32;  
  72.                 dataLength++;  
  73.             }  
  74.   
  75.             if (tempVal > 0)         // overflow check for +ve value  
  76.             {  
  77.                 if (value != 0 || (data[maxLength - 1] & 0x80000000) != 0)  
  78.                     throw (new ArithmeticException("Positive overflow in constructor."));  
  79.             }  
  80.             else if (tempVal < 0)    // underflow check for -ve value  
  81.             {  
  82.                 if (value != -1 || (data[dataLength - 1] & 0x80000000) == 0)  
  83.                     throw (new ArithmeticException("Negative underflow in constructor."));  
  84.             }  
  85.   
  86.             if (dataLength == 0)  
  87.                 dataLength = 1;  
  88.         }  
  89.   
  90.   
  91.         //***********************************************************************  
  92.         // Constructor (Default value provided by ulong)  
  93.         //***********************************************************************  
  94.   
  95.         public BigInteger(ulong value)  
  96.         {  
  97.             data = new uint[maxLength];  
  98.   
  99.             // copy bytes from ulong to BigInteger without any assumption of  
  100.             // the length of the ulong datatype  
  101.   
  102.             dataLength = 0;  
  103.             while (value != 0 && dataLength < maxLength)  
  104.             {  
  105.                 data[dataLength] = (uint)(value & 0xFFFFFFFF);  
  106.                 value >>= 32;  
  107.                 dataLength++;  
  108.             }  
  109.   
  110.             if (value != 0 || (data[maxLength - 1] & 0x80000000) != 0)  
  111.                 throw (new ArithmeticException("Positive overflow in constructor."));  
  112.   
  113.             if (dataLength == 0)  
  114.                 dataLength = 1;  
  115.         }  
  116.   
  117.   
  118.   
  119.         //***********************************************************************  
  120.         // Constructor (Default value provided by BigInteger)  
  121.         //***********************************************************************  
  122.   
  123.         public BigInteger(BigInteger bi)  
  124.         {  
  125.             data = new uint[maxLength];  
  126.   
  127.             dataLength = bi.dataLength;  
  128.   
  129.             for (int i = 0; i < dataLength; i++)  
  130.                 data[i] = bi.data[i];  
  131.         }  
  132.   
  133.   
  134.         //***********************************************************************  
  135.         // Constructor (Default value provided by a string of digits of the  
  136.         //              specified base)  
  137.         //  
  138.         // Example (base 10)  
  139.         // -----------------  
  140.         // To initialize "a" with the default value of 1234 in base 10  
  141.         //      BigInteger a = new BigInteger("1234", 10)  
  142.         //  
  143.         // To initialize "a" with the default value of -1234  
  144.         //      BigInteger a = new BigInteger("-1234", 10)  
  145.         //  
  146.         // Example (base 16)  
  147.         // -----------------  
  148.         // To initialize "a" with the default value of 0x1D4F in base 16  
  149.         //      BigInteger a = new BigInteger("1D4F", 16)  
  150.         //  
  151.         // To initialize "a" with the default value of -0x1D4F  
  152.         //      BigInteger a = new BigInteger("-1D4F", 16)  
  153.         //  
  154.         // Note that string values are specified in the <sign><magnitude>  
  155.         // format.  
  156.         //  
  157.         //***********************************************************************  
  158.   
  159.         public BigInteger(string value, int radix)  
  160.         {  
  161.             BigInteger multiplier = new BigInteger(1);  
  162.             BigInteger result = new BigInteger();  
  163.             value = (value.ToUpper()).Trim();  
  164.             int limit = 0;  
  165.   
  166.             if (value[0] == '-')  
  167.                 limit = 1;  
  168.   
  169.             for (int i = value.Length - 1; i >= limit; i--)  
  170.             {  
  171.                 int posVal = (int)value[i];  
  172.   
  173.                 if (posVal >= '0' && posVal <= '9')  
  174.                     posVal -= '0';  
  175.                 else if (posVal >= 'A' && posVal <= 'Z')  
  176.                     posVal = (posVal - 'A') + 10;  
  177.                 else  
  178.                     posVal = 9999999;       // arbitrary large  
  179.   
  180.   
  181.                 if (posVal >= radix)  
  182.                     throw (new ArithmeticException("Invalid string in constructor."));  
  183.                 else  
  184.                 {  
  185.                     if (value[0] == '-')  
  186.                         posVal = -posVal;  
  187.   
  188.                     result = result + (multiplier * posVal);  
  189.   
  190.                     if ((i - 1) >= limit)  
  191.                         multiplier = multiplier * radix;  
  192.                 }  
  193.             }  
  194.   
  195.             if (value[0] == '-')     // negative values  
  196.             {  
  197.                 if ((result.data[maxLength - 1] & 0x80000000) == 0)  
  198.                     throw (new ArithmeticException("Negative underflow in constructor."));  
  199.             }  
  200.             else    // positive values  
  201.             {  
  202.                 if ((result.data[maxLength - 1] & 0x80000000) != 0)  
  203.                     throw (new ArithmeticException("Positive overflow in constructor."));  
  204.             }  
  205.   
  206.             data = new uint[maxLength];  
  207.             for (int i = 0; i < result.dataLength; i++)  
  208.                 data[i] = result.data[i];  
  209.   
  210.             dataLength = result.dataLength;  
  211.         }  
  212.   
  213.   
  214.         //***********************************************************************  
  215.         // Constructor (Default value provided by an array of bytes)  
  216.         //  
  217.         // The lowest index of the input byte array (i.e [0]) should contain the  
  218.         // most significant byte of the number, and the highest index should  
  219.         // contain the least significant byte.  
  220.         //  
  221.         // E.g.  
  222.         // To initialize "a" with the default value of 0x1D4F in base 16  
  223.         //      byte[] temp = { 0x1D, 0x4F };  
  224.         //      BigInteger a = new BigInteger(temp)  
  225.         //  
  226.         // Note that this method of initialization does not allow the  
  227.         // sign to be specified.  
  228.         //  
  229.         //***********************************************************************  
  230.   
  231.         public BigInteger(byte[] inData)  
  232.         {  
  233.             dataLength = inData.Length >> 2;  
  234.   
  235.             int leftOver = inData.Length & 0x3;  
  236.             if (leftOver != 0)         // length not multiples of 4  
  237.                 dataLength++;  
  238.   
  239.   
  240.             if (dataLength > maxLength)  
  241.                 throw (new ArithmeticException("Byte overflow in constructor."));  
  242.   
  243.             data = new uint[maxLength];  
  244.   
  245.             for (int i = inData.Length - 1, j = 0; i >= 3; i -= 4, j++)  
  246.             {  
  247.                 data[j] = (uint)((inData[i - 3] << 24) + (inData[i - 2] << 16) +  
  248.                                  (inData[i - 1] << 8) + inData[i]);  
  249.             }  
  250.   
  251.             if (leftOver == 1)  
  252.                 data[dataLength - 1] = (uint)inData[0];  
  253.             else if (leftOver == 2)  
  254.                 data[dataLength - 1] = (uint)((inData[0] << 8) + inData[1]);  
  255.             else if (leftOver == 3)  
  256.                 data[dataLength - 1] = (uint)((inData[0] << 16) + (inData[1] << 8) + inData[2]);  
  257.   
  258.   
  259.             while (dataLength > 1 && data[dataLength - 1] == 0)  
  260.                 dataLength--;  
  261.   
  262.             //Console.WriteLine("Len = " + dataLength);  
  263.         }  
  264.   
  265.   
  266.         //***********************************************************************  
  267.         // Constructor (Default value provided by an array of bytes of the  
  268.         // specified length.)  
  269.         //***********************************************************************  
  270.   
  271.         public BigInteger(byte[] inData, int inLen)  
  272.         {  
  273.             dataLength = inLen >> 2;  
  274.   
  275.             int leftOver = inLen & 0x3;  
  276.             if (leftOver != 0)         // length not multiples of 4  
  277.                 dataLength++;  
  278.   
  279.             if (dataLength > maxLength || inLen > inData.Length)  
  280.                 throw (new ArithmeticException("Byte overflow in constructor."));  
  281.   
  282.   
  283.             data = new uint[maxLength];  
  284.   
  285.             for (int i = inLen - 1, j = 0; i >= 3; i -= 4, j++)  
  286.             {  
  287.                 data[j] = (uint)((inData[i - 3] << 24) + (inData[i - 2] << 16) +  
  288.                                  (inData[i - 1] << 8) + inData[i]);  
  289.             }  
  290.   
  291.             if (leftOver == 1)  
  292.                 data[dataLength - 1] = (uint)inData[0];  
  293.             else if (leftOver == 2)  
  294.                 data[dataLength - 1] = (uint)((inData[0] << 8) + inData[1]);  
  295.             else if (leftOver == 3)  
  296.                 data[dataLength - 1] = (uint)((inData[0] << 16) + (inData[1] << 8) + inData[2]);  
  297.   
  298.   
  299.             if (dataLength == 0)  
  300.                 dataLength = 1;  
  301.   
  302.             while (dataLength > 1 && data[dataLength - 1] == 0)  
  303.                 dataLength--;  
  304.   
  305.             //Console.WriteLine("Len = " + dataLength);  
  306.         }  
  307.   
  308.   
  309.         //***********************************************************************  
  310.         // Constructor (Default value provided by an array of unsigned integers)  
  311.         //*********************************************************************  
  312.   
  313.         public BigInteger(uint[] inData)  
  314.         {  
  315.             dataLength = inData.Length;  
  316.   
  317.             if (dataLength > maxLength)  
  318.                 throw (new ArithmeticException("Byte overflow in constructor."));  
  319.   
  320.             data = new uint[maxLength];  
  321.   
  322.             for (int i = dataLength - 1, j = 0; i >= 0; i--, j++)  
  323.                 data[j] = inData[i];  
  324.   
  325.             while (dataLength > 1 && data[dataLength - 1] == 0)  
  326.                 dataLength--;  
  327.   
  328.             //Console.WriteLine("Len = " + dataLength);  
  329.         }  
  330.   
  331.   
  332.         //***********************************************************************  
  333.         // Overloading of the typecast operator.  
  334.         // For BigInteger bi = 10;  
  335.         //***********************************************************************  
  336.   
  337.         public static implicit operator BigInteger(long value)  
  338.         {  
  339.             return (new BigInteger(value));  
  340.         }  
  341.   
  342.         public static implicit operator BigInteger(ulong value)  
  343.         {  
  344.             return (new BigInteger(value));  
  345.         }  
  346.   
  347.         public static implicit operator BigInteger(int value)  
  348.         {  
  349.             return (new BigInteger((long)value));  
  350.         }  
  351.   
  352.         public static implicit operator BigInteger(uint value)  
  353.         {  
  354.             return (new BigInteger((ulong)value));  
  355.         }  
  356.   
  357.   
  358.         //***********************************************************************  
  359.         // Overloading of addition operator  
  360.         //***********************************************************************  
  361.   
  362.         public static BigInteger operator +(BigInteger bi1, BigInteger bi2)  
  363.         {  
  364.             BigInteger result = new BigInteger();  
  365.   
  366.             result.dataLength = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;  
  367.   
  368.             long carry = 0;  
  369.             for (int i = 0; i < result.dataLength; i++)  
  370.             {  
  371.                 long sum = (long)bi1.data[i] + (long)bi2.data[i] + carry;  
  372.                 carry = sum >> 32;  
  373.                 result.data[i] = (uint)(sum & 0xFFFFFFFF);  
  374.             }  
  375.   
  376.             if (carry != 0 && result.dataLength < maxLength)  
  377.             {  
  378.                 result.data[result.dataLength] = (uint)(carry);  
  379.                 result.dataLength++;  
  380.             }  
  381.   
  382.             while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  383.                 result.dataLength--;  
  384.   
  385.   
  386.             // overflow check  
  387.             int lastPos = maxLength - 1;  
  388.             if ((bi1.data[lastPos] & 0x80000000) == (bi2.data[lastPos] & 0x80000000) &&  
  389.                (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))  
  390.             {  
  391.                 throw (new ArithmeticException());  
  392.             }  
  393.   
  394.             return result;  
  395.         }  
  396.   
  397.   
  398.         //***********************************************************************  
  399.         // Overloading of the unary ++ operator  
  400.         //***********************************************************************  
  401.   
  402.         public static BigInteger operator ++(BigInteger bi1)  
  403.         {  
  404.             BigInteger result = new BigInteger(bi1);  
  405.   
  406.             long val, carry = 1;  
  407.             int index = 0;  
  408.   
  409.             while (carry != 0 && index < maxLength)  
  410.             {  
  411.                 val = (long)(result.data[index]);  
  412.                 val++;  
  413.   
  414.                 result.data[index] = (uint)(val & 0xFFFFFFFF);  
  415.                 carry = val >> 32;  
  416.   
  417.                 index++;  
  418.             }  
  419.   
  420.             if (index > result.dataLength)  
  421.                 result.dataLength = index;  
  422.             else  
  423.             {  
  424.                 while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  425.                     result.dataLength--;  
  426.             }  
  427.   
  428.             // overflow check  
  429.             int lastPos = maxLength - 1;  
  430.   
  431.             // overflow if initial value was +ve but ++ caused a sign  
  432.             // change to negative.  
  433.   
  434.             if ((bi1.data[lastPos] & 0x80000000) == 0 &&  
  435.                (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))  
  436.             {  
  437.                 throw (new ArithmeticException("Overflow in ++."));  
  438.             }  
  439.             return result;  
  440.         }  
  441.   
  442.   
  443.         //***********************************************************************  
  444.         // Overloading of subtraction operator  
  445.         //***********************************************************************  
  446.   
  447.         public static BigInteger operator -(BigInteger bi1, BigInteger bi2)  
  448.         {  
  449.             BigInteger result = new BigInteger();  
  450.   
  451.             result.dataLength = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;  
  452.   
  453.             long carryIn = 0;  
  454.             for (int i = 0; i < result.dataLength; i++)  
  455.             {  
  456.                 long diff;  
  457.   
  458.                 diff = (long)bi1.data[i] - (long)bi2.data[i] - carryIn;  
  459.                 result.data[i] = (uint)(diff & 0xFFFFFFFF);  
  460.   
  461.                 if (diff < 0)  
  462.                     carryIn = 1;  
  463.                 else  
  464.                     carryIn = 0;  
  465.             }  
  466.   
  467.             // roll over to negative  
  468.             if (carryIn != 0)  
  469.             {  
  470.                 for (int i = result.dataLength; i < maxLength; i++)  
  471.                     result.data[i] = 0xFFFFFFFF;  
  472.                 result.dataLength = maxLength;  
  473.             }  
  474.   
  475.             // fixed in v1.03 to give correct datalength for a - (-b)  
  476.             while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  477.                 result.dataLength--;  
  478.   
  479.             // overflow check  
  480.   
  481.             int lastPos = maxLength - 1;  
  482.             if ((bi1.data[lastPos] & 0x80000000) != (bi2.data[lastPos] & 0x80000000) &&  
  483.                (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))  
  484.             {  
  485.                 throw (new ArithmeticException());  
  486.             }  
  487.   
  488.             return result;  
  489.         }  
  490.   
  491.   
  492.         //***********************************************************************  
  493.         // Overloading of the unary -- operator  
  494.         //***********************************************************************  
  495.   
  496.         public static BigInteger operator --(BigInteger bi1)  
  497.         {  
  498.             BigInteger result = new BigInteger(bi1);  
  499.   
  500.             long val;  
  501.             bool carryIn = true;  
  502.             int index = 0;  
  503.   
  504.             while (carryIn && index < maxLength)  
  505.             {  
  506.                 val = (long)(result.data[index]);  
  507.                 val--;  
  508.   
  509.                 result.data[index] = (uint)(val & 0xFFFFFFFF);  
  510.   
  511.                 if (val >= 0)  
  512.                     carryIn = false;  
  513.   
  514.                 index++;  
  515.             }  
  516.   
  517.             if (index > result.dataLength)  
  518.                 result.dataLength = index;  
  519.   
  520.             while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  521.                 result.dataLength--;  
  522.   
  523.             // overflow check  
  524.             int lastPos = maxLength - 1;  
  525.   
  526.             // overflow if initial value was -ve but -- caused a sign  
  527.             // change to positive.  
  528.   
  529.             if ((bi1.data[lastPos] & 0x80000000) != 0 &&  
  530.                (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))  
  531.             {  
  532.                 throw (new ArithmeticException("Underflow in --."));  
  533.             }  
  534.   
  535.             return result;  
  536.         }  
  537.   
  538.   
  539.         //***********************************************************************  
  540.         // Overloading of multiplication operator  
  541.         //***********************************************************************  
  542.   
  543.         public static BigInteger operator *(BigInteger bi1, BigInteger bi2)  
  544.         {  
  545.             int lastPos = maxLength - 1;  
  546.             bool bi1Neg = false, bi2Neg = false;  
  547.   
  548.             // take the absolute value of the inputs  
  549.             try  
  550.             {  
  551.                 if ((bi1.data[lastPos] & 0x80000000) != 0)     // bi1 negative  
  552.                 {  
  553.                     bi1Neg = true; bi1 = -bi1;  
  554.                 }  
  555.                 if ((bi2.data[lastPos] & 0x80000000) != 0)     // bi2 negative  
  556.                 {  
  557.                     bi2Neg = true; bi2 = -bi2;  
  558.                 }  
  559.             }  
  560.             catch (Exception) { }  
  561.   
  562.             BigInteger result = new BigInteger();  
  563.   
  564.             // multiply the absolute values  
  565.             try  
  566.             {  
  567.                 for (int i = 0; i < bi1.dataLength; i++)  
  568.                 {  
  569.                     if (bi1.data[i] == 0) continue;  
  570.   
  571.                     ulong mcarry = 0;  
  572.                     for (int j = 0, k = i; j < bi2.dataLength; j++, k++)  
  573.                     {  
  574.                         // k = i + j  
  575.                         ulong val = ((ulong)bi1.data[i] * (ulong)bi2.data[j]) +  
  576.                                      (ulong)result.data[k] + mcarry;  
  577.   
  578.                         result.data[k] = (uint)(val & 0xFFFFFFFF);  
  579.                         mcarry = (val >> 32);  
  580.                     }  
  581.   
  582.                     if (mcarry != 0)  
  583.                         result.data[i + bi2.dataLength] = (uint)mcarry;  
  584.                 }  
  585.             }  
  586.             catch (Exception)  
  587.             {  
  588.                 throw (new ArithmeticException("Multiplication overflow."));  
  589.             }  
  590.   
  591.   
  592.             result.dataLength = bi1.dataLength + bi2.dataLength;  
  593.             if (result.dataLength > maxLength)  
  594.                 result.dataLength = maxLength;  
  595.   
  596.             while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  597.                 result.dataLength--;  
  598.   
  599.             // overflow check (result is -ve)  
  600.             if ((result.data[lastPos] & 0x80000000) != 0)  
  601.             {  
  602.                 if (bi1Neg != bi2Neg && result.data[lastPos] == 0x80000000)    // different sign  
  603.                 {  
  604.                     // handle the special case where multiplication produces  
  605.                     // a max negative number in 2's complement.  
  606.   
  607.                     if (result.dataLength == 1)  
  608.                         return result;  
  609.                     else  
  610.                     {  
  611.                         bool isMaxNeg = true;  
  612.                         for (int i = 0; i < result.dataLength - 1 && isMaxNeg; i++)  
  613.                         {  
  614.                             if (result.data[i] != 0)  
  615.                                 isMaxNeg = false;  
  616.                         }  
  617.   
  618.                         if (isMaxNeg)  
  619.                             return result;  
  620.                     }  
  621.                 }  
  622.   
  623.                 throw (new ArithmeticException("Multiplication overflow."));  
  624.             }  
  625.   
  626.             // if input has different signs, then result is -ve  
  627.             if (bi1Neg != bi2Neg)  
  628.                 return -result;  
  629.   
  630.             return result;  
  631.         }  
  632.   
  633.   
  634.   
  635.         //***********************************************************************  
  636.         // Overloading of unary << operators  
  637.         //***********************************************************************  
  638.   
  639.         public static BigInteger operator <<(BigInteger bi1, int shiftVal)  
  640.         {  
  641.             BigInteger result = new BigInteger(bi1);  
  642.             result.dataLength = shiftLeft(result.data, shiftVal);  
  643.   
  644.             return result;  
  645.         }  
  646.   
  647.   
  648.         // least significant bits at lower part of buffer  
  649.   
  650.         private static int shiftLeft(uint[] buffer, int shiftVal)  
  651.         {  
  652.             int shiftAmount = 32;  
  653.             int bufLen = buffer.Length;  
  654.   
  655.             while (bufLen > 1 && buffer[bufLen - 1] == 0)  
  656.                 bufLen--;  
  657.   
  658.             for (int count = shiftVal; count > 0; )  
  659.             {  
  660.                 if (count < shiftAmount)  
  661.                     shiftAmount = count;  
  662.   
  663.                 //Console.WriteLine("shiftAmount = {0}", shiftAmount);  
  664.   
  665.                 ulong carry = 0;  
  666.                 for (int i = 0; i < bufLen; i++)  
  667.                 {  
  668.                     ulong val = ((ulong)buffer[i]) << shiftAmount;  
  669.                     val |= carry;  
  670.   
  671.                     buffer[i] = (uint)(val & 0xFFFFFFFF);  
  672.                     carry = val >> 32;  
  673.                 }  
  674.   
  675.                 if (carry != 0)  
  676.                 {  
  677.                     if (bufLen + 1 <= buffer.Length)  
  678.                     {  
  679.                         buffer[bufLen] = (uint)carry;  
  680.                         bufLen++;  
  681.                     }  
  682.                 }  
  683.                 count -= shiftAmount;  
  684.             }  
  685.             return bufLen;  
  686.         }  
  687.   
  688.   
  689.         //***********************************************************************  
  690.         // Overloading of unary >> operators  
  691.         //***********************************************************************  
  692.   
  693.         public static BigInteger operator >>(BigInteger bi1, int shiftVal)  
  694.         {  
  695.             BigInteger result = new BigInteger(bi1);  
  696.             result.dataLength = shiftRight(result.data, shiftVal);  
  697.   
  698.   
  699.             if ((bi1.data[maxLength - 1] & 0x80000000) != 0) // negative  
  700.             {  
  701.                 for (int i = maxLength - 1; i >= result.dataLength; i--)  
  702.                     result.data[i] = 0xFFFFFFFF;  
  703.   
  704.                 uint mask = 0x80000000;  
  705.                 for (int i = 0; i < 32; i++)  
  706.                 {  
  707.                     if ((result.data[result.dataLength - 1] & mask) != 0)  
  708.                         break;  
  709.   
  710.                     result.data[result.dataLength - 1] |= mask;  
  711.                     mask >>= 1;  
  712.                 }  
  713.                 result.dataLength = maxLength;  
  714.             }  
  715.   
  716.             return result;  
  717.         }  
  718.   
  719.   
  720.         private static int shiftRight(uint[] buffer, int shiftVal)  
  721.         {  
  722.             int shiftAmount = 32;  
  723.             int invShift = 0;  
  724.             int bufLen = buffer.Length;  
  725.   
  726.             while (bufLen > 1 && buffer[bufLen - 1] == 0)  
  727.                 bufLen--;  
  728.   
  729.             //Console.WriteLine("bufLen = " + bufLen + " buffer.Length = " + buffer.Length);  
  730.   
  731.             for (int count = shiftVal; count > 0; )  
  732.             {  
  733.                 if (count < shiftAmount)  
  734.                 {  
  735.                     shiftAmount = count;  
  736.                     invShift = 32 - shiftAmount;  
  737.                 }  
  738.   
  739.                 //Console.WriteLine("shiftAmount = {0}", shiftAmount);  
  740.   
  741.                 ulong carry = 0;  
  742.                 for (int i = bufLen - 1; i >= 0; i--)  
  743.                 {  
  744.                     ulong val = ((ulong)buffer[i]) >> shiftAmount;  
  745.                     val |= carry;  
  746.   
  747.                     carry = ((ulong)buffer[i]) << invShift;  
  748.                     buffer[i] = (uint)(val);  
  749.                 }  
  750.   
  751.                 count -= shiftAmount;  
  752.             }  
  753.   
  754.             while (bufLen > 1 && buffer[bufLen - 1] == 0)  
  755.                 bufLen--;  
  756.   
  757.             return bufLen;  
  758.         }  
  759.   
  760.   
  761.         //***********************************************************************  
  762.         // Overloading of the NOT operator (1's complement)  
  763.         //***********************************************************************  
  764.   
  765.         public static BigInteger operator ~(BigInteger bi1)  
  766.         {  
  767.             BigInteger result = new BigInteger(bi1);  
  768.   
  769.             for (int i = 0; i < maxLength; i++)  
  770.                 result.data[i] = (uint)(~(bi1.data[i]));  
  771.   
  772.             result.dataLength = maxLength;  
  773.   
  774.             while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  775.                 result.dataLength--;  
  776.   
  777.             return result;  
  778.         }  
  779.   
  780.   
  781.         //***********************************************************************  
  782.         // Overloading of the NEGATE operator (2's complement)  
  783.         //***********************************************************************  
  784.   
  785.         public static BigInteger operator -(BigInteger bi1)  
  786.         {  
  787.             // handle neg of zero separately since it'll cause an overflow  
  788.             // if we proceed.  
  789.   
  790.             if (bi1.dataLength == 1 && bi1.data[0] == 0)  
  791.                 return (new BigInteger());  
  792.   
  793.             BigInteger result = new BigInteger(bi1);  
  794.   
  795.             // 1's complement  
  796.             for (int i = 0; i < maxLength; i++)  
  797.                 result.data[i] = (uint)(~(bi1.data[i]));  
  798.   
  799.             // add one to result of 1's complement  
  800.             long val, carry = 1;  
  801.             int index = 0;  
  802.   
  803.             while (carry != 0 && index < maxLength)  
  804.             {  
  805.                 val = (long)(result.data[index]);  
  806.                 val++;  
  807.   
  808.                 result.data[index] = (uint)(val & 0xFFFFFFFF);  
  809.                 carry = val >> 32;  
  810.   
  811.                 index++;  
  812.             }  
  813.   
  814.             if ((bi1.data[maxLength - 1] & 0x80000000) == (result.data[maxLength - 1] & 0x80000000))  
  815.                 throw (new ArithmeticException("Overflow in negation.\n"));  
  816.   
  817.             result.dataLength = maxLength;  
  818.   
  819.             while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  820.                 result.dataLength--;  
  821.             return result;  
  822.         }  
  823.   
  824.   
  825.         //***********************************************************************  
  826.         // Overloading of equality operator  
  827.         //***********************************************************************  
  828.   
  829.         public static bool operator ==(BigInteger bi1, BigInteger bi2)  
  830.         {  
  831.             return bi1.Equals(bi2);  
  832.         }  
  833.   
  834.   
  835.         public static bool operator !=(BigInteger bi1, BigInteger bi2)  
  836.         {  
  837.             return !(bi1.Equals(bi2));  
  838.         }  
  839.   
  840.   
  841.         public override bool Equals(object o)  
  842.         {  
  843.             BigInteger bi = (BigInteger)o;  
  844.   
  845.             if (this.dataLength != bi.dataLength)  
  846.                 return false;  
  847.   
  848.             for (int i = 0; i < this.dataLength; i++)  
  849.             {  
  850.                 if (this.data[i] != bi.data[i])  
  851.                     return false;  
  852.             }  
  853.             return true;  
  854.         }  
  855.   
  856.   
  857.         public override int GetHashCode()  
  858.         {  
  859.             return this.ToString().GetHashCode();  
  860.         }  
  861.   
  862.   
  863.         //***********************************************************************  
  864.         // Overloading of inequality operator  
  865.         //***********************************************************************  
  866.   
  867.         public static bool operator >(BigInteger bi1, BigInteger bi2)  
  868.         {  
  869.             int pos = maxLength - 1;  
  870.   
  871.             // bi1 is negative, bi2 is positive  
  872.             if ((bi1.data[pos] & 0x80000000) != 0 && (bi2.data[pos] & 0x80000000) == 0)  
  873.                 return false;  
  874.   
  875.                 // bi1 is positive, bi2 is negative  
  876.             else if ((bi1.data[pos] & 0x80000000) == 0 && (bi2.data[pos] & 0x80000000) != 0)  
  877.                 return true;  
  878.   
  879.             // same sign  
  880.             int len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;  
  881.             for (pos = len - 1; pos >= 0 && bi1.data[pos] == bi2.data[pos]; pos--) ;  
  882.   
  883.             if (pos >= 0)  
  884.             {  
  885.                 if (bi1.data[pos] > bi2.data[pos])  
  886.                     return true;  
  887.                 return false;  
  888.             }  
  889.             return false;  
  890.         }  
  891.   
  892.   
  893.         public static bool operator <(BigInteger bi1, BigInteger bi2)  
  894.         {  
  895.             int pos = maxLength - 1;  
  896.   
  897.             // bi1 is negative, bi2 is positive  
  898.             if ((bi1.data[pos] & 0x80000000) != 0 && (bi2.data[pos] & 0x80000000) == 0)  
  899.                 return true;  
  900.   
  901.                 // bi1 is positive, bi2 is negative  
  902.             else if ((bi1.data[pos] & 0x80000000) == 0 && (bi2.data[pos] & 0x80000000) != 0)  
  903.                 return false;  
  904.   
  905.             // same sign  
  906.             int len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;  
  907.             for (pos = len - 1; pos >= 0 && bi1.data[pos] == bi2.data[pos]; pos--) ;  
  908.   
  909.             if (pos >= 0)  
  910.             {  
  911.                 if (bi1.data[pos] < bi2.data[pos])  
  912.                     return true;  
  913.                 return false;  
  914.             }  
  915.             return false;  
  916.         }  
  917.   
  918.   
  919.         public static bool operator >=(BigInteger bi1, BigInteger bi2)  
  920.         {  
  921.             return (bi1 == bi2 || bi1 > bi2);  
  922.         }  
  923.   
  924.   
  925.         public static bool operator <=(BigInteger bi1, BigInteger bi2)  
  926.         {  
  927.             return (bi1 == bi2 || bi1 < bi2);  
  928.         }  
  929.   
  930.   
  931.         //***********************************************************************  
  932.         // Private function that supports the division of two numbers with  
  933.         // a divisor that has more than 1 digit.  
  934.         //  
  935.         // Algorithm taken from [1]  
  936.         //***********************************************************************  
  937.   
  938.         private static void multiByteDivide(BigInteger bi1, BigInteger bi2,  
  939.                                             BigInteger outQuotient, BigInteger outRemainder)  
  940.         {  
  941.             uint[] result = new uint[maxLength];  
  942.   
  943.             int remainderLen = bi1.dataLength + 1;  
  944.             uint[] remainder = new uint[remainderLen];  
  945.   
  946.             uint mask = 0x80000000;  
  947.             uint val = bi2.data[bi2.dataLength - 1];  
  948.             int shift = 0, resultPos = 0;  
  949.   
  950.             while (mask != 0 && (val & mask) == 0)  
  951.             {  
  952.                 shift++; mask >>= 1;  
  953.             }  
  954.   
  955.             //Console.WriteLine("shift = {0}", shift);  
  956.             //Console.WriteLine("Before bi1 Len = {0}, bi2 Len = {1}", bi1.dataLength, bi2.dataLength);  
  957.   
  958.             for (int i = 0; i < bi1.dataLength; i++)  
  959.                 remainder[i] = bi1.data[i];  
  960.             shiftLeft(remainder, shift);  
  961.             bi2 = bi2 << shift;  
  962.   
  963.             /*  
  964.             Console.WriteLine("bi1 Len = {0}, bi2 Len = {1}", bi1.dataLength, bi2.dataLength);  
  965.             Console.WriteLine("dividend = " + bi1 + "\ndivisor = " + bi2);  
  966.             for(int q = remainderLen - 1; q >= 0; q--)  
  967.                     Console.Write("{0:x2}", remainder[q]);  
  968.             Console.WriteLine();  
  969.             */  
  970.   
  971.             int j = remainderLen - bi2.dataLength;  
  972.             int pos = remainderLen - 1;  
  973.   
  974.             ulong firstDivisorByte = bi2.data[bi2.dataLength - 1];  
  975.             ulong secondDivisorByte = bi2.data[bi2.dataLength - 2];  
  976.   
  977.             int divisorLen = bi2.dataLength + 1;  
  978.             uint[] dividendPart = new uint[divisorLen];  
  979.   
  980.             while (j > 0)  
  981.             {  
  982.                 ulong dividend = ((ulong)remainder[pos] << 32) + (ulong)remainder[pos - 1];  
  983.                 //Console.WriteLine("dividend = {0}", dividend);  
  984.   
  985.                 ulong q_hat = dividend / firstDivisorByte;  
  986.                 ulong r_hat = dividend % firstDivisorByte;  
  987.   
  988.                 //Console.WriteLine("q_hat = {0:X}, r_hat = {1:X}", q_hat, r_hat);  
  989.   
  990.                 bool done = false;  
  991.                 while (!done)  
  992.                 {  
  993.                     done = true;  
  994.   
  995.                     if (q_hat == 0x100000000 ||  
  996.                        (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder[pos - 2]))  
  997.                     {  
  998.                         q_hat--;  
  999.                         r_hat += firstDivisorByte;  
  1000.   
  1001.                         if (r_hat < 0x100000000)  
  1002.                             done = false;  
  1003.                     }  
  1004.                 }  
  1005.   
  1006.                 for (int h = 0; h < divisorLen; h++)  
  1007.                     dividendPart[h] = remainder[pos - h];  
  1008.   
  1009.                 BigInteger kk = new BigInteger(dividendPart);  
  1010.                 BigInteger ss = bi2 * (long)q_hat;  
  1011.   
  1012.                 //Console.WriteLine("ss before = " + ss);  
  1013.                 while (ss > kk)  
  1014.                 {  
  1015.                     q_hat--;  
  1016.                     ss -= bi2;  
  1017.                     //Console.WriteLine(ss);  
  1018.                 }  
  1019.                 BigInteger yy = kk - ss;  
  1020.   
  1021.                 //Console.WriteLine("ss = " + ss);  
  1022.                 //Console.WriteLine("kk = " + kk);  
  1023.                 //Console.WriteLine("yy = " + yy);  
  1024.   
  1025.                 for (int h = 0; h < divisorLen; h++)  
  1026.                     remainder[pos - h] = yy.data[bi2.dataLength - h];  
  1027.   
  1028.                 /* 
  1029.                 Console.WriteLine("dividend = "); 
  1030.                 for(int q = remainderLen - 1; q >= 0; q--) 
  1031.                         Console.Write("{0:x2}", remainder[q]); 
  1032.                 Console.WriteLine("\n************ q_hat = {0:X}\n", q_hat); 
  1033.                 */  
  1034.   
  1035.                 result[resultPos++] = (uint)q_hat;  
  1036.   
  1037.                 pos--;  
  1038.                 j--;  
  1039.             }  
  1040.   
  1041.             outQuotient.dataLength = resultPos;  
  1042.             int y = 0;  
  1043.             for (int x = outQuotient.dataLength - 1; x >= 0; x--, y++)  
  1044.                 outQuotient.data[y] = result[x];  
  1045.             for (; y < maxLength; y++)  
  1046.                 outQuotient.data[y] = 0;  
  1047.   
  1048.             while (outQuotient.dataLength > 1 && outQuotient.data[outQuotient.dataLength - 1] == 0)  
  1049.                 outQuotient.dataLength--;  
  1050.   
  1051.             if (outQuotient.dataLength == 0)  
  1052.                 outQuotient.dataLength = 1;  
  1053.   
  1054.             outRemainder.dataLength = shiftRight(remainder, shift);  
  1055.   
  1056.             for (y = 0; y < outRemainder.dataLength; y++)  
  1057.                 outRemainder.data[y] = remainder[y];  
  1058.             for (; y < maxLength; y++)  
  1059.                 outRemainder.data[y] = 0;  
  1060.         }  
  1061.   
  1062.   
  1063.         //***********************************************************************  
  1064.         // Private function that supports the division of two numbers with  
  1065.         // a divisor that has only 1 digit.  
  1066.         //***********************************************************************  
  1067.   
  1068.         private static void singleByteDivide(BigInteger bi1, BigInteger bi2,  
  1069.                                              BigInteger outQuotient, BigInteger outRemainder)  
  1070.         {  
  1071.             uint[] result = new uint[maxLength];  
  1072.             int resultPos = 0;  
  1073.   
  1074.             // copy dividend to reminder  
  1075.             for (int i = 0; i < maxLength; i++)  
  1076.                 outRemainder.data[i] = bi1.data[i];  
  1077.             outRemainder.dataLength = bi1.dataLength;  
  1078.   
  1079.             while (outRemainder.dataLength > 1 && outRemainder.data[outRemainder.dataLength - 1] == 0)  
  1080.                 outRemainder.dataLength--;  
  1081.   
  1082.             ulong divisor = (ulong)bi2.data[0];  
  1083.             int pos = outRemainder.dataLength - 1;  
  1084.             ulong dividend = (ulong)outRemainder.data[pos];  
  1085.   
  1086.             //Console.WriteLine("divisor = " + divisor + " dividend = " + dividend);  
  1087.             //Console.WriteLine("divisor = " + bi2 + "\ndividend = " + bi1);  
  1088.   
  1089.             if (dividend >= divisor)  
  1090.             {  
  1091.                 ulong quotient = dividend / divisor;  
  1092.                 result[resultPos++] = (uint)quotient;  
  1093.   
  1094.                 outRemainder.data[pos] = (uint)(dividend % divisor);  
  1095.             }  
  1096.             pos--;  
  1097.   
  1098.             while (pos >= 0)  
  1099.             {  
  1100.                 //Console.WriteLine(pos);  
  1101.   
  1102.                 dividend = ((ulong)outRemainder.data[pos + 1] << 32) + (ulong)outRemainder.data[pos];  
  1103.                 ulong quotient = dividend / divisor;  
  1104.                 result[resultPos++] = (uint)quotient;  
  1105.   
  1106.                 outRemainder.data[pos + 1] = 0;  
  1107.                 outRemainder.data[pos--] = (uint)(dividend % divisor);  
  1108.                 //Console.WriteLine(">>>> " + bi1);  
  1109.             }  
  1110.   
  1111.             outQuotient.dataLength = resultPos;  
  1112.             int j = 0;  
  1113.             for (int i = outQuotient.dataLength - 1; i >= 0; i--, j++)  
  1114.                 outQuotient.data[j] = result[i];  
  1115.             for (; j < maxLength; j++)  
  1116.                 outQuotient.data[j] = 0;  
  1117.   
  1118.             while (outQuotient.dataLength > 1 && outQuotient.data[outQuotient.dataLength - 1] == 0)  
  1119.                 outQuotient.dataLength--;  
  1120.   
  1121.             if (outQuotient.dataLength == 0)  
  1122.                 outQuotient.dataLength = 1;  
  1123.   
  1124.             while (outRemainder.dataLength > 1 && outRemainder.data[outRemainder.dataLength - 1] == 0)  
  1125.                 outRemainder.dataLength--;  
  1126.         }  
  1127.   
  1128.   
  1129.         //***********************************************************************  
  1130.         // Overloading of division operator  
  1131.         //***********************************************************************  
  1132.   
  1133.         public static BigInteger operator /(BigInteger bi1, BigInteger bi2)  
  1134.         {  
  1135.             BigInteger quotient = new BigInteger();  
  1136.             BigInteger remainder = new BigInteger();  
  1137.   
  1138.             int lastPos = maxLength - 1;  
  1139.             bool divisorNeg = false, dividendNeg = false;  
  1140.   
  1141.             if ((bi1.data[lastPos] & 0x80000000) != 0)     // bi1 negative  
  1142.             {  
  1143.                 bi1 = -bi1;  
  1144.                 dividendNeg = true;  
  1145.             }  
  1146.             if ((bi2.data[lastPos] & 0x80000000) != 0)     // bi2 negative  
  1147.             {  
  1148.                 bi2 = -bi2;  
  1149.                 divisorNeg = true;  
  1150.             }  
  1151.   
  1152.             if (bi1 < bi2)  
  1153.             {  
  1154.                 return quotient;  
  1155.             }  
  1156.   
  1157.             else  
  1158.             {  
  1159.                 if (bi2.dataLength == 1)  
  1160.                     singleByteDivide(bi1, bi2, quotient, remainder);  
  1161.                 else  
  1162.                     multiByteDivide(bi1, bi2, quotient, remainder);  
  1163.   
  1164.                 if (dividendNeg != divisorNeg)  
  1165.                     return -quotient;  
  1166.   
  1167.                 return quotient;  
  1168.             }  
  1169.         }  
  1170.   
  1171.   
  1172.         //***********************************************************************  
  1173.         // Overloading of modulus operator  
  1174.         //***********************************************************************  
  1175.   
  1176.         public static BigInteger operator %(BigInteger bi1, BigInteger bi2)  
  1177.         {  
  1178.             BigInteger quotient = new BigInteger();  
  1179.             BigInteger remainder = new BigInteger(bi1);  
  1180.   
  1181.             int lastPos = maxLength - 1;  
  1182.             bool dividendNeg = false;  
  1183.   
  1184.             if ((bi1.data[lastPos] & 0x80000000) != 0)     // bi1 negative  
  1185.             {  
  1186.                 bi1 = -bi1;  
  1187.                 dividendNeg = true;  
  1188.             }  
  1189.             if ((bi2.data[lastPos] & 0x80000000) != 0)     // bi2 negative  
  1190.                 bi2 = -bi2;  
  1191.   
  1192.             if (bi1 < bi2)  
  1193.             {  
  1194.                 return remainder;  
  1195.             }  
  1196.   
  1197.             else  
  1198.             {  
  1199.                 if (bi2.dataLength == 1)  
  1200.                     singleByteDivide(bi1, bi2, quotient, remainder);  
  1201.                 else  
  1202.                     multiByteDivide(bi1, bi2, quotient, remainder);  
  1203.   
  1204.                 if (dividendNeg)  
  1205.                     return -remainder;  
  1206.   
  1207.                 return remainder;  
  1208.             }  
  1209.         }  
  1210.   
  1211.   
  1212.         //***********************************************************************  
  1213.         // Overloading of bitwise AND operator  
  1214.         //***********************************************************************  
  1215.   
  1216.         public static BigInteger operator &(BigInteger bi1, BigInteger bi2)  
  1217.         {  
  1218.             BigInteger result = new BigInteger();  
  1219.   
  1220.             int len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;  
  1221.   
  1222.             for (int i = 0; i < len; i++)  
  1223.             {  
  1224.                 uint sum = (uint)(bi1.data[i] & bi2.data[i]);  
  1225.                 result.data[i] = sum;  
  1226.             }  
  1227.   
  1228.             result.dataLength = maxLength;  
  1229.   
  1230.             while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  1231.                 result.dataLength--;  
  1232.   
  1233.             return result;  
  1234.         }  
  1235.   
  1236.   
  1237.         //***********************************************************************  
  1238.         // Overloading of bitwise OR operator  
  1239.         //***********************************************************************  
  1240.   
  1241.         public static BigInteger operator |(BigInteger bi1, BigInteger bi2)  
  1242.         {  
  1243.             BigInteger result = new BigInteger();  
  1244.   
  1245.             int len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;  
  1246.   
  1247.             for (int i = 0; i < len; i++)  
  1248.             {  
  1249.                 uint sum = (uint)(bi1.data[i] | bi2.data[i]);  
  1250.                 result.data[i] = sum;  
  1251.             }  
  1252.   
  1253.             result.dataLength = maxLength;  
  1254.   
  1255.             while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  1256.                 result.dataLength--;  
  1257.   
  1258.             return result;  
  1259.         }  
  1260.   
  1261.   
  1262.         //***********************************************************************  
  1263.         // Overloading of bitwise XOR operator  
  1264.         //***********************************************************************  
  1265.   
  1266.         public static BigInteger operator ^(BigInteger bi1, BigInteger bi2)  
  1267.         {  
  1268.             BigInteger result = new BigInteger();  
  1269.   
  1270.             int len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;  
  1271.   
  1272.             for (int i = 0; i < len; i++)  
  1273.             {  
  1274.                 uint sum = (uint)(bi1.data[i] ^ bi2.data[i]);  
  1275.                 result.data[i] = sum;  
  1276.             }  
  1277.   
  1278.             result.dataLength = maxLength;  
  1279.   
  1280.             while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)  
  1281.                 result.dataLength--;  
  1282.   
  1283.             return result;  
  1284.         }  
  1285.   
  1286.   
  1287.         //***********************************************************************  
  1288.         // Returns max(this, bi)  
  1289.         //***********************************************************************  
  1290.   
  1291.         public BigInteger max(BigInteger bi)  
  1292.         {  
  1293.             if (this > bi)  
  1294.                 return (new BigInteger(this));  
  1295.             else  
  1296.                 return (new BigInteger(bi));  
  1297.         }  
  1298.   
  1299.   
  1300.         //***********************************************************************  
  1301.         // Returns min(this, bi)  
  1302.         //***********************************************************************  
  1303.   
  1304.         public BigInteger min(BigInteger bi)  
  1305.         {  
  1306.             if (this < bi)  
  1307.                 return (new BigInteger(this));  
  1308.             else  
  1309.                 return (new BigInteger(bi));  
  1310.   
  1311.         }  
  1312.   
  1313.   
  1314.         //***********************************************************************  
  1315.         // Returns the absolute value  
  1316.         //***********************************************************************  
  1317.   
  1318.         public BigInteger abs()  
  1319.         {  
  1320.             if ((this.data[maxLength - 1] & 0x80000000) != 0)  
  1321.                 return (-this);  
  1322.             else  
  1323.                 return (new BigInteger(this));  
  1324.         }  
  1325.   
  1326.   
  1327.         //***********************************************************************  
  1328.         // Returns a string representing the BigInteger in base 10.  
  1329.         //***********************************************************************  
  1330.   
  1331.         public override string ToString()  
  1332.         {  
  1333.             return ToString(10);  
  1334.         }  
  1335.   
  1336.   
  1337.         //***********************************************************************  
  1338.         // Returns a string representing the BigInteger in sign-and-magnitude  
  1339.         // format in the specified radix.  
  1340.         //  
  1341.         // Example  
  1342.         // -------  
  1343.         // If the value of BigInteger is -255 in base 10, then  
  1344.         // ToString(16) returns "-FF"  
  1345.         //  
  1346.         //***********************************************************************  
  1347.   
  1348.         public string ToString(int radix)  
  1349.         {  
  1350.             if (radix < 2 || radix > 36)  
  1351.                 throw (new ArgumentException("Radix must be >= 2 and <= 36"));  
  1352.   
  1353.             string charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";  
  1354.             string result = "";  
  1355.   
  1356.             BigInteger a = this;  
  1357.   
  1358.             bool negative = false;  
  1359.             if ((a.data[maxLength - 1] & 0x80000000) != 0)  
  1360.             {  
  1361.                 negative = true;  
  1362.                 try  
  1363.                 {  
  1364.                     a = -a;  
  1365.                 }  
  1366.                 catch (Exception) { }  
  1367.             }  
  1368.   
  1369.             BigInteger quotient = new BigInteger();  
  1370.             BigInteger remainder = new BigInteger();  
  1371.             BigInteger biRadix = new BigInteger(radix);  
  1372.   
  1373.             if (a.dataLength == 1 && a.data[0] == 0)  
  1374.                 result = "0";  
  1375.             else  
  1376.             {  
  1377.                 while (a.dataLength > 1 || (a.dataLength == 1 && a.data[0] != 0))  
  1378.                 {  
  1379.                     singleByteDivide(a, biRadix, quotient, remainder);  
  1380.   
  1381.                     if (remainder.data[0] < 10)  
  1382.                         result = remainder.data[0] + result;  
  1383.                     else  
  1384.                         result = charSet[(int)remainder.data[0] - 10] + result;  
  1385.   
  1386.                     a = quotient;  
  1387.                 }  
  1388.                 if (negative)  
  1389.                     result = "-" + result;  
  1390.             }  
  1391.   
  1392.             return result;  
  1393.         }  
  1394.   
  1395.   
  1396.         //***********************************************************************  
  1397.         // Returns a hex string showing the contains of the BigInteger  
  1398.         //  
  1399.         // Examples  
  1400.         // -------  
  1401.         // 1) If the value of BigInteger is 255 in base 10, then  
  1402.         //    ToHexString() returns "FF"  
  1403.         //  
  1404.         // 2) If the value of BigInteger is -255 in base 10, then  
  1405.         //    ToHexString() returns ".....FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01",  
  1406.         //    which is the 2's complement representation of -255.  
  1407.         //  
  1408.         //***********************************************************************  
  1409.   
  1410.         public string ToHexString()  
  1411.         {  
  1412.             string result = data[dataLength - 1].ToString("X");  
  1413.   
  1414.             for (int i = dataLength - 2; i >= 0; i--)  
  1415.             {  
  1416.                 result += data[i].ToString("X8");  
  1417.             }  
  1418.   
  1419.             return result;  
  1420.         }  
  1421.   
  1422.   
  1423.   
  1424.         //***********************************************************************  
  1425.         // Modulo Exponentiation  
  1426.         //***********************************************************************  
  1427.   
  1428.         public BigInteger modPow(BigInteger exp, BigInteger n)  
  1429.         {  
  1430.             if ((exp.data[maxLength - 1] & 0x80000000) != 0)  
  1431.                 throw (new ArithmeticException("Positive exponents only."));  
  1432.   
  1433.             BigInteger resultNum = 1;  
  1434.             BigInteger tempNum;  
  1435.             bool thisNegative = false;  
  1436.   
  1437.             if ((this.data[maxLength - 1] & 0x80000000) != 0)   // negative this  
  1438.             {  
  1439.                 tempNum = -this % n;  
  1440.                 thisNegative = true;  
  1441.             }  
  1442.             else  
  1443.                 tempNum = this % n;  // ensures (tempNum * tempNum) < b^(2k)  
  1444.   
  1445.             if ((n.data[maxLength - 1] & 0x80000000) != 0)   // negative n  
  1446.                 n = -n;  
  1447.   
  1448.             // calculate constant = b^(2k) / m  
  1449.             BigInteger constant = new BigInteger();  
  1450.   
  1451.             int i = n.dataLength << 1;  
  1452.             constant.data[i] = 0x00000001;  
  1453.             constant.dataLength = i + 1;  
  1454.   
  1455.             constant = constant / n;  
  1456.             int totalBits = exp.bitCount();  
  1457.             int count = 0;  
  1458.   
  1459.             // perform squaring and multiply exponentiation  
  1460.             for (int pos = 0; pos < exp.dataLength; pos++)  
  1461.             {  
  1462.                 uint mask = 0x01;  
  1463.                 //Console.WriteLine("pos = " + pos);  
  1464.   
  1465.                 for (int index = 0; index < 32; index++)  
  1466.                 {  
  1467.                     if ((exp.data[pos] & mask) != 0)  
  1468.                         resultNum = BarrettReduction(resultNum * tempNum, n, constant);  
  1469.   
  1470.                     mask <<= 1;  
  1471.   
  1472.                     tempNum = BarrettReduction(tempNum * tempNum, n, constant);  
  1473.   
  1474.   
  1475.                     if (tempNum.dataLength == 1 && tempNum.data[0] == 1)  
  1476.                     {  
  1477.                         if (thisNegative && (exp.data[0] & 0x1) != 0)    //odd exp  
  1478.                             return -resultNum;  
  1479.                         return resultNum;  
  1480.                     }  
  1481.                     count++;  
  1482.                     if (count == totalBits)  
  1483.                         break;  
  1484.                 }  
  1485.             }  
  1486.   
  1487.             if (thisNegative && (exp.data[0] & 0x1) != 0)    //odd exp  
  1488.                 return -resultNum;  
  1489.   
  1490.             return resultNum;  
  1491.         }  
  1492.   
  1493.   
  1494.   
  1495.         //***********************************************************************  
  1496.         // Fast calculation of modular reduction using Barrett's reduction.  
  1497.         // Requires x < b^(2k), where b is the base.  In this case, base is  
  1498.         // 2^32 (uint).  
  1499.         //  
  1500.         // Reference [4]  
  1501.         //***********************************************************************  
  1502.   
  1503.         private BigInteger BarrettReduction(BigInteger x, BigInteger n, BigInteger constant)  
  1504.         {  
  1505.             int k = n.dataLength,  
  1506.                 kPlusOne = k + 1,  
  1507.                 kMinusOne = k - 1;  
  1508.   
  1509.             BigInteger q1 = new BigInteger();  
  1510.   
  1511.             // q1 = x / b^(k-1)  
  1512.             for (int i = kMinusOne, j = 0; i < x.dataLength; i++, j++)  
  1513.                 q1.data[j] = x.data[i];  
  1514.             q1.dataLength = x.dataLength - kMinusOne;  
  1515.             if (q1.dataLength <= 0)  
  1516.                 q1.dataLength = 1;  
  1517.   
  1518.   
  1519.             BigInteger q2 = q1 * constant;  
  1520.             BigInteger q3 = new BigInteger();  
  1521.   
  1522.             // q3 = q2 / b^(k+1)  
  1523.             for (int i = kPlusOne, j = 0; i < q2.dataLength; i++, j++)  
  1524.                 q3.data[j] = q2.data[i];  
  1525.             q3.dataLength = q2.dataLength - kPlusOne;  
  1526.             if (q3.dataLength <= 0)  
  1527.                 q3.dataLength = 1;  
  1528.   
  1529.   
  1530.             // r1 = x mod b^(k+1)  
  1531.             // i.e. keep the lowest (k+1) words  
  1532.             BigInteger r1 = new BigInteger();  
  1533.             int lengthToCopy = (x.dataLength > kPlusOne) ? kPlusOne : x.dataLength;  
  1534.             for (int i = 0; i < lengthToCopy; i++)  
  1535.                 r1.data[i] = x.data[i];  
  1536.             r1.dataLength = lengthToCopy;  
  1537.   
  1538.   
  1539.             // r2 = (q3 * n) mod b^(k+1)  
  1540.             // partial multiplication of q3 and n  
  1541.   
  1542.             BigInteger r2 = new BigInteger();  
  1543.             for (int i = 0; i < q3.dataLength; i++)  
  1544.             {  
  1545.                 if (q3.data[i] == 0) continue;  
  1546.   
  1547.                 ulong mcarry = 0;  
  1548.                 int t = i;  
  1549.                 for (int j = 0; j < n.dataLength && t < kPlusOne; j++, t++)  
  1550.                 {  
  1551.                     // t = i + j  
  1552.                     ulong val = ((ulong)q3.data[i] * (ulong)n.data[j]) +  
  1553.                                  (ulong)r2.data[t] + mcarry;  
  1554.   
  1555.                     r2.data[t] = (uint)(val & 0xFFFFFFFF);  
  1556.                     mcarry = (val >> 32);  
  1557.                 }  
  1558.   
  1559.                 if (t < kPlusOne)  
  1560.                     r2.data[t] = (uint)mcarry;  
  1561.             }  
  1562.             r2.dataLength = kPlusOne;  
  1563.             while (r2.dataLength > 1 && r2.data[r2.dataLength - 1] == 0)  
  1564.                 r2.dataLength--;  
  1565.   
  1566.             r1 -= r2;  
  1567.             if ((r1.data[maxLength - 1] & 0x80000000) != 0)        // negative  
  1568.             {  
  1569.                 BigInteger val = new BigInteger();  
  1570.                 val.data[kPlusOne] = 0x00000001;  
  1571.                 val.dataLength = kPlusOne + 1;  
  1572.                 r1 += val;  
  1573.             }  
  1574.   
  1575.             while (r1 >= n)  
  1576.                 r1 -= n;  
  1577.   
  1578.             return r1;  
  1579.         }  
  1580.   
  1581.   
  1582.         //***********************************************************************  
  1583.         // Returns gcd(this, bi)  
  1584.         //***********************************************************************  
  1585.   
  1586.         public BigInteger gcd(BigInteger bi)  
  1587.         {  
  1588.             BigInteger x;  
  1589.             BigInteger y;  
  1590.   
  1591.             if ((data[maxLength - 1] & 0x80000000) != 0)     // negative  
  1592.                 x = -this;  
  1593.             else  
  1594.                 x = this;  
  1595.   
  1596.             if ((bi.data[maxLength - 1] & 0x80000000) != 0)     // negative  
  1597.                 y = -bi;  
  1598.             else  
  1599.                 y = bi;  
  1600.   
  1601.             BigInteger g = y;  
  1602.   
  1603.             while (x.dataLength > 1 || (x.dataLength == 1 && x.data[0] != 0))  
  1604.             {  
  1605.                 g = x;  
  1606.                 x = y % x;  
  1607.                 y = g;  
  1608.             }  
  1609.   
  1610.             return g;  
  1611.         }  
  1612.   
  1613.   
  1614.         //***********************************************************************  
  1615.         // Populates "this" with the specified amount of random bits  
  1616.         //***********************************************************************  
  1617.   
  1618.         public void genRandomBits(int bits, Random rand)  
  1619.         {  
  1620.             int dwords = bits >> 5;  
  1621.             int remBits = bits & 0x1F;  
  1622.   
  1623.             if (remBits != 0)  
  1624.                 dwords++;  
  1625.   
  1626.             if (dwords > maxLength)  
  1627.                 throw (new ArithmeticException("Number of required bits > maxLength."));  
  1628.   
  1629.             for (int i = 0; i < dwords; i++)  
  1630.                 data[i] = (uint)(rand.NextDouble() * 0x100000000);  
  1631.   
  1632.             for (int i = dwords; i < maxLength; i++)  
  1633.                 data[i] = 0;  
  1634.   
  1635.             if (remBits != 0)  
  1636.             {  
  1637.                 uint mask = (uint)(0x01 << (remBits - 1));  
  1638.                 data[dwords - 1] |= mask;  
  1639.   
  1640.                 mask = (uint)(0xFFFFFFFF >> (32 - remBits));  
  1641.                 data[dwords - 1] &= mask;  
  1642.             }  
  1643.             else  
  1644.                 data[dwords - 1] |= 0x80000000;  
  1645.   
  1646.             dataLength = dwords;  
  1647.   
  1648.             if (dataLength == 0)  
  1649.                 dataLength = 1;  
  1650.         }  
  1651.   
  1652.   
  1653.         //***********************************************************************  
  1654.         // Returns the position of the most significant bit in the BigInteger.  
  1655.         //  
  1656.         // Eg.  The result is 0, if the value of BigInteger is 0...0000 0000  
  1657.         //      The result is 1, if the value of BigInteger is 0...0000 0001  
  1658.         //      The result is 2, if the value of BigInteger is 0...0000 0010  
  1659.         //      The result is 2, if the value of BigInteger is 0...0000 0011  
  1660.         //  
  1661.         //***********************************************************************  
  1662.   
  1663.         public int bitCount()  
  1664.         {  
  1665.             while (dataLength > 1 && data[dataLength - 1] == 0)  
  1666.                 dataLength--;  
  1667.   
  1668.             uint value = data[dataLength - 1];  
  1669.             uint mask = 0x80000000;  
  1670.             int bits = 32;  
  1671.   
  1672.             while (bits > 0 && (value & mask) == 0)  
  1673.             {  
  1674.                 bits--;  
  1675.                 mask >>= 1;  
  1676.             }  
  1677.             bits += ((dataLength - 1) << 5);  
  1678.   
  1679.             return bits;  
  1680.         }  
  1681.   
  1682.   
  1683.         //***********************************************************************  
  1684.         // Probabilistic prime test based on Fermat's little theorem  
  1685.         //  
  1686.         // for any a < p (p does not divide a) if  
  1687.         //      a^(p-1) mod p != 1 then p is not prime.  
  1688.         //  
  1689.         // Otherwise, p is probably prime (pseudoprime to the chosen base).  
  1690.         //  
  1691.         // Returns  
  1692.         // -------  
  1693.         // True if "this" is a pseudoprime to randomly chosen  
  1694.         // bases.  The number of chosen bases is given by the "confidence"  
  1695.         // parameter.  
  1696.         //  
  1697.         // False if "this" is definitely NOT prime.  
  1698.         //  
  1699.         // Note - this method is fast but fails for Carmichael numbers except  
  1700.         // when the randomly chosen base is a factor of the number.  
  1701.         //  
  1702.         //***********************************************************************  
  1703.   
  1704.         public bool FermatLittleTest(int confidence)  
  1705.         {  
  1706.             BigInteger thisVal;  
  1707.             if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative  
  1708.                 thisVal = -this;  
  1709.             else  
  1710.                 thisVal = this;  
  1711.   
  1712.             if (thisVal.dataLength == 1)  
  1713.             {  
  1714.                 // test small numbers  
  1715.                 if (thisVal.data[0] == 0 || thisVal.data[0] == 1)  
  1716.                     return false;  
  1717.                 else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)  
  1718.                     return true;  
  1719.             }  
  1720.   
  1721.             if ((thisVal.data[0] & 0x1) == 0)     // even numbers  
  1722.                 return false;  
  1723.   
  1724.             int bits = thisVal.bitCount();  
  1725.             BigInteger a = new BigInteger();  
  1726.             BigInteger p_sub1 = thisVal - (new BigInteger(1));  
  1727.             Random rand = new Random();  
  1728.   
  1729.             for (int round = 0; round < confidence; round++)  
  1730.             {  
  1731.                 bool done = false;  
  1732.   
  1733.                 while (!done)       // generate a < n  
  1734.                 {  
  1735.                     int testBits = 0;  
  1736.   
  1737.                     // make sure "a" has at least 2 bits  
  1738.                     while (testBits < 2)  
  1739.                         testBits = (int)(rand.NextDouble() * bits);  
  1740.   
  1741.                     a.genRandomBits(testBits, rand);  
  1742.   
  1743.                     int byteLen = a.dataLength;  
  1744.   
  1745.                     // make sure "a" is not 0  
  1746.                     if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1))  
  1747.                         done = true;  
  1748.                 }  
  1749.   
  1750.                 // check whether a factor exists (fix for version 1.03)  
  1751.                 BigInteger gcdTest = a.gcd(thisVal);  
  1752.                 if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1)  
  1753.                     return false;  
  1754.   
  1755.                 // calculate a^(p-1) mod p  
  1756.                 BigInteger expResult = a.modPow(p_sub1, thisVal);  
  1757.   
  1758.                 int resultLen = expResult.dataLength;  
  1759.   
  1760.                 // is NOT prime is a^(p-1) mod p != 1  
  1761.   
  1762.                 if (resultLen > 1 || (resultLen == 1 && expResult.data[0] != 1))  
  1763.                 {  
  1764.                     //Console.WriteLine("a = " + a.ToString());  
  1765.                     return false;  
  1766.                 }  
  1767.             }  
  1768.   
  1769.             return true;  
  1770.         }  
  1771.   
  1772.   
  1773.         //***********************************************************************  
  1774.         // Probabilistic prime test based on Rabin-Miller's  
  1775.         //  
  1776.         // for any p > 0 with p - 1 = 2^s * t  
  1777.         //  
  1778.         // p is probably prime (strong pseudoprime) if for any a < p,  
  1779.         // 1) a^t mod p = 1 or  
  1780.         // 2) a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1  
  1781.         //  
  1782.         // Otherwise, p is composite.  
  1783.         //  
  1784.         // Returns  
  1785.         // -------  
  1786.         // True if "this" is a strong pseudoprime to randomly chosen  
  1787.         // bases.  The number of chosen bases is given by the "confidence"  
  1788.         // parameter.  
  1789.         //  
  1790.         // False if "this" is definitely NOT prime.  
  1791.         //  
  1792.         //***********************************************************************  
  1793.   
  1794.         public bool RabinMillerTest(int confidence)  
  1795.         {  
  1796.             BigInteger thisVal;  
  1797.             if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative  
  1798.                 thisVal = -this;  
  1799.             else  
  1800.                 thisVal = this;  
  1801.   
  1802.             if (thisVal.dataLength == 1)  
  1803.             {  
  1804.                 // test small numbers  
  1805.                 if (thisVal.data[0] == 0 || thisVal.data[0] == 1)  
  1806.                     return false;  
  1807.                 else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)  
  1808.                     return true;  
  1809.             }  
  1810.   
  1811.             if ((thisVal.data[0] & 0x1) == 0)     // even numbers  
  1812.                 return false;  
  1813.   
  1814.   
  1815.             // calculate values of s and t  
  1816.             BigInteger p_sub1 = thisVal - (new BigInteger(1));  
  1817.             int s = 0;  
  1818.   
  1819.             for (int index = 0; index < p_sub1.dataLength; index++)  
  1820.             {  
  1821.                 uint mask = 0x01;  
  1822.   
  1823.                 for (int i = 0; i < 32; i++)  
  1824.                 {  
  1825.                     if ((p_sub1.data[index] & mask) != 0)  
  1826.                     {  
  1827.                         index = p_sub1.dataLength;      // to break the outer loop  
  1828.                         break;  
  1829.                     }  
  1830.                     mask <<= 1;  
  1831.                     s++;  
  1832.                 }  
  1833.             }  
  1834.   
  1835.             BigInteger t = p_sub1 >> s;  
  1836.   
  1837.             int bits = thisVal.bitCount();  
  1838.             BigInteger a = new BigInteger();  
  1839.             Random rand = new Random();  
  1840.   
  1841.             for (int round = 0; round < confidence; round++)  
  1842.             {  
  1843.                 bool done = false;  
  1844.   
  1845.                 while (!done)       // generate a < n  
  1846.                 {  
  1847.                     int testBits = 0;  
  1848.   
  1849.                     // make sure "a" has at least 2 bits  
  1850.                     while (testBits < 2)  
  1851.                         testBits = (int)(rand.NextDouble() * bits);  
  1852.   
  1853.                     a.genRandomBits(testBits, rand);  
  1854.   
  1855.                     int byteLen = a.dataLength;  
  1856.   
  1857.                     // make sure "a" is not 0  
  1858.                     if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1))  
  1859.                         done = true;  
  1860.                 }  
  1861.   
  1862.                 // check whether a factor exists (fix for version 1.03)  
  1863.                 BigInteger gcdTest = a.gcd(thisVal);  
  1864.                 if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1)  
  1865.                     return false;  
  1866.   
  1867.                 BigInteger b = a.modPow(t, thisVal);  
  1868.   
  1869.                 /*  
  1870.                 Console.WriteLine("a = " + a.ToString(10));  
  1871.                 Console.WriteLine("b = " + b.ToString(10));  
  1872.                 Console.WriteLine("t = " + t.ToString(10));  
  1873.                 Console.WriteLine("s = " + s);  
  1874.                 */  
  1875.   
  1876.                 bool result = false;  
  1877.   
  1878.                 if (b.dataLength == 1 && b.data[0] == 1)         // a^t mod p = 1  
  1879.                     result = true;  
  1880.   
  1881.                 for (int j = 0; result == false && j < s; j++)  
  1882.                 {  
  1883.                     if (b == p_sub1)         // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1  
  1884.                     {  
  1885.                         result = true;  
  1886.                         break;  
  1887.                     }  
  1888.   
  1889.                     b = (b * b) % thisVal;  
  1890.                 }  
  1891.   
  1892.                 if (result == false)  
  1893.                     return false;  
  1894.             }  
  1895.             return true;  
  1896.         }  
  1897.   
  1898.   
  1899.         //***********************************************************************  
  1900.         // Probabilistic prime test based on Solovay-Strassen (Euler Criterion)  
  1901.         //  
  1902.         // p is probably prime if for any a < p (a is not multiple of p),  
  1903.         // a^((p-1)/2) mod p = J(a, p)  
  1904.         //  
  1905.         // where J is the Jacobi symbol.  
  1906.         //  
  1907.         // Otherwise, p is composite.  
  1908.         //  
  1909.         // Returns  
  1910.         // -------  
  1911.         // True if "this" is a Euler pseudoprime to randomly chosen  
  1912.         // bases.  The number of chosen bases is given by the "confidence"  
  1913.         // parameter.  
  1914.         //  
  1915.         // False if "this" is definitely NOT prime.  
  1916.         //  
  1917.         //***********************************************************************  
  1918.   
  1919.         public bool SolovayStrassenTest(int confidence)  
  1920.         {  
  1921.             BigInteger thisVal;  
  1922.             if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative  
  1923.                 thisVal = -this;  
  1924.             else  
  1925.                 thisVal = this;  
  1926.   
  1927.             if (thisVal.dataLength == 1)  
  1928.             {  
  1929.                 // test small numbers  
  1930.                 if (thisVal.data[0] == 0 || thisVal.data[0] == 1)  
  1931.                     return false;  
  1932.                 else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)  
  1933.                     return true;  
  1934.             }  
  1935.   
  1936.             if ((thisVal.data[0] & 0x1) == 0)     // even numbers  
  1937.                 return false;  
  1938.   
  1939.   
  1940.             int bits = thisVal.bitCount();  
  1941.             BigInteger a = new BigInteger();  
  1942.             BigInteger p_sub1 = thisVal - 1;  
  1943.             BigInteger p_sub1_shift = p_sub1 >> 1;  
  1944.   
  1945.             Random rand = new Random();  
  1946.   
  1947.             for (int round = 0; round < confidence; round++)  
  1948.             {  
  1949.                 bool done = false;  
  1950.   
  1951.                 while (!done)       // generate a < n  
  1952.                 {  
  1953.                     int testBits = 0;  
  1954.   
  1955.                     // make sure "a" has at least 2 bits  
  1956.                     while (testBits < 2)  
  1957.                         testBits = (int)(rand.NextDouble() * bits);  
  1958.   
  1959.                     a.genRandomBits(testBits, rand);  
  1960.   
  1961.                     int byteLen = a.dataLength;  
  1962.   
  1963.                     // make sure "a" is not 0  
  1964.                     if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1))  
  1965.                         done = true;  
  1966.                 }  
  1967.   
  1968.                 // check whether a factor exists (fix for version 1.03)  
  1969.                 BigInteger gcdTest = a.gcd(thisVal);  
  1970.                 if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1)  
  1971.                     return false;  
  1972.   
  1973.                 // calculate a^((p-1)/2) mod p  
  1974.   
  1975.                 BigInteger expResult = a.modPow(p_sub1_shift, thisVal);  
  1976.                 if (expResult == p_sub1)  
  1977.                     expResult = -1;  
  1978.   
  1979.                 // calculate Jacobi symbol  
  1980.                 BigInteger jacob = Jacobi(a, thisVal);  
  1981.   
  1982.                 //Console.WriteLine("a = " + a.ToString(10) + " b = " + thisVal.ToString(10));  
  1983.                 //Console.WriteLine("expResult = " + expResult.ToString(10) + " Jacob = " + jacob.ToString(10));  
  1984.   
  1985.                 // if they are different then it is not prime  
  1986.                 if (expResult != jacob)  
  1987.                     return false;  
  1988.             }  
  1989.   
  1990.             return true;  
  1991.         }  
  1992.   
  1993.   
  1994.         //***********************************************************************  
  1995.         // Implementation of the Lucas Strong Pseudo Prime test.  
  1996.         //  
  1997.         // Let n be an odd number with gcd(n,D) = 1, and n - J(D, n) = 2^s * d  
  1998.         // with d odd and s >= 0.  
  1999.         //  
  2000.         // If Ud mod n = 0 or V2^r*d mod n = 0 for some 0 <= r < s, then n  
  2001.         // is a strong Lucas pseudoprime with parameters (P, Q).  We select  
  2002.         // P and Q based on Selfridge.  
  2003.         //  
  2004.         // Returns True if number is a strong Lucus pseudo prime.  
  2005.         // Otherwise, returns False indicating that number is composite.  
  2006.         //***********************************************************************  
  2007.   
  2008.         public bool LucasStrongTest()  
  2009.         {  
  2010.             BigInteger thisVal;  
  2011.             if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative  
  2012.                 thisVal = -this;  
  2013.             else  
  2014.                 thisVal = this;  
  2015.   
  2016.             if (thisVal.dataLength == 1)  
  2017.             {  
  2018.                 // test small numbers  
  2019.                 if (thisVal.data[0] == 0 || thisVal.data[0] == 1)  
  2020.                     return false;  
  2021.                 else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)  
  2022.                     return true;  
  2023.             }  
  2024.   
  2025.             if ((thisVal.data[0] & 0x1) == 0)     // even numbers  
  2026.                 return false;  
  2027.   
  2028.             return LucasStrongTestHelper(thisVal);  
  2029.         }  
  2030.   
  2031.   
  2032.         private bool LucasStrongTestHelper(BigInteger thisVal)  
  2033.         {  
  2034.             // Do the test (selects D based on Selfridge)  
  2035.             // Let D be the first element of the sequence  
  2036.             // 5, -7, 9, -11, 13, ... for which J(D,n) = -1  
  2037.             // Let P = 1, Q = (1-D) / 4  
  2038.   
  2039.             long D = 5, sign = -1, dCount = 0;  
  2040.             bool done = false;  
  2041.   
  2042.             while (!done)  
  2043.             {  
  2044.                 int Jresult = BigInteger.Jacobi(D, thisVal);  
  2045.   
  2046.                 if (Jresult == -1)  
  2047.                     done = true;    // J(D, this) = 1  
  2048.                 else  
  2049.                 {  
  2050.                     if (Jresult == 0 && Math.Abs(D) < thisVal)       // divisor found  
  2051.                         return false;  
  2052.   
  2053.                     if (dCount == 20)  
  2054.                     {  
  2055.                         // check for square  
  2056.                         BigInteger root = thisVal.sqrt();  
  2057.                         if (root * root == thisVal)  
  2058.                             return false;  
  2059.                     }  
  2060.   
  2061.                     //Console.WriteLine(D);  
  2062.                     D = (Math.Abs(D) + 2) * sign;  
  2063.                     sign = -sign;  
  2064.                 }  
  2065.                 dCount++;  
  2066.             }  
  2067.   
  2068.             long Q = (1 - D) >> 2;  
  2069.   
  2070.             /*  
  2071.             Console.WriteLine("D = " + D);  
  2072.             Console.WriteLine("Q = " + Q);  
  2073.             Console.WriteLine("(n,D) = " + thisVal.gcd(D));  
  2074.             Console.WriteLine("(n,Q) = " + thisVal.gcd(Q));  
  2075.             Console.WriteLine("J(D|n) = " + BigInteger.Jacobi(D, thisVal));  
  2076.             */  
  2077.   
  2078.             BigInteger p_add1 = thisVal + 1;  
  2079.             int s = 0;  
  2080.   
  2081.             for (int index = 0; index < p_add1.dataLength; index++)  
  2082.             {  
  2083.                 uint mask = 0x01;  
  2084.   
  2085.                 for (int i = 0; i < 32; i++)  
  2086.                 {  
  2087.                     if ((p_add1.data[index] & mask) != 0)  
  2088.                     {  
  2089.                         index = p_add1.dataLength;      // to break the outer loop  
  2090.                         break;  
  2091.                     }  
  2092.                     mask <<= 1;  
  2093.                     s++;  
  2094.                 }  
  2095.             }  
  2096.   
  2097.             BigInteger t = p_add1 >> s;  
  2098.   
  2099.             // calculate constant = b^(2k) / m  
  2100.             // for Barrett Reduction  
  2101.             BigInteger constant = new BigInteger();  
  2102.   
  2103.             int nLen = thisVal.dataLength << 1;  
  2104.             constant.data[nLen] = 0x00000001;  
  2105.             constant.dataLength = nLen + 1;  
  2106.   
  2107.             constant = constant / thisVal;  
  2108.   
  2109.             BigInteger[] lucas = LucasSequenceHelper(1, Q, t, thisVal, constant, 0);  
  2110.             bool isPrime = false;  
  2111.   
  2112.             if ((lucas[0].dataLength == 1 && lucas[0].data[0] == 0) ||  
  2113.                (lucas[1].dataLength == 1 && lucas[1].data[0] == 0))  
  2114.             {  
  2115.                 // u(t) = 0 or V(t) = 0  
  2116.                 isPrime = true;  
  2117.             }  
  2118.   
  2119.             for (int i = 1; i < s; i++)  
  2120.             {  
  2121.                 if (!isPrime)  
  2122.                 {  
  2123.                     // doubling of index  
  2124.                     lucas[1] = thisVal.BarrettReduction(lucas[1] * lucas[1], thisVal, constant);  
  2125.                     lucas[1] = (lucas[1] - (lucas[2] << 1)) % thisVal;  
  2126.   
  2127.                     //lucas[1] = ((lucas[1] * lucas[1]) - (lucas[2] << 1)) % thisVal;  
  2128.   
  2129.                     if ((lucas[1].dataLength == 1 && lucas[1].data[0] == 0))  
  2130.                         isPrime = true;  
  2131.                 }  
  2132.   
  2133.                 lucas[2] = thisVal.BarrettReduction(lucas[2] * lucas[2], thisVal, constant);     //Q^k  
  2134.             }  
  2135.   
  2136.   
  2137.             if (isPrime)     // additional checks for composite numbers  
  2138.             {  
  2139.                 // If n is prime and gcd(n, Q) == 1, then  
  2140.                 // Q^((n+1)/2) = Q * Q^((n-1)/2) is congruent to (Q * J(Q, n)) mod n  
  2141.   
  2142.                 BigInteger g = thisVal.gcd(Q);  
  2143.                 if (g.dataLength == 1 && g.data[0] == 1)         // gcd(this, Q) == 1  
  2144.                 {  
  2145.                     if ((lucas[2].data[maxLength - 1] & 0x80000000) != 0)  
  2146.                         lucas[2] += thisVal;  
  2147.   
  2148.                     BigInteger temp = (Q * BigInteger.Jacobi(Q, thisVal)) % thisVal;  
  2149.                     if ((temp.data[maxLength - 1] & 0x80000000) != 0)  
  2150.                         temp += thisVal;  
  2151.   
  2152.                     if (lucas[2] != temp)  
  2153.                         isPrime = false;  
  2154.                 }  
  2155.             }  
  2156.   
  2157.             return isPrime;  
  2158.         }  
  2159.   
  2160.   
  2161.         //***********************************************************************  
  2162.         // Determines whether a number is probably prime, using the Rabin-Miller's  
  2163.         // test.  Before applying the test, the number is tested for divisibility  
  2164.         // by primes < 2000  
  2165.         //  
  2166.         // Returns true if number is probably prime.  
  2167.         //***********************************************************************  
  2168.   
  2169.         public bool isProbablePrime(int confidence)  
  2170.         {  
  2171.             BigInteger thisVal;  
  2172.             if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative  
  2173.                 thisVal = -this;  
  2174.             else  
  2175.                 thisVal = this;  
  2176.   
  2177.   
  2178.             // test for divisibility by primes < 2000  
  2179.             for (int p = 0; p < primesBelow2000.Length; p++)  
  2180.             {  
  2181.                 BigInteger divisor = primesBelow2000[p];  
  2182.   
  2183.                 if (divisor >= thisVal)  
  2184.                     break;  
  2185.   
  2186.                 BigInteger resultNum = thisVal % divisor;  
  2187.                 if (resultNum.IntValue() == 0)  
  2188.                 {  
  2189.                     /*  
  2190.     Console.WriteLine("Not prime!  Divisible by {0}\n",  
  2191.                                       primesBelow2000[p]);  
  2192.                     */  
  2193.                     return false;  
  2194.                 }  
  2195.             }  
  2196.   
  2197.             if (thisVal.RabinMillerTest(confidence))  
  2198.                 return true;  
  2199.             else  
  2200.             {  
  2201.                 //Console.WriteLine("Not prime!  Failed primality test\n");  
  2202.                 return false;  
  2203.             }  
  2204.         }  
  2205.   
  2206.   
  2207.         //***********************************************************************  
  2208.         // Determines whether this BigInteger is probably prime using a  
  2209.         // combination of base 2 strong pseudoprime test and Lucas strong  
  2210.         // pseudoprime test.  
  2211.         //  
  2212.         // The sequence of the primality test is as follows,  
  2213.         //  
  2214.         // 1) Trial divisions are carried out using prime numbers below 2000.  
  2215.         //    if any of the primes divides this BigInteger, then it is not prime.  
  2216.         //  
  2217.         // 2) Perform base 2 strong pseudoprime test.  If this BigInteger is a  
  2218.         //    base 2 strong pseudoprime, proceed on to the next step.  
  2219.         //  
  2220.         // 3) Perform strong Lucas pseudoprime test.  
  2221.         //  
  2222.         // Returns True if this BigInteger is both a base 2 strong pseudoprime  
  2223.         // and a strong Lucas pseudoprime.  
  2224.         //  
  2225.         // For a detailed discussion of this primality test, see [6].  
  2226.         //  
  2227.         //***********************************************************************  
  2228.   
  2229.         public bool isProbablePrime()  
  2230.         {  
  2231.             BigInteger thisVal;  
  2232.             if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative  
  2233.                 thisVal = -this;  
  2234.             else  
  2235.                 thisVal = this;  
  2236.   
  2237.             if (thisVal.dataLength == 1)  
  2238.             {  
  2239.                 // test small numbers  
  2240.                 if (thisVal.data[0] == 0 || thisVal.data[0] == 1)  
  2241.                     return false;  
  2242.                 else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)  
  2243.                     return true;  
  2244.             }  
  2245.   
  2246.             if ((thisVal.data[0] & 0x1) == 0)     // even numbers  
  2247.                 return false;  
  2248.   
  2249.   
  2250.             // test for divisibility by primes < 2000  
  2251.             for (int p = 0; p < primesBelow2000.Length; p++)  
  2252.             {  
  2253.                 BigInteger divisor = primesBelow2000[p];  
  2254.   
  2255.                 if (divisor >= thisVal)  
  2256.                     break;  
  2257.   
  2258.                 BigInteger resultNum = thisVal % divisor;  
  2259.                 if (resultNum.IntValue() == 0)  
  2260.                 {  
  2261.                     //Console.WriteLine("Not prime!  Divisible by {0}\n",  
  2262.                     //                  primesBelow2000[p]);  
  2263.   
  2264.                     return false;  
  2265.                 }  
  2266.             }  
  2267.   
  2268.             // Perform BASE 2 Rabin-Miller Test  
  2269.   
  2270.             // calculate values of s and t  
  2271.             BigInteger p_sub1 = thisVal - (new BigInteger(1));  
  2272.             int s = 0;  
  2273.   
  2274.             for (int index = 0; index < p_sub1.dataLength; index++)  
  2275.             {  
  2276.                 uint mask = 0x01;  
  2277.   
  2278.                 for (int i = 0; i < 32; i++)  
  2279.                 {  
  2280.                     if ((p_sub1.data[index] & mask) != 0)  
  2281.                     {  
  2282.                         index = p_sub1.dataLength;      // to break the outer loop  
  2283.                         break;  
  2284.                     }  
  2285.                     mask <<= 1;  
  2286.                     s++;  
  2287.                 }  
  2288.             }  
  2289.   
  2290.             BigInteger t = p_sub1 >> s;  
  2291.   
  2292.             int bits = thisVal.bitCount();  
  2293.             BigInteger a = 2;  
  2294.   
  2295.             // b = a^t mod p  
  2296.             BigInteger b = a.modPow(t, thisVal);  
  2297.             bool result = false;  
  2298.   
  2299.             if (b.dataLength == 1 && b.data[0] == 1)         // a^t mod p = 1  
  2300.                 result = true;  
  2301.   
  2302.             for (int j = 0; result == false && j < s; j++)  
  2303.             {  
  2304.                 if (b == p_sub1)         // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1  
  2305.                 {  
  2306.                     result = true;  
  2307.                     break;  
  2308.                 }  
  2309.   
  2310.                 b = (b * b) % thisVal;  
  2311.             }  
  2312.   
  2313.             // if number is strong pseudoprime to base 2, then do a strong lucas test  
  2314.             if (result)  
  2315.                 result = LucasStrongTestHelper(thisVal);  
  2316.   
  2317.             return result;  
  2318.         }  
  2319.   
  2320.   
  2321.   
  2322.         //***********************************************************************  
  2323.         // Returns the lowest 4 bytes of the BigInteger as an int.  
  2324.         //***********************************************************************  
  2325.   
  2326.         public int IntValue()  
  2327.         {  
  2328.             return (int)data[0];  
  2329.         }  
  2330.   
  2331.   
  2332.         //***********************************************************************  
  2333.         // Returns the lowest 8 bytes of the BigInteger as a long.  
  2334.         //***********************************************************************  
  2335.   
  2336.         public long LongValue()  
  2337.         {  
  2338.             long val = 0;  
  2339.   
  2340.             val = (long)data[0];  
  2341.             try  
  2342.             {       // exception if maxLength = 1  
  2343.                 val |= (long)data[1] << 32;  
  2344.             }  
  2345.             catch (Exception)  
  2346.             {  
  2347.                 if ((data[0] & 0x80000000) != 0) // negative  
  2348.                     val = (int)data[0];  
  2349.             }  
  2350.   
  2351.             return val;  
  2352.         }  
  2353.   
  2354.   
  2355.         //***********************************************************************  
  2356.         // Computes the Jacobi Symbol for a and b.  
  2357.         // Algorithm adapted from [3] and [4] with some optimizations  
  2358.         //***********************************************************************  
  2359.   
  2360.         public static int Jacobi(BigInteger a, BigInteger b)  
  2361.         {  
  2362.             // Jacobi defined only for odd integers  
  2363.             if ((b.data[0] & 0x1) == 0)  
  2364.                 throw (new ArgumentException("Jacobi defined only for odd integers."));  
  2365.   
  2366.             if (a >= b) a %= b;  
  2367.             if (a.dataLength == 1 && a.data[0] == 0) return 0;  // a == 0  
  2368.             if (a.dataLength == 1 && a.data[0] == 1) return 1;  // a == 1  
  2369.   
  2370.             if (a < 0)  
  2371.             {  
  2372.                 if ((((b - 1).data[0]) & 0x2) == 0)       //if( (((b-1) >> 1).data[0] & 0x1) == 0)  
  2373.                     return Jacobi(-a, b);  
  2374.                 else  
  2375.                     return -Jacobi(-a, b);  
  2376.             }  
  2377.   
  2378.             int e = 0;  
  2379.             for (int index = 0; index < a.dataLength; index++)  
  2380.             {  
  2381.                 uint mask = 0x01;  
  2382.   
  2383.                 for (int i = 0; i < 32; i++)  
  2384.                 {  
  2385.                     if ((a.data[index] & mask) != 0)  
  2386.                     {  
  2387.                         index = a.dataLength;      // to break the outer loop  
  2388.                         break;  
  2389.                     }  
  2390.                     mask <<= 1;  
  2391.                     e++;  
  2392.                 }  
  2393.             }  
  2394.   
  2395.             BigInteger a1 = a >> e;  
  2396.   
  2397.             int s = 1;  
  2398.             if ((e & 0x1) != 0 && ((b.data[0] & 0x7) == 3 || (b.data[0] & 0x7) == 5))  
  2399.                 s = -1;  
  2400.   
  2401.             if ((b.data[0] & 0x3) == 3 && (a1.data[0] & 0x3) == 3)  
  2402.                 s = -s;  
  2403.   
  2404.             if (a1.dataLength == 1 && a1.data[0] == 1)  
  2405.                 return s;  
  2406.             else  
  2407.                 return (s * Jacobi(b % a1, a1));  
  2408.         }  
  2409.   
  2410.   
  2411.   
  2412.         //***********************************************************************  
  2413.         // Generates a positive BigInteger that is probably prime.  
  2414.         //***********************************************************************  
  2415.   
  2416.         public static BigInteger genPseudoPrime(int bits, int confidence, Random rand)  
  2417.         {  
  2418.             BigInteger result = new BigInteger();  
  2419.             bool done = false;  
  2420.   
  2421.             while (!done)  
  2422.             {  
  2423.                 result.genRandomBits(bits, rand);  
  2424.                 result.data[0] |= 0x01;     // make it odd  
  2425.   
  2426.                 // prime test  
  2427.                 done = result.isProbablePrime(confidence);  
  2428.             }  
  2429.             return result;  
  2430.         }  
  2431.   
  2432.   
  2433.         //***********************************************************************  
  2434.         // Generates a random number with the specified number of bits such  
  2435.         // that gcd(number, this) = 1  
  2436.         //***********************************************************************  
  2437.   
  2438.         public BigInteger genCoPrime(int bits, Random rand)  
  2439.         {  
  2440.             bool done = false;  
  2441.             BigInteger result = new BigInteger();  
  2442.   
  2443.             while (!done)  
  2444.             {  
  2445.                 result.genRandomBits(bits, rand);  
  2446.                 //Console.WriteLine(result.ToString(16));  
  2447.   
  2448.                 // gcd test  
  2449.                 BigInteger g = result.gcd(this);  
  2450.                 if (g.dataLength == 1 && g.data[0] == 1)  
  2451.                     done = true;  
  2452.             }  
  2453.   
  2454.             return result;  
  2455.         }  
  2456.   
  2457.   
  2458.         //***********************************************************************  
  2459.         // Returns the modulo inverse of this.  Throws ArithmeticException if  
  2460.         // the inverse does not exist.  (i.e. gcd(this, modulus) != 1)  
  2461.         //***********************************************************************  
  2462.   
  2463.         public BigInteger modInverse(BigInteger modulus)  
  2464.         {  
  2465.             BigInteger[] p = { 0, 1 };  
  2466.             BigInteger[] q = new BigInteger[2];    // quotients  
  2467.             BigInteger[] r = { 0, 0 };             // remainders  
  2468.   
  2469.             int step = 0;  
  2470.   
  2471.             BigInteger a = modulus;  
  2472.             BigInteger b = this;  
  2473.   
  2474.             while (b.dataLength > 1 || (b.dataLength == 1 && b.data[0] != 0))  
  2475.             {  
  2476.                 BigInteger quotient = new BigInteger();  
  2477.                 BigInteger remainder = new BigInteger();  
  2478.   
  2479.                 if (step > 1)  
  2480.                 {  
  2481.                     BigInteger pval = (p[0] - (p[1] * q[0])) % modulus;  
  2482.                     p[0] = p[1];  
  2483.                     p[1] = pval;  
  2484.                 }  
  2485.   
  2486.                 if (b.dataLength == 1)  
  2487.                     singleByteDivide(a, b, quotient, remainder);  
  2488.                 else  
  2489.                     multiByteDivide(a, b, quotient, remainder);  
  2490.   
  2491.                 /*  
  2492.                 Console.WriteLine(quotient.dataLength);  
  2493.                 Console.WriteLine("{0} = {1}({2}) + {3}  p = {4}", a.ToString(10),  
  2494.                                   b.ToString(10), quotient.ToString(10), remainder.ToString(10),  
  2495.                                   p[1].ToString(10));  
  2496.                 */  
  2497.   
  2498.                 q[0] = q[1];  
  2499.                 r[0] = r[1];  
  2500.                 q[1] = quotient; r[1] = remainder;  
  2501.   
  2502.                 a = b;  
  2503.                 b = remainder;  
  2504.   
  2505.                 step++;  
  2506.             }  
  2507.   
  2508.             if (r[0].dataLength > 1 || (r[0].dataLength == 1 && r[0].data[0] != 1))  
  2509.                 throw (new ArithmeticException("No inverse!"));  
  2510.   
  2511.             BigInteger result = ((p[0] - (p[1] * q[0])) % modulus);  
  2512.   
  2513.             if ((result.data[maxLength - 1] & 0x80000000) != 0)  
  2514.                 result += modulus;  // get the least positive modulus  
  2515.   
  2516.             return result;  
  2517.         }  
  2518.   
  2519.   
  2520.         //***********************************************************************  
  2521.         // Returns the value of the BigInteger as a byte array.  The lowest  
  2522.         // index contains the MSB.  
  2523.         //***********************************************************************  
  2524.   
  2525.         public byte[] getBytes()  
  2526.         {  
  2527.             int numBits = bitCount();  
  2528.   
  2529.             int numBytes = numBits >> 3;  
  2530.             if ((numBits & 0x7) != 0)  
  2531.                 numBytes++;  
  2532.   
  2533.             byte[] result = new byte[numBytes];  
  2534.   
  2535.             //Console.WriteLine(result.Length);  
  2536.   
  2537.             int pos = 0;  
  2538.             uint tempVal, val = data[dataLength - 1];  
  2539.   
  2540.             if ((tempVal = (val >> 24 & 0xFF)) != 0)  
  2541.                 result[pos++] = (byte)tempVal;  
  2542.             if ((tempVal = (val >> 16 & 0xFF)) != 0)  
  2543.                 result[pos++] = (byte)tempVal;  
  2544.             if ((tempVal = (val >> 8 & 0xFF)) != 0)  
  2545.                 result[pos++] = (byte)tempVal;  
  2546.             if ((tempVal = (val & 0xFF)) != 0)  
  2547.                 result[pos++] = (byte)tempVal;  
  2548.   
  2549.             for (int i = dataLength - 2; i >= 0; i--, pos += 4)  
  2550.             {  
  2551.                 val = data[i];  
  2552.                 result[pos + 3] = (byte)(val & 0xFF);  
  2553.                 val >>= 8;  
  2554.                 result[pos + 2] = (byte)(val & 0xFF);  
  2555.                 val >>= 8;  
  2556.                 result[pos + 1] = (byte)(val & 0xFF);  
  2557.                 val >>= 8;  
  2558.                 result[pos] = (byte)(val & 0xFF);  
  2559.             }  
  2560.   
  2561.             return result;  
  2562.         }  
  2563.   
  2564.   
  2565.         //***********************************************************************  
  2566.         // Sets the value of the specified bit to 1  
  2567.         // The Least Significant Bit position is 0.  
  2568.         //***********************************************************************  
  2569.   
  2570.         public void setBit(uint bitNum)  
  2571.         {  
  2572.             uint bytePos = bitNum >> 5;             // divide by 32  
  2573.             byte bitPos = (byte)(bitNum & 0x1F);    // get the lowest 5 bits  
  2574.   
  2575.             uint mask = (uint)1 << bitPos;  
  2576.             this.data[bytePos] |= mask;  
  2577.   
  2578.             if (bytePos >= this.dataLength)  
  2579.                 this.dataLength = (int)bytePos + 1;  
  2580.         }  
  2581.   
  2582.   
  2583.         //***********************************************************************  
  2584.         // Sets the value of the specified bit to 0  
  2585.         // The Least Significant Bit position is 0.  
  2586.         //***********************************************************************  
  2587.   
  2588.         public void unsetBit(uint bitNum)  
  2589.         {  
  2590.             uint bytePos = bitNum >> 5;  
  2591.   
  2592.             if (bytePos < this.dataLength)  
  2593.             {  
  2594.                 byte bitPos = (byte)(bitNum & 0x1F);  
  2595.   
  2596.                 uint mask = (uint)1 << bitPos;  
  2597.                 uint mask2 = 0xFFFFFFFF ^ mask;  
  2598.   
  2599.                 this.data[bytePos] &= mask2;  
  2600.   
  2601.                 if (this.dataLength > 1 && this.data[this.dataLength - 1] == 0)  
  2602.                     this.dataLength--;  
  2603.             }  
  2604.         }  
  2605.   
  2606.   
  2607.         //***********************************************************************  
  2608.         // Returns a value that is equivalent to the integer square root  
  2609.         // of the BigInteger.  
  2610.         //  
  2611.         // The integer square root of "this" is defined as the largest integer n  
  2612.         // such that (n * n) <= this  
  2613.         //  
  2614.         //***********************************************************************  
  2615.   
  2616.         public BigInteger sqrt()  
  2617.         {  
  2618.             uint numBits = (uint)this.bitCount();  
  2619.   
  2620.             if ((numBits & 0x1) != 0)        // odd number of bits  
  2621.                 numBits = (numBits >> 1) + 1;  
  2622.             else  
  2623.                 numBits = (numBits >> 1);  
  2624.   
  2625.             uint bytePos = numBits >> 5;  
  2626.             byte bitPos = (byte)(numBits & 0x1F);  
  2627.   
  2628.             uint mask;  
  2629.   
  2630.             BigInteger result = new BigInteger();  
  2631.             if (bitPos == 0)  
  2632.                 mask = 0x80000000;  
  2633.             else  
  2634.             {  
  2635.                 mask = (uint)1 << bitPos;  
  2636.                 bytePos++;  
  2637.             }  
  2638.             result.dataLength = (int)bytePos;  
  2639.   
  2640.             for (int i = (int)bytePos - 1; i >= 0; i--)  
  2641.             {  
  2642.                 while (mask != 0)  
  2643.                 {  
  2644.                     // guess  
  2645.                     result.data[i] ^= mask;  
  2646.   
  2647.                     // undo the guess if its square is larger than this  
  2648.                     if ((result * result) > this)  
  2649.                         result.data[i] ^= mask;  
  2650.   
  2651.                     mask >>= 1;  
  2652.                 }  
  2653.                 mask = 0x80000000;  
  2654.             }  
  2655.             return result;  
  2656.         }  
  2657.   
  2658.   
  2659.         //***********************************************************************  
  2660.         // Returns the k_th number in the Lucas Sequence reduced modulo n.  
  2661.         //  
  2662.         // Uses index doubling to speed up the process.  For example, to calculate V(k),  
  2663.         // we maintain two numbers in the sequence V(n) and V(n+1).  
  2664.         //  
  2665.         // To obtain V(2n), we use the identity  
  2666.         //      V(2n) = (V(n) * V(n)) - (2 * Q^n)  
  2667.         // To obtain V(2n+1), we first write it as  
  2668.         //      V(2n+1) = V((n+1) + n)  
  2669.         // and use the identity  
  2670.         //      V(m+n) = V(m) * V(n) - Q * V(m-n)  
  2671.         // Hence,  
  2672.         //      V((n+1) + n) = V(n+1) * V(n) - Q^n * V((n+1) - n)  
  2673.         //                   = V(n+1) * V(n) - Q^n * V(1)  
  2674.         //                   = V(n+1) * V(n) - Q^n * P  
  2675.         //  
  2676.         // We use k in its binary expansion and perform index doubling for each  
  2677.         // bit position.  For each bit position that is set, we perform an  
  2678.         // index doubling followed by an index addition.  This means that for V(n),  
  2679.         // we need to update it to V(2n+1).  For V(n+1), we need to update it to  
  2680.         // V((2n+1)+1) = V(2*(n+1))  
  2681.         //  
  2682.         // This function returns  
  2683.         // [0] = U(k)  
  2684.         // [1] = V(k)  
  2685.         // [2] = Q^n  
  2686.         //  
  2687.         // Where U(0) = 0 % n, U(1) = 1 % n  
  2688.         //       V(0) = 2 % n, V(1) = P % n  
  2689.         //***********************************************************************  
  2690.   
  2691.         public static BigInteger[] LucasSequence(BigInteger P, BigInteger Q,  
  2692.                                                  BigInteger k, BigInteger n)  
  2693.         {  
  2694.             if (k.dataLength == 1 && k.data[0] == 0)  
  2695.             {  
  2696.                 BigInteger[] result = new BigInteger[3];  
  2697.   
  2698.                 result[0] = 0; result[1] = 2 % n; result[2] = 1 % n;  
  2699.                 return result;  
  2700.             }  
  2701.   
  2702.             // calculate constant = b^(2k) / m  
  2703.             // for Barrett Reduction  
  2704.             BigInteger constant = new BigInteger();  
  2705.   
  2706.             int nLen = n.dataLength << 1;  
  2707.             constant.data[nLen] = 0x00000001;  
  2708.             constant.dataLength = nLen + 1;  
  2709.   
  2710.             constant = constant / n;  
  2711.   
  2712.             // calculate values of s and t  
  2713.             int s = 0;  
  2714.   
  2715.             for (int index = 0; index < k.dataLength; index++)  
  2716.             {  
  2717.                 uint mask = 0x01;  
  2718.   
  2719.                 for (int i = 0; i < 32; i++)  
  2720.                 {  
  2721.                     if ((k.data[index] & mask) != 0)  
  2722.                     {  
  2723.                         index = k.dataLength;      // to break the outer loop  
  2724.                         break;  
  2725.                     }  
  2726.                     mask <<= 1;  
  2727.                     s++;  
  2728.                 }  
  2729.             }  
  2730.   
  2731.             BigInteger t = k >> s;  
  2732.   
  2733.             //Console.WriteLine("s = " + s + " t = " + t);  
  2734.             return LucasSequenceHelper(P, Q, t, n, constant, s);  
  2735.         }  
  2736.   
  2737.   
  2738.         //***********************************************************************  
  2739.         // Performs the calculation of the kth term in the Lucas Sequence.  
  2740.         // For details of the algorithm, see reference [9].  
  2741.         //  
  2742.         // k must be odd.  i.e LSB == 1  
  2743.         //***********************************************************************  
  2744.   
  2745.         private static BigInteger[] LucasSequenceHelper(BigInteger P, BigInteger Q,  
  2746.                                                         BigInteger k, BigInteger n,  
  2747.                                                         BigInteger constant, int s)  
  2748.         {  
  2749.             BigInteger[] result = new BigInteger[3];  
  2750.   
  2751.             if ((k.data[0] & 0x00000001) == 0)  
  2752.                 throw (new ArgumentException("Argument k must be odd."));  
  2753.   
  2754.             int numbits = k.bitCount();  
  2755.             uint mask = (uint)0x1 << ((numbits & 0x1F) - 1);  
  2756.   
  2757.             // v = v0, v1 = v1, u1 = u1, Q_k = Q^0  
  2758.   
  2759.             BigInteger v = 2 % n, Q_k = 1 % n,  
  2760.                        v1 = P % n, u1 = Q_k;  
  2761.             bool flag = true;  
  2762.   
  2763.             for (int i = k.dataLength - 1; i >= 0; i--)     // iterate on the binary expansion of k  
  2764.             {  
  2765.                 //Console.WriteLine("round");  
  2766.                 while (mask != 0)  
  2767.                 {  
  2768.                     if (i == 0 && mask == 0x00000001)        // last bit  
  2769.                         break;  
  2770.   
  2771.                     if ((k.data[i] & mask) != 0)             // bit is set  
  2772.                     {  
  2773.                         // index doubling with addition  
  2774.   
  2775.                         u1 = (u1 * v1) % n;  
  2776.   
  2777.                         v = ((v * v1) - (P * Q_k)) % n;  
  2778.                         v1 = n.BarrettReduction(v1 * v1, n, constant);  
  2779.                         v1 = (v1 - ((Q_k * Q) << 1)) % n;  
  2780.   
  2781.                         if (flag)  
  2782.                             flag = false;  
  2783.                         else  
  2784.                             Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);  
  2785.   
  2786.                         Q_k = (Q_k * Q) % n;  
  2787.                     }  
  2788.                     else  
  2789.                     {  
  2790.                         // index doubling  
  2791.                         u1 = ((u1 * v) - Q_k) % n;  
  2792.   
  2793.                         v1 = ((v * v1) - (P * Q_k)) % n;  
  2794.                         v = n.BarrettReduction(v * v, n, constant);  
  2795.                         v = (v - (Q_k << 1)) % n;  
  2796.   
  2797.                         if (flag)  
  2798.                         {  
  2799.                             Q_k = Q % n;  
  2800.                             flag = false;  
  2801.                         }  
  2802.                         else  
  2803.                             Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);  
  2804.                     }  
  2805.   
  2806.                     mask >>= 1;  
  2807.                 }  
  2808.                 mask = 0x80000000;  
  2809.             }  
  2810.   
  2811.             // at this point u1 = u(n+1) and v = v(n)  
  2812.             // since the last bit always 1, we need to transform u1 to u(2n+1) and v to v(2n+1)  
  2813.   
  2814.             u1 = ((u1 * v) - Q_k) % n;  
  2815.             v = ((v * v1) - (P * Q_k)) % n;  
  2816.             if (flag)  
  2817.                 flag = false;  
  2818.             else  
  2819.                 Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);  
  2820.   
  2821.             Q_k = (Q_k * Q) % n;  
  2822.   
  2823.   
  2824.             for (int i = 0; i < s; i++)  
  2825.             {  
  2826.                 // index doubling  
  2827.                 u1 = (u1 * v) % n;  
  2828.                 v = ((v * v) - (Q_k << 1)) % n;  
  2829.   
  2830.                 if (flag)  
  2831.                 {  
  2832.                     Q_k = Q % n;  
  2833.                     flag = false;  
  2834.                 }  
  2835.                 else  
  2836.                     Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);  
  2837.             }  
  2838.   
  2839.             result[0] = u1;  
  2840.             result[1] = v;  
  2841.             result[2] = Q_k;  
  2842.   
  2843.             return result;  
  2844.         }  
  2845.   
  2846.   
  2847.         //***********************************************************************  
  2848.         // Tests the correct implementation of the /, %, * and + operators  
  2849.         //***********************************************************************  
  2850.   
  2851.         public static void MulDivTest(int rounds)  
  2852.         {  
  2853.             Random rand = new Random();  
  2854.             byte[] val = new byte[64];  
  2855.             byte[] val2 = new byte[64];  
  2856.   
  2857.             for (int count = 0; count < rounds; count++)  
  2858.             {  
  2859.                 // generate 2 numbers of random length  
  2860.                 int t1 = 0;  
  2861.                 while (t1 == 0)  
  2862.                     t1 = (int)(rand.NextDouble() * 65);  
  2863.   
  2864.                 int t2 = 0;  
  2865.                 while (t2 == 0)  
  2866.                     t2 = (int)(rand.NextDouble() * 65);  
  2867.   
  2868.                 bool done = false;  
  2869.                 while (!done)  
  2870.                 {  
  2871.                     for (int i = 0; i < 64; i++)  
  2872.                     {  
  2873.                         if (i < t1)  
  2874.                             val[i] = (byte)(rand.NextDouble() * 256);  
  2875.                         else  
  2876.                             val[i] = 0;  
  2877.   
  2878.                         if (val[i] != 0)  
  2879.                             done = true;  
  2880.                     }  
  2881.                 }  
  2882.   
  2883.                 done = false;  
  2884.                 while (!done)  
  2885.                 {  
  2886.                     for (int i = 0; i < 64; i++)  
  2887.                     {  
  2888.                         if (i < t2)  
  2889.                             val2[i] = (byte)(rand.NextDouble() * 256);  
  2890.                         else  
  2891.                             val2[i] = 0;  
  2892.   
  2893.                         if (val2[i] != 0)  
  2894.                             done = true;  
  2895.                     }  
  2896.                 }  
  2897.   
  2898.                 while (val[0] == 0)  
  2899.                     val[0] = (byte)(rand.NextDouble() * 256);  
  2900.                 while (val2[0] == 0)  
  2901.                     val2[0] = (byte)(rand.NextDouble() * 256);  
  2902.   
  2903.                 Console.WriteLine(count);  
  2904.                 BigInteger bn1 = new BigInteger(val, t1);  
  2905.                 BigInteger bn2 = new BigInteger(val2, t2);  
  2906.   
  2907.   
  2908.                 // Determine the quotient and remainder by dividing  
  2909.                 // the first number by the second.  
  2910.   
  2911.                 BigInteger bn3 = bn1 / bn2;  
  2912.                 BigInteger bn4 = bn1 % bn2;  
  2913.   
  2914.                 // Recalculate the number  
  2915.                 BigInteger bn5 = (bn3 * bn2) + bn4;  
  2916.   
  2917.                 // Make sure they're the same  
  2918.                 if (bn5 != bn1)  
  2919.                 {  
  2920.                     Console.WriteLine("Error at " + count);  
  2921.                     Console.WriteLine(bn1 + "\n");  
  2922.                     Console.WriteLine(bn2 + "\n");  
  2923.                     Console.WriteLine(bn3 + "\n");  
  2924.                     Console.WriteLine(bn4 + "\n");  
  2925.                     Console.WriteLine(bn5 + "\n");  
  2926.                     return;  
  2927.                 }  
  2928.             }  
  2929.         }  
  2930.   
  2931.   
  2932.         //***********************************************************************  
  2933.         // Tests the correct implementation of the modulo exponential function  
  2934.         // using RSA encryption and decryption (using pre-computed encryption and  
  2935.         // decryption keys).  
  2936.         //***********************************************************************  
  2937.   
  2938.         public static void RSATest(int rounds)  
  2939.         {  
  2940.             Random rand = new Random(1);  
  2941.             byte[] val = new byte[64];  
  2942.   
  2943.             // private and public key  
  2944.             BigInteger bi_e = new BigInteger("a932b948feed4fb2b692609bd22164fc9edb59fae7880cc1eaff7b3c9626b7e5b241c27a974833b2622ebe09beb451917663d47232488f23a117fc97720f1e7", 16);  
  2945.             BigInteger bi_d = new BigInteger("4adf2f7a89da93248509347d2ae506d683dd3a16357e859a980c4f77a4e2f7a01fae289f13a851df6e9db5adaa60bfd2b162bbbe31f7c8f828261a6839311929d2cef4f864dde65e556ce43c89bbbf9f1ac5511315847ce9cc8dc92470a747b8792d6a83b0092d2e5ebaf852c85cacf34278efa99160f2f8aa7ee7214de07b7", 16);  
  2946.             BigInteger bi_n = new BigInteger("e8e77781f36a7b3188d711c2190b560f205a52391b3479cdb99fa010745cbeba5f2adc08e1de6bf38398a0487c4a73610d94ec36f17f3f46ad75e17bc1adfec99839589f45f95ccc94cb2a5c500b477eb3323d8cfab0c8458c96f0147a45d27e45a4d11d54d77684f65d48f15fafcc1ba208e71e921b9bd9017c16a5231af7f", 16);  
  2947.   
  2948.             Console.WriteLine("e =\n" + bi_e.ToString(10));  
  2949.             Console.WriteLine("\nd =\n" + bi_d.ToString(10));  
  2950.             Console.WriteLine("\nn =\n" + bi_n.ToString(10) + "\n");  
  2951.   
  2952.             for (int count = 0; count < rounds; count++)  
  2953.             {  
  2954.                 // generate data of random length  
  2955.                 int t1 = 0;  
  2956.                 while (t1 == 0)  
  2957.                     t1 = (int)(rand.NextDouble() * 65);  
  2958.   
  2959.                 bool done = false;  
  2960.                 while (!done)  
  2961.                 {  
  2962.                     for (int i = 0; i < 64; i++)  
  2963.                     {  
  2964.                         if (i < t1)  
  2965.                             val[i] = (byte)(rand.NextDouble() * 256);  
  2966.                         else  
  2967.                             val[i] = 0;  
  2968.   
  2969.                         if (val[i] != 0)  
  2970.                             done = true;  
  2971.                     }  
  2972.                 }  
  2973.   
  2974.                 while (val[0] == 0)  
  2975.                     val[0] = (byte)(rand.NextDouble() * 256);  
  2976.   
  2977.                 Console.Write("Round = " + count);  
  2978.   
  2979.                 // encrypt and decrypt data  
  2980.                 BigInteger bi_data = new BigInteger(val, t1);  
  2981.                 BigInteger bi_encrypted = bi_data.modPow(bi_e, bi_n);  
  2982.                 BigInteger bi_decrypted = bi_encrypted.modPow(bi_d, bi_n);  
  2983.   
  2984.                 // compare  
  2985.                 if (bi_decrypted != bi_data)  
  2986.                 {  
  2987.                     Console.WriteLine("\nError at round " + count);  
  2988.                     Console.WriteLine(bi_data + "\n");  
  2989.                     return;  
  2990.                 }  
  2991.                 Console.WriteLine(" <PASSED>.");  
  2992.             }  
  2993.   
  2994.         }  
  2995.   
  2996.   
  2997.         //***********************************************************************  
  2998.         // Tests the correct implementation of the modulo exponential and  
  2999.         // inverse modulo functions using RSA encryption and decryption.  The two  
  3000.         // pseudoprimes p and q are fixed, but the two RSA keys are generated  
  3001.         // for each round of testing.  
  3002.         //***********************************************************************  
  3003.   
  3004.         public static void RSATest2(int rounds)  
  3005.         {  
  3006.             Random rand = new Random();  
  3007.             byte[] val = new byte[64];  
  3008.   
  3009.             byte[] pseudoPrime1 = {  
  3010.                         (byte)0x85, (byte)0x84, (byte)0x64, (byte)0xFD, (byte)0x70, (byte)0x6A,  
  3011.                         (byte)0x9F, (byte)0xF0, (byte)0x94, (byte)0x0C, (byte)0x3E, (byte)0x2C,  
  3012.                         (byte)0x74, (byte)0x34, (byte)0x05, (byte)0xC9, (byte)0x55, (byte)0xB3,  
  3013.                         (byte)0x85, (byte)0x32, (byte)0x98, (byte)0x71, (byte)0xF9, (byte)0x41,  
  3014.                         (byte)0x21, (byte)0x5F, (byte)0x02, (byte)0x9E, (byte)0xEA, (byte)0x56,  
  3015.                         (byte)0x8D, (byte)0x8C, (byte)0x44, (byte)0xCC, (byte)0xEE, (byte)0xEE,  
  3016.                         (byte)0x3D, (byte)0x2C, (byte)0x9D, (byte)0x2C, (byte)0x12, (byte)0x41,  
  3017.                         (byte)0x1E, (byte)0xF1, (byte)0xC5, (byte)0x32, (byte)0xC3, (byte)0xAA,  
  3018.                         (byte)0x31, (byte)0x4A, (byte)0x52, (byte)0xD8, (byte)0xE8, (byte)0xAF,  
  3019.                         (byte)0x42, (byte)0xF4, (byte)0x72, (byte)0xA1, (byte)0x2A, (byte)0x0D,  
  3020.                         (byte)0x97, (byte)0xB1, (byte)0x31, (byte)0xB3,  
  3021.                 };  
  3022.   
  3023.             byte[] pseudoPrime2 = {  
  3024.                         (byte)0x99, (byte)0x98, (byte)0xCA, (byte)0xB8, (byte)0x5E, (byte)0xD7,  
  3025.                         (byte)0xE5, (byte)0xDC, (byte)0x28, (byte)0x5C, (byte)0x6F, (byte)0x0E,  
  3026.                         (byte)0x15, (byte)0x09, (byte)0x59, (byte)0x6E, (byte)0x84, (byte)0xF3,  
  3027.                         (byte)0x81, (byte)0xCD, (byte)0xDE, (byte)0x42, (byte)0xDC, (byte)0x93,  
  3028.                         (byte)0xC2, (byte)0x7A, (byte)0x62, (byte)0xAC, (byte)0x6C, (byte)0xAF,  
  3029.                         (byte)0xDE, (byte)0x74, (byte)0xE3, (byte)0xCB, (byte)0x60, (byte)0x20,  
  3030.                         (byte)0x38, (byte)0x9C, (byte)0x21, (byte)0xC3, (byte)0xDC, (byte)0xC8,  
  3031.                         (byte)0xA2, (byte)0x4D, (byte)0xC6, (byte)0x2A, (byte)0x35, (byte)0x7F,  
  3032.                         (byte)0xF3, (byte)0xA9, (byte)0xE8, (byte)0x1D, (byte)0x7B, (byte)0x2C,  
  3033.                         (byte)0x78, (byte)0xFA, (byte)0xB8, (byte)0x02, (byte)0x55, (byte)0x80,  
  3034.                         (byte)0x9B, (byte)0xC2, (byte)0xA5, (byte)0xCB,  
  3035.                 };  
  3036.   
  3037.   
  3038.             BigInteger bi_p = new BigInteger(pseudoPrime1);  
  3039.             BigInteger bi_q = new BigInteger(pseudoPrime2);  
  3040.             BigInteger bi_pq = (bi_p - 1) * (bi_q - 1);  
  3041.             BigInteger bi_n = bi_p * bi_q;  
  3042.   
  3043.             for (int count = 0; count < rounds; count++)  
  3044.             {  
  3045.                 // generate private and public key  
  3046.                 BigInteger bi_e = bi_pq.genCoPrime(512, rand);  
  3047.                 BigInteger bi_d = bi_e.modInverse(bi_pq);  
  3048.   
  3049.                 Console.WriteLine("\ne =\n" + bi_e.ToString(10));  
  3050.                 Console.WriteLine("\nd =\n" + bi_d.ToString(10));  
  3051.                 Console.WriteLine("\nn =\n" + bi_n.ToString(10) + "\n");  
  3052.   
  3053.                 // generate data of random length  
  3054.                 int t1 = 0;  
  3055.                 while (t1 == 0)  
  3056.                     t1 = (int)(rand.NextDouble() * 65);  
  3057.   
  3058.                 bool done = false;  
  3059.                 while (!done)  
  3060.                 {  
  3061.                     for (int i = 0; i < 64; i++)  
  3062.                     {  
  3063.                         if (i < t1)  
  3064.                             val[i] = (byte)(rand.NextDouble() * 256);  
  3065.                         else  
  3066.                             val[i] = 0;  
  3067.   
  3068.                         if (val[i] != 0)  
  3069.                             done = true;  
  3070.                     }  
  3071.                 }  
  3072.   
  3073.                 while (val[0] == 0)  
  3074.                     val[0] = (byte)(rand.NextDouble() * 256);  
  3075.   
  3076.                 Console.Write("Round = " + count);  
  3077.   
  3078.                 // encrypt and decrypt data  
  3079.                 BigInteger bi_data = new BigInteger(val, t1);  
  3080.                 BigInteger bi_encrypted = bi_data.modPow(bi_e, bi_n);  
  3081.                 BigInteger bi_decrypted = bi_encrypted.modPow(bi_d, bi_n);  
  3082.   
  3083.                 // compare  
  3084.                 if (bi_decrypted != bi_data)  
  3085.                 {  
  3086.                     Console.WriteLine("\nError at round " + count);  
  3087.                     Console.WriteLine(bi_data + "\n");  
  3088.                     return;  
  3089.                 }  
  3090.                 Console.WriteLine(" <PASSED>.");  
  3091.             }  
  3092.   
  3093.         }  
  3094.   
  3095.   
  3096.         //***********************************************************************  
  3097.         // Tests the correct implementation of sqrt() method.  
  3098.         //***********************************************************************  
  3099.   
  3100.         public static void SqrtTest(int rounds)  
  3101.         {  
  3102.             Random rand = new Random();  
  3103.             for (int count = 0; count < rounds; count++)  
  3104.             {  
  3105.                 // generate data of random length  
  3106.                 int t1 = 0;  
  3107.                 while (t1 == 0)  
  3108.                     t1 = (int)(rand.NextDouble() * 1024);  
  3109.   
  3110.                 Console.Write("Round = " + count);  
  3111.   
  3112.                 BigInteger a = new BigInteger();  
  3113.                 a.genRandomBits(t1, rand);  
  3114.   
  3115.                 BigInteger b = a.sqrt();  
  3116.                 BigInteger c = (b + 1) * (b + 1);  
  3117.   
  3118.                 // check that b is the largest integer such that b*b <= a  
  3119.                 if (c <= a)  
  3120.                 {  
  3121.                     Console.WriteLine("\nError at round " + count);  
  3122.                     Console.WriteLine(a + "\n");  
  3123.                     return;  
  3124.                 }  
  3125.                 Console.WriteLine(" <PASSED>.");  
  3126.             }  
  3127.         }  
  3128.   
  3129.   
  3130.   
  3131.        
  3132.   
  3133.     }  
  3134. }  
[csharp] view plain copy
  1.   
[csharp] view plain copy
  1.   


[csharp] view plain copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Security.Cryptography;  
  5. using System.Text;  
  6.   
  7. namespace RSATest  
  8. {  
  9.     /// <summary>  
  10.     /// 非对称RSA加密类 可以参考  
  11.     /// http://www.cnblogs.com/hhh/archive/2011/06/03/2070692.html  
  12.     /// http://blog.youkuaiyun.com/zhilunchen/article/details/2943158  
  13.     /// 若是私匙加密 则需公钥解密  
  14.     /// 反正公钥加密 私匙来解密  
  15.     /// 需要BigInteger类来辅助  
  16.     /// </summary>  
  17.     public static class RSAHelper  
  18.     {  
  19.         /// <summary>  
  20.         /// RSA的容器 可以解密的源字符串长度为 DWKEYSIZE/8-11   
  21.         /// </summary>  
  22.         public const int DWKEYSIZE = 1024;  
  23.   
  24.         /// <summary>  
  25.         /// RSA加密的密匙结构  公钥和私匙  
  26.         /// </summary>  
  27.         public struct RSAKey  
  28.         {  
  29.             public string PublicKey { getset; }  
  30.             public string PrivateKey { getset; }  
  31.         }  
  32.  
  33.         #region 得到RSA的解谜的密匙对  
  34.         /// <summary>  
  35.         /// 得到RSA的解谜的密匙对  
  36.         /// </summary>  
  37.         /// <returns></returns>  
  38.         public static RSAKey GetRASKey()  
  39.         {  
  40.             RSACryptoServiceProvider.UseMachineKeyStore = true;  
  41.             //声明一个指定大小的RSA容器  
  42.             RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(DWKEYSIZE);  
  43.             //取得RSA容易里的各种参数  
  44.             RSAParameters p = rsaProvider.ExportParameters(true);  
  45.   
  46.             return new RSAKey()  
  47.             {  
  48.                 PublicKey = ComponentKey(p.Exponent,p.Modulus),  
  49.                 PrivateKey = ComponentKey(p.D,p.Modulus)  
  50.             };  
  51.         }  
  52.         #endregion  
  53.  
  54.         #region 检查明文的有效性 DWKEYSIZE/8-11 长度之内为有效 中英文都算一个字符  
  55.         /// <summary>  
  56.         /// 检查明文的有效性 DWKEYSIZE/8-11 长度之内为有效 中英文都算一个字符  
  57.         /// </summary>  
  58.         /// <param name="source"></param>  
  59.         /// <returns></returns>  
  60.         public static bool CheckSourceValidate(string source)  
  61.         {  
  62.             return (DWKEYSIZE / 8 - 11) >= source.Length;  
  63.         }  
  64.         #endregion  
  65.  
  66.         #region 组合解析密匙  
  67.         /// <summary>  
  68.         /// 组合成密匙字符串  
  69.         /// </summary>  
  70.         /// <param name="b1"></param>  
  71.         /// <param name="b2"></param>  
  72.         /// <returns></returns>  
  73.         private static string ComponentKey(byte[] b1, byte[] b2)  
  74.         {  
  75.             List<byte> list = new List<byte>();  
  76.             //在前端加上第一个数组的长度值 这样今后可以根据这个值分别取出来两个数组  
  77.             list.Add((byte)b1.Length);  
  78.             list.AddRange(b1);  
  79.             list.AddRange(b2);  
  80.             byte[] b = list.ToArray<byte>();  
  81.             return Convert.ToBase64String(b);  
  82.         }  
  83.   
  84.         /// <summary>  
  85.         /// 解析密匙  
  86.         /// </summary>  
  87.         /// <param name="key">密匙</param>  
  88.         /// <param name="b1">RSA的相应参数1</param>  
  89.         /// <param name="b2">RSA的相应参数2</param>  
  90.         private static void ResolveKey(string key, out byte[] b1, out byte[] b2)  
  91.         {  
  92.             //从base64字符串 解析成原来的字节数组  
  93.             byte[] b = Convert.FromBase64String(key);  
  94.             //初始化参数的数组长度  
  95.             b1=new byte[b[0]];  
  96.             b2=new byte[b.Length-b[0]-1];  
  97.             //将相应位置是值放进相应的数组  
  98.             for (int n = 1, i = 0, j = 0; n < b.Length; n++)  
  99.             {  
  100.                 if (n <= b[0])  
  101.                 {  
  102.                     b1[i++] = b[n];  
  103.                 }  
  104.                 else {  
  105.                     b2[j++] = b[n];  
  106.                 }  
  107.             }  
  108.         }  
  109.         #endregion  
  110.  
  111.         #region 字符串加密解密 公开方法  
  112.         /// <summary>  
  113.         /// 字符串加密  
  114.         /// </summary>  
  115.         /// <param name="source">源字符串 明文</param>  
  116.         /// <param name="key">密匙</param>  
  117.         /// <returns>加密遇到错误将会返回原字符串</returns>  
  118.         public static string EncryptString(string source,string key)  
  119.         {  
  120.             string encryptString = string.Empty;  
  121.             byte[] d;  
  122.             byte[] n;  
  123.             try  
  124.             {  
  125.                 if (!CheckSourceValidate(source))  
  126.                 {  
  127.                     throw new Exception("source string too long");  
  128.                 }  
  129.                 //解析这个密钥  
  130.                 ResolveKey(key, out d, out n);  
  131.                 BigInteger biN = new BigInteger(n);  
  132.                 BigInteger biD = new BigInteger(d);  
  133.                 encryptString= EncryptString(source, biD, biN);  
  134.             }  
  135.             catch  
  136.             {  
  137.                 encryptString = source;  
  138.             }  
  139.             return encryptString;  
  140.         }  
  141.   
  142.         /// <summary>  
  143.         /// 字符串解密  
  144.         /// </summary>  
  145.         /// <param name="encryptString">密文</param>  
  146.         /// <param name="key">密钥</param>  
  147.         /// <returns>遇到解密失败将会返回原字符串</returns>  
  148.         public static string DecryptString(string encryptString, string key)  
  149.         {  
  150.             string source = string.Empty;  
  151.             byte[] e;  
  152.             byte[] n;  
  153.             try  
  154.             {  
  155.                 //解析这个密钥  
  156.                 ResolveKey(key, out e, out n);  
  157.                 BigInteger biE = new BigInteger(e);  
  158.                 BigInteger biN = new BigInteger(n);  
  159.                 source = DecryptString(encryptString, biE, biN);  
  160.             }  
  161.             catch {  
  162.                 source = encryptString;  
  163.             }  
  164.             return source;  
  165.         }  
  166.         #endregion  
  167.  
  168.         #region 字符串加密解密 私有  实现加解密的实现方法  
  169.         /// <summary>  
  170.         /// 用指定的密匙加密   
  171.         /// </summary>  
  172.         /// <param name="source">明文</param>  
  173.         /// <param name="d">可以是RSACryptoServiceProvider生成的D</param>  
  174.         /// <param name="n">可以是RSACryptoServiceProvider生成的Modulus</param>  
  175.         /// <returns>返回密文</returns>  
  176.         private static string EncryptString(string source, BigInteger d, BigInteger n)  
  177.         {  
  178.             int len = source.Length;  
  179.             int len1 = 0;  
  180.             int blockLen = 0;  
  181.             if ((len % 128) == 0)  
  182.                 len1 = len / 128;  
  183.             else  
  184.                 len1 = len / 128 + 1;  
  185.             string block = "";  
  186.             StringBuilder result = new StringBuilder();  
  187.             for (int i = 0; i < len1; i++)  
  188.             {  
  189.                 if (len >= 128)  
  190.                     blockLen = 128;  
  191.                 else  
  192.                     blockLen = len;  
  193.                 block = source.Substring(i * 128, blockLen);  
  194.                 byte[] oText = System.Text.Encoding.Default.GetBytes(block);  
  195.                 BigInteger biText = new BigInteger(oText);  
  196.                 BigInteger biEnText = biText.modPow(d, n);  
  197.                 string temp = biEnText.ToHexString();  
  198.                 result.Append(temp).Append("@");  
  199.                 len -= blockLen;  
  200.             }  
  201.             return result.ToString().TrimEnd('@');  
  202.         }  
  203.   
  204.         /// <summary>  
  205.         /// 用指定的密匙加密   
  206.         /// </summary>  
  207.         /// <param name="source">密文</param>  
  208.         /// <param name="e">可以是RSACryptoServiceProvider生成的Exponent</param>  
  209.         /// <param name="n">可以是RSACryptoServiceProvider生成的Modulus</param>  
  210.         /// <returns>返回明文</returns>  
  211.         private static string DecryptString(string encryptString, BigInteger e, BigInteger n)  
  212.         {  
  213.             StringBuilder result = new StringBuilder();  
  214.             string[] strarr1 = encryptString.Split(new char[] { '@' }, StringSplitOptions.RemoveEmptyEntries);  
  215.             for (int i = 0; i < strarr1.Length; i++)  
  216.             {  
  217.                 string block = strarr1[i];  
  218.                 BigInteger biText = new BigInteger(block, 16);  
  219.                 BigInteger biEnText = biText.modPow(e, n);  
  220.                 string temp = System.Text.Encoding.Default.GetString(biEnText.getBytes());  
  221.                 result.Append(temp);  
  222.             }  
  223.             return result.ToString();  
  224.         }  
  225.         #endregion  
  226.     }  
  227. }  

测试程序:

[csharp] view plain copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace RSATest  
  7. {  
  8.     class Program  
  9.     {  
  10.         static void Main(string[] args)  
  11.         {  
  12.             string str = "{\"sc\":\"his51\",\"no\":\"1\",\"na\":\"管理员\"}{\"sc\":\"@his51\",\"no\":\"1\",\"na\":\"管理员\"}{\"sc\":\"his51\",\"no\":\"1\",\"na\":\"管员\"}{\"sc\":\"his522";  
  13.             RSAHelper.RSAKey keyPair = RSAHelper.GetRASKey();  
  14.             Console.WriteLine("加密前:"+str+"\r\n");  
  15.             Console.WriteLine("公钥:" + keyPair.PublicKey + "\r\n");  
  16.             Console.WriteLine("私钥:" + keyPair.PrivateKey + "\r\n");  
  17.             string en = RSAHelper.EncryptString(str, keyPair.PrivateKey);  
  18.             Console.WriteLine("加密后:"+en + "\r\n");  
  19.             Console.WriteLine("解密:"+RSAHelper.DecryptString(en, keyPair.PublicKey) + "\r\n");  
  20.             Console.ReadLine();  
  21.         }  
  22.     }  
  23. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值