- using System;
- public class RSA
- {
- //RSA算法所需参数
- public struct RSA_PARAM
- {
- public ulong p, q; //两个素数,不参与加密解密运算
- public ulong f; //f=(p-1)*(q-1),不参与加密解密运算
- public ulong n, e; //公匙,n=p*q,gcd(e,f)=1
- public ulong d; //私匙,e*d=1 (mod f),gcd(n,d)=1
- public ulong s; //块长,满足2^s<=n的最大的s,即log2(n)
- public override string ToString()
- {
- string result = "";
- result += "p=" + this.p + "/n";
- result += "q=" + this.q + "/n";
- result += "f=(p-1)*(q-1)=" + this.f + "/n";
- result += "n=p*q=" + this.n + "/n";
- result += "e=" + this.e + "/n";
- result += "d=" + this.d + "/n";
- result += "s=" + this.s + "/n";
- return result;
- }
- }
- public class RandNumber
- {
- const ulong MULTIPLIER = 12747293821;
- const ulong ADDER = 1343545677842234541;//随机数类
- private ulong randSeed;
- public RandNumber() : this(0) { }
- public RandNumber(ulong s)
- {
- if (s == 0)
- randSeed = (ulong)Environment.TickCount;
- else
- randSeed = s;
- }
- public ulong Random(ulong n)
- {
- randSeed = MULTIPLIER * randSeed + ADDER;
- return randSeed % n;
- }
- }
- public static RandNumber Rand = new RandNumber();
- //小素数表
- 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 };
- static int PrimeCount = PrimeTable.Length;
- //模幂运算,返回值 x=base^pow mod n
- static ulong PowMod(ulong Base, ulong pow, ulong n)
- {
- ulong c = 1;
- while (pow != 0)
- {
- while ((pow & 1) == 0)
- {
- pow >>= 1;
- Base = Base * Base % n;
- }
- pow--;
- c = Base * c % n;
- } return c;
- }
- //Rabin-Miller素数测试,通过测试返回1,否则返回0。
- //n是待测素数。
- //注意:通过测试并不一定就是素数,非素数通过测试的概率是1/4
- static int RabinMillerKnl(ref ulong n)
- {
- ulong b, m, j, v, i;
- m = n - 1;
- j = 0; //0、先计算出m、j,使得n-1=m*2^j,其中m是正奇数,j是非负整数
- while ((m & 1) == 0)
- {
- ++j;
- m >>= 1;
- } //1、随机取一个b,2<=b<n-1
- b = 2 + Rand.Random(n - 3); //2、计算v=b^m mod n
- v = PowMod(b, m, n); //3、如果v==1,通过测试
- if (v == 1)
- {
- return 1;
- } //4、令i=1
- i = 1; //5、如果v=n-1,通过测试
- while (v != n - 1)
- {
- //6、如果i==l,非素数,结束
- if (i == j)
- {
- return 0;
- } //7、v=v^2 mod n,i=i+1
- v = PowMod(v, 2, n);
- ++i; //8、循环到5
- } return 1;
- }
- //Rabin-Miller素数测试,循环调用核心loop次
- //全部通过返回1,否则返回0
- static int RabinMiller(ulong n, int loop)
- {
- //先用小素数筛选一次,提高效率
- for (int i = 0; i < PrimeCount; i++)
- {
- if (n % (ulong)PrimeTable[i] == 0)
- {
- return 0;
- }
- } //循环调用Rabin-Miller测试loop次,使得非素数通过测试的概率降为(1/4)^loop
- for (int i = 0; i < loop; i++)
- {
- if (RabinMillerKnl(ref n) == 0)
- {
- return 0;
- }
- } return 1;
- }
- /* 随机生成一个bits位(二进制位)的素数,最多32位 */
- static ulong RandomPrime(sbyte bits)
- {
- ulong @base;
- do
- {
- @base = (uint)1 << (bits - 1); //保证最高位是1
- @base += Rand.Random(@base); //再加上一个随机数
- @base |= 1; //保证最低位是1,即保证是奇数
- } while (RabinMiller(@base, 30) == 0); //进行拉宾-米勒测试30次
- return @base; //全部通过认为是素数
- }
- /* 欧几里得法求最大公约数 */
- ulong EuclidGcd(ref ulong p, ref ulong q)
- {
- ulong a = p > q ? p : q;
- ulong b = p < q ? p : q;
- ulong t;
- if (p == q)
- {
- return p; //两数相等,最大公约数就是本身
- }
- else
- {
- while (b != 0) //辗转相除法,gcd(a,b)=gcd(b,a-qb)
- {
- a = a % b;
- t = a;
- a = b;
- b = t;
- } return a;
- }
- }
- /* Stein法求最大公约数 */
- static ulong SteinGcd(ref ulong p, ref ulong q)
- {
- ulong a = p > q ? p : q;
- ulong b = p < q ? p : q;
- ulong t, r = 1;
- if (p == q)
- {
- return p; //两数相等,最大公约数就是本身
- }
- else
- {
- while (((a & 1) == 0) && ((b & 1) == 0))
- {
- r <<= 1; //a、b均为偶数时,gcd(a,b)=2*gcd(a/2,b/2)
- a >>= 1;
- b >>= 1;
- } if ((a & 1) == 0)
- {
- t = a; //如果a为偶数,交换a,b
- a = b;
- b = t;
- } do
- {
- while ((b & 1) == 0)
- {
- b >>= 1; //b为偶数,a为奇数时,gcd(b,a)=gcd(b/2,a)
- }
- if (b < a)
- {
- t = a; //如果b小于a,交换a,b
- a = b;
- b = t;
- } b = (b - a) >> 1; //b、a都是奇数,gcd(b,a)=gcd((b-a)/2,a)
- } while (b != 0);
- return r * a;
- }
- }
- /* 已知a、b,求x,满足a*x =1 (mod b) 相当于求解a*x-b*y=1的最小整数解 */
- static ulong Euclid(ref ulong a, ref ulong b)
- {
- ulong m, e, i, j, x, y;
- int xx, yy;
- m = b;
- e = a;
- x = 0;
- y = 1;
- xx = 1;
- yy = 1;
- while (e != 0)
- {
- i = m / e;
- j = m % e;
- m = e;
- e = j;
- j = y;
- y *= i;
- if (xx == yy)
- {
- if (x > y)
- {
- y = x - y;
- }
- else
- {
- y -= x;
- yy = 0;
- }
- }
- else
- {
- y += x;
- xx = 1 - xx;
- yy = 1 - yy;
- } x = j;
- } if (xx == 0)
- {
- x = b - x;
- } return x;
- }
- /* 随机产生一个RSA加密参数 */
- static RSA_PARAM RsaGetParam()
- {
- RSA_PARAM Rsa = new RSA_PARAM();
- ulong t;
- Rsa.p = RandomPrime(16); //随机生成两个素数
- Rsa.q = RandomPrime(16);
- Rsa.n = Rsa.p * Rsa.q;
- Rsa.f = (Rsa.p - 1) * (Rsa.q - 1);
- do
- {
- Rsa.e = Rand.Random(65536); //小于2^16,65536=2^16
- Rsa.e |= 1; //保证最低位是1,即保证是奇数,因f一定是偶数,要互素,只能是奇数
- } while (SteinGcd(ref Rsa.e, ref Rsa.f) != 1); Rsa.d = Euclid(ref Rsa.e, ref Rsa.f);
- Rsa.s = 0;
- t = Rsa.n >> 1;
- while (t != 0)
- {
- Rsa.s++; //s=log2(n)
- t >>= 1;
- } return Rsa;
- }
- /* 拉宾-米勒测试 */
- static void TestRM()
- {
- uint k = 0;
- Console.WriteLine(" - Rabin-Miller prime check./n");
- for (ulong i = 4197900001; i < 4198000000; i += 2)
- {
- if (RabinMiller(i, 30) != 0)
- {
- k++;
- Console.WriteLine(i);
- }
- Console.WriteLine("Total: " + k);
- }
- }
- static void Main(string[] args)
- {
- for (int x = 0; x < 1000; x++)
- {
- RSA_PARAM r = RsaGetParam();
- ulong[] test = new ulong[100];
- Random rand = new Random();
- for (int i = 0; i < test.Length; i++)
- test[i] = (ushort)rand.Next();
- //加密
- ulong[] enc = new ulong[test.Length];
- for (int i = 0; i < test.Length; i++)
- enc[i] = PowMod(test[i], r.e, r.n);
- //解密
- ulong[] dec = new ulong[test.Length];
- for (int i = 0; i < dec.Length; i++)
- dec[i] = PowMod(enc[i], r.d, r.n);
- for (int i = 0; i < dec.Length; i++)
- if (test[i] != dec[i])
- Console.WriteLine("false");
- Console.WriteLine("OK");
- }
- Console.ReadLine();
- }
- }
ras算法
最新推荐文章于 2023-04-23 17:08:18 发布