ras算法

  1. using System;
  2. public class RSA
  3. {
  4.     //RSA算法所需参数
  5.     public struct RSA_PARAM
  6.     {
  7.         public ulong p, q;   //两个素数,不参与加密解密运算
  8.         public ulong f;      //f=(p-1)*(q-1),不参与加密解密运算
  9.         public ulong n, e;   //公匙,n=p*q,gcd(e,f)=1
  10.         public ulong d;      //私匙,e*d=1 (mod f),gcd(n,d)=1
  11.         public ulong s;      //块长,满足2^s<=n的最大的s,即log2(n)
  12.         public override string ToString()
  13.         {
  14.             string result = "";
  15.             result += "p=" + this.p + "/n";
  16.             result += "q=" + this.q + "/n";
  17.             result += "f=(p-1)*(q-1)=" + this.f + "/n";
  18.             result += "n=p*q=" + this.n + "/n";
  19.             result += "e=" + this.e + "/n";
  20.             result += "d=" + this.d + "/n";
  21.             result += "s=" + this.s + "/n";
  22.             return result;
  23.         }
  24.     }
  25.     public class RandNumber
  26.     {
  27.         const ulong MULTIPLIER = 12747293821;
  28.         const ulong ADDER = 1343545677842234541;//随机数类
  29.         private ulong randSeed;
  30.         public RandNumber() : this(0) { }
  31.         public RandNumber(ulong s)
  32.         {
  33.             if (s == 0)
  34.                 randSeed = (ulong)Environment.TickCount;
  35.             else
  36.                 randSeed = s;
  37.         }
  38.         public ulong Random(ulong n)
  39.         {
  40.             randSeed = MULTIPLIER * randSeed + ADDER;
  41.             return randSeed % n;
  42.         }
  43.     }
  44.     public static RandNumber Rand = new RandNumber();
  45.     //小素数表
  46.     static int[] PrimeTable = new int[] { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };
  47.     static int PrimeCount = PrimeTable.Length;
  48.     //模幂运算,返回值 x=base^pow mod n
  49.     static ulong PowMod(ulong Base, ulong pow, ulong n)
  50.     {
  51.         ulong c = 1;
  52.         while (pow != 0)
  53.         {
  54.             while ((pow & 1) == 0)
  55.             {
  56.                 pow >>= 1;
  57.                 Base = Base * Base % n;
  58.             }
  59.             pow--;
  60.             c = Base * c % n;
  61.         } return c;
  62.     }
  63.     //Rabin-Miller素数测试,通过测试返回1,否则返回0。
  64.     //n是待测素数。
  65.     //注意:通过测试并不一定就是素数,非素数通过测试的概率是1/4
  66.     static int RabinMillerKnl(ref  ulong n)
  67.     {
  68.         ulong b, m, j, v, i;
  69.         m = n - 1;
  70.         j = 0;    //0、先计算出m、j,使得n-1=m*2^j,其中m是正奇数,j是非负整数
  71.         while ((m & 1) == 0)
  72.         {
  73.             ++j;
  74.             m >>= 1;
  75.         }    //1、随机取一个b,2<=b<n-1
  76.         b = 2 + Rand.Random(n - 3);    //2、计算v=b^m mod n
  77.         v = PowMod(b, m, n);    //3、如果v==1,通过测试
  78.         if (v == 1)
  79.         {
  80.             return 1;
  81.         }    //4、令i=1
  82.         i = 1;    //5、如果v=n-1,通过测试
  83.         while (v != n - 1)
  84.         {
  85.             //6、如果i==l,非素数,结束
  86.             if (i == j)
  87.             {
  88.                 return 0;
  89.             }        //7、v=v^2 mod n,i=i+1
  90.             v = PowMod(v, 2, n);
  91.             ++i;        //8、循环到5
  92.         } return 1;
  93.     }
  94.     //Rabin-Miller素数测试,循环调用核心loop次
  95.     //全部通过返回1,否则返回0
  96.     static int RabinMiller(ulong n, int loop)
  97.     {
  98.         //先用小素数筛选一次,提高效率
  99.         for (int i = 0; i < PrimeCount; i++)
  100.         {
  101.             if (n % (ulong)PrimeTable[i] == 0)
  102.             {
  103.                 return 0;
  104.             }
  105.         }    //循环调用Rabin-Miller测试loop次,使得非素数通过测试的概率降为(1/4)^loop
  106.         for (int i = 0; i < loop; i++)
  107.         {
  108.             if (RabinMillerKnl(ref n) == 0)
  109.             {
  110.                 return 0;
  111.             }
  112.         } return 1;
  113.     }
  114.     /* 随机生成一个bits位(二进制位)的素数,最多32位 */
  115.     static ulong RandomPrime(sbyte bits)
  116.     {
  117.         ulong @base;
  118.         do
  119.         {
  120.             @base = (uint)1 << (bits - 1);   //保证最高位是1
  121.             @base += Rand.Random(@base);               //再加上一个随机数
  122.             @base |= 1;    //保证最低位是1,即保证是奇数
  123.         } while (RabinMiller(@base, 30) == 0);    //进行拉宾-米勒测试30次
  124.         return @base;    //全部通过认为是素数
  125.     }
  126.     /* 欧几里得法求最大公约数 */
  127.     ulong EuclidGcd(ref ulong p, ref ulong q)
  128.     {
  129.         ulong a = p > q ? p : q;
  130.         ulong b = p < q ? p : q;
  131.         ulong t;
  132.         if (p == q)
  133.         {
  134.             return p;   //两数相等,最大公约数就是本身
  135.         }
  136.         else
  137.         {
  138.             while (b != 0)    //辗转相除法,gcd(a,b)=gcd(b,a-qb)
  139.             {
  140.                 a = a % b;
  141.                 t = a;
  142.                 a = b;
  143.                 b = t;
  144.             } return a;
  145.         }
  146.     }
  147.     /* Stein法求最大公约数 */
  148.     static ulong SteinGcd(ref ulong p, ref ulong q)
  149.     {
  150.         ulong a = p > q ? p : q;
  151.         ulong b = p < q ? p : q;
  152.         ulong t, r = 1;
  153.         if (p == q)
  154.         {
  155.             return p;   //两数相等,最大公约数就是本身
  156.         }
  157.         else
  158.         {
  159.             while (((a & 1) == 0) && ((b & 1) == 0))
  160.             {
  161.                 r <<= 1;    //a、b均为偶数时,gcd(a,b)=2*gcd(a/2,b/2)
  162.                 a >>= 1;
  163.                 b >>= 1;
  164.             } if ((a & 1) == 0)
  165.             {
  166.                 t = a;  //如果a为偶数,交换a,b
  167.                 a = b;
  168.                 b = t;
  169.             } do
  170.             {
  171.                 while ((b & 1) == 0)
  172.                 {
  173.                     b >>= 1;    //b为偶数,a为奇数时,gcd(b,a)=gcd(b/2,a)
  174.                 }
  175.                 if (b < a)
  176.                 {
  177.                     t = a;  //如果b小于a,交换a,b
  178.                     a = b;
  179.                     b = t;
  180.                 } b = (b - a) >> 1; //b、a都是奇数,gcd(b,a)=gcd((b-a)/2,a)
  181.             } while (b != 0);
  182.             return r * a;
  183.         }
  184.     }
  185.     /* 已知a、b,求x,满足a*x =1 (mod b) 相当于求解a*x-b*y=1的最小整数解 */
  186.     static ulong Euclid(ref ulong a, ref ulong b)
  187.     {
  188.         ulong m, e, i, j, x, y;
  189.         int xx, yy;
  190.         m = b;
  191.         e = a;
  192.         x = 0;
  193.         y = 1;
  194.         xx = 1;
  195.         yy = 1;
  196.         while (e != 0)
  197.         {
  198.             i = m / e;
  199.             j = m % e;
  200.             m = e;
  201.             e = j;
  202.             j = y;
  203.             y *= i;
  204.             if (xx == yy)
  205.             {
  206.                 if (x > y)
  207.                 {
  208.                     y = x - y;
  209.                 }
  210.                 else
  211.                 {
  212.                     y -= x;
  213.                     yy = 0;
  214.                 }
  215.             }
  216.             else
  217.             {
  218.                 y += x;
  219.                 xx = 1 - xx;
  220.                 yy = 1 - yy;
  221.             } x = j;
  222.         } if (xx == 0)
  223.         {
  224.             x = b - x;
  225.         } return x;
  226.     }
  227.     /* 随机产生一个RSA加密参数 */
  228.     static RSA_PARAM RsaGetParam()
  229.     {
  230.         RSA_PARAM Rsa = new RSA_PARAM();
  231.         ulong t;
  232.         Rsa.p = RandomPrime(16);          //随机生成两个素数
  233.         Rsa.q = RandomPrime(16);
  234.         Rsa.n = Rsa.p * Rsa.q;
  235.         Rsa.f = (Rsa.p - 1) * (Rsa.q - 1);
  236.         do
  237.         {
  238.             Rsa.e = Rand.Random(65536);  //小于2^16,65536=2^16
  239.             Rsa.e |= 1;                   //保证最低位是1,即保证是奇数,因f一定是偶数,要互素,只能是奇数
  240.         } while (SteinGcd(ref  Rsa.e, ref  Rsa.f) != 1); Rsa.d = Euclid(ref  Rsa.e, ref  Rsa.f);
  241.         Rsa.s = 0;
  242.         t = Rsa.n >> 1;
  243.         while (t != 0)
  244.         {
  245.             Rsa.s++;                    //s=log2(n)
  246.             t >>= 1;
  247.         } return Rsa;
  248.     }
  249.     /* 拉宾-米勒测试 */
  250.     static void TestRM()
  251.     {
  252.         uint k = 0;
  253.         Console.WriteLine(" - Rabin-Miller prime check./n");
  254.         for (ulong i = 4197900001; i < 4198000000; i += 2)
  255.         {
  256.             if (RabinMiller(i, 30) != 0)
  257.             {
  258.                 k++;
  259.                 Console.WriteLine(i);
  260.             }
  261.             Console.WriteLine("Total: " + k);
  262.         }
  263.     }
  264.     static void Main(string[] args)
  265.     {
  266.         for (int x = 0; x < 1000; x++)
  267.         {
  268.             RSA_PARAM r = RsaGetParam();
  269.             ulong[] test = new ulong[100];
  270.             Random rand = new Random();
  271.             for (int i = 0; i < test.Length; i++)
  272.                 test[i] = (ushort)rand.Next();
  273.             //加密
  274.             ulong[] enc = new ulong[test.Length];
  275.             for (int i = 0; i < test.Length; i++)
  276.                 enc[i] = PowMod(test[i], r.e, r.n);
  277.             //解密
  278.             ulong[] dec = new ulong[test.Length];
  279.             for (int i = 0; i < dec.Length; i++)
  280.                 dec[i] = PowMod(enc[i], r.d, r.n);
  281.             for (int i = 0; i < dec.Length; i++)
  282.                 if (test[i] != dec[i])
  283.                     Console.WriteLine("false");
  284.             Console.WriteLine("OK");
  285.         }
  286.         Console.ReadLine();
  287.     }
  288. }

猜你喜欢

转载自blog.csdn.net/KAMILLE/article/details/3075015
RAS