⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 program.cs

📁 RSA ENCODE and DECODE C#
💻 CS
字号:
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics; 

namespace RSAceshi
{
    //class Program
    //{
    //    static void Main(string[] args)
    //    {
    //    }
    //}

    namespace rsatest 
{ 

/* 
??? RSA算法 
? 1978年就出现了这种算法,它是第一个既能用于数据加密也能用于数字签名的算法。 
??? 它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, 
??? AdiShamir 和Leonard Adleman。但RSA的安全性一直未能得到理论上的证明。 

? RSA的安全性依赖于大数难于分解这一特点。公钥和私钥都是两个大素数(大于100个 
??? 十进制位)的函数。据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大 
??? 素数的积。 

? 密钥对的产生。选择两个大素数,p 和q 。计算:n = p * q 然后随机选择加密密钥e, 
??? 要求 e 和 ( p - 1 ) * ( q - 1 )互质。最后,利用Euclid 算法计算解密密钥d, 满足 
??? e * d = 1 ( mod ( p - 1 ) * ( q - 1 ) )其中n和d也要互质。数e和n是公钥,d是私钥。 
??? 两个素数p和q不再需要,应该丢弃,不要让任何人知道。加密信息 m(二进制表示)时, 
??? 首先把m分成等长数据块 m1 ,m2,..., mi ,块长s,其中 2^s <= n, s 尽可能的大。对应 
??? 的密文是: 
ci = mi^e ( mod n ) .................( a ) 
解密时作如下计算: 
mi = ci^d ( mod n ) .................( b ) 

? RSA 可用于数字签名,方案是用 ( a ) 式签名, ( b )式验证。具体操作时考虑到安全性 
??? 和 m信息量较大等因素,一般是先作HASH 运算。RSA 的安全性。RSA的安全性依赖于大数 
??? 分解,但是否等同于大数分解一直未能得到理论上的证明,因为没有证明破解RSA就一定 
??? 需要作大数分解。假设存在一种无须分解大数的算法,那它肯定可以修改成为大数分解算法。 
??? 目前,RSA的一些变种算法已被证明等价于大数分解。不管怎样,分解n是最显然的攻击方法。 
??? 现在,人们已能分解140多个十进制位的大素数。因此,模数n必须选大一些,因具体适用情况而定。 
??? 
??? 由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论是软件还是硬件实现。 
??? 速度一直是RSA的缺陷。一般来说只用于少量数据加密。 
*/    
   public struct RSA_PARAM 
   { 
        public UInt64 p, q;  //两个素数,不参与加密解密运算 
 public UInt64 f;  //f=(p-1)*(q-1),不参与加密解密运算 
 public UInt64 n, e; //公匙,n=p*q,gcd(e,f)=1 
 public UInt64 d; //私匙,e*d=1 (mod f),gcd(n,d)=1 
 public UInt64 s; //块长,满足2^s<=n的最大的s,即log2(n) 
 }; 

 class Program 
 { 
 //小素数表 
 #region Prime Table 
 readonly static long[] g_PrimeTable = 
 { 
 3, 
 5, 
 7, 
 11, 
 13, 
 17, 
 19, 
 23, 
 29, 
 31, 
 37, 
 41, 
  43, 
  47, 
 53, 
 59, 
  61, 
 67, 
 71, 
  73, 
  79, 
  83, 
  89, 
  97 
  }; 
 #endregion 

  readonly long g_PrimeCount = g_PrimeTable.Length; 
  const UInt64 multiplier = 12747293821; 
 const UInt64 adder = 1343545677842234541; 

 //随机数类 
  public class RandNumber 
 { 
  /* */ 
  private UInt64 randSeed;/* */ 
  public RandNumber():this(0) { } 

  public RandNumber(UInt64 s) 
  { 
  if (0 == s)//(!s) 
  { 
   randSeed = (UInt64)new Random().Next();//time(NULL); 
 } 
  else 
 { 
  randSeed = s; 
 } 
  } 
  
  /* */ 
  public UInt64 Random(UInt64 n) 
 { 
  randSeed = multiplier * randSeed + adder; 
  return randSeed % n; 
  } 
 } 

 static RandNumber g_Rnd = new RandNumber(); 

 /* 模乘运算,返回值 x=a*b mod n */ 
 UInt64 MulMod(UInt64 a, UInt64 b, UInt64 n) 
  { 
 return a * b % n; 
  } 

  /* 模幂运算,返回值 x=base^pow mod n */ 
 UInt64 PowMod(UInt64 bas, UInt64 pow, UInt64 n) 
 { 
 UInt64 a = bas, b = pow, c = 1; 
 while (b != 0)  // (b) 
  { 
  while (1 != (b & 1)) // !(b&1) 
 { 
  b >>= 1;  //a=a * a % n;??? //函数看起来可以处理64位的整数,但由于这里a*a在a>=2^32时已经造成了溢出,因此实际处理范围没有64位 
  a = MulMod(a, a, n); 
  } b--;  //c=a * c % n;??????? //这里也会溢出,若把64位整数拆为两个32位整数不知是否可以解决这个问题。 
 c = MulMod(a, c, n); 
 } return c; 
  } 

  /* 
  Rabin-Miller素数测试,通过测试返回1,否则返回0。 
 n是待测素数。 
 注意:通过测试并不一定就是素数,非素数通过测试的概率是1/4 
 */ 
  long RabinMillerKnl(UInt64 n) 
 { 
  UInt64  b, m, j, v, i; 
  m = n - 1; 
  j = 0;  //0、先计算出m、j,使得n-1=m*2^j,其中m是正奇数,j是非负整数 
  while (1 != (m&1))  // (!(m & 1)) 
 { 
  ++j; 
  m >>= 1; 
   }  //1、随机取一个b,2<=b b = 2 + g_Rnd.Random(n - 3); //2、计算v=b^m mod n 
   b = 6;
 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 
  */ 
 long RabinMiller(UInt64 n, long loop) 
 { 
 //先用小素数筛选一次,提高效率 
  for (long i = 0; i < g_PrimeCount; i++) 
 { 
  if ((n % unchecked((ulong)g_PrimeTable[i])) == 0) 
  { 
  return 0; 
  } 
  } 

 //循环调用Rabin-Miller测试loop次,使得非素数通过测试的概率降为(1/4)^loop 
 for (long i = 0; i < loop; i++) 
 { 
 if (0 == RabinMillerKnl(n)) //(! ...) 
  { 
  return 0; 
 } 
  } return 1; 
  } 
  /* 随机生成一个bits位(二进制位)的素数,最多32位 */ 
 UInt64 RandomPrime(char bits) 
  { 
  UInt64 bas; 
 do 
  { 
  bas = (UInt32)1 << (bits - 1);  //保证最高位是1 
 bas += g_Rnd.Random(bas);  //再加上一个随机数 
  bas |= 1;  //保证最低位是1,即保证是奇数 
 } while (0 == RabinMiller(bas, 30)); // (!RabinMiller(bas, 30))??? //进行拉宾-米勒测试30次 
 return bas;  //全部通过认为是素数 
 } 

 /* 欧几里得法求最大公约数 */ 
  UInt64 EuclidGcd(UInt64 p, UInt64 q) 
 { 
  UInt64 a = p > q ? p : q; 
  UInt64 b = p < q ? p : q; 
  UInt64 t; 
 if (p == q) 
 { 
  return p; //两数相等,最大公约数就是本身 
 } 
  else 
  { 
  while (0 != b) //(b)  //辗转相除法,gcd(a,b)=gcd(b,a-qb) 
  { 
  a = a % b; 
 t = a; 
 a = b; 
  b = t; 
  } return a; 
  } 
 } 
  /* Stein法求最大公约数 */ 
  UInt64 SteinGcd( UInt64 p, UInt64 q) 
 { 
  UInt64 a = p > q ? p : q; 
  UInt64 b = p < q ? p : q; 
  UInt64 t, r = 1; 
 if (p == q) 
  { 
 return p;  //两数相等,最大公约数就是本身 
 } 
  else 
 { 
  //while ((!(a & 1)) && (!(b & 1))) 
  while ((0 ==(a & 1)) && (0 ==(b & 1))) 
 { 
  r <<= 1;  //a、b均为偶数时,gcd(a,b)=2*gcd(a/2,b/2) 
  a >>= 1; 
 b >>= 1; 
 } 
 if (0 == (a&1))//(!(a & 1)) 
 { 
  t = a; //如果a为偶数,交换a,b 
 a = b; 
  b = t; 
  } 
        do 
  {  
        while (0 == (b & 1))//(!(b & 1)) 
  { 
  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); //(b); 
  return r * a; 
 } 
  } 
 /* 
 已知a、b,求x,满足a*x =1 (mod b) 
 相当于求解a*x-b*y=1的最小整数解 
 */ 
  UInt64 Euclid(UInt64 a, UInt64 b) 
  { 
 UInt64 m, e, i, j, x, y; 
  long xx, yy; 
  m = b; 
 e = a; 
  x = 0; 
  y = 1; 
  xx = 1; 
  yy = 1; 
 while (0 != e)//(e) 
 { 
  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加密参数 */ 
 RSA_PARAM RsaGetParam() 
 { 
 RSA_PARAM Rsa =new RSA_PARAM(); 
  UInt64 t; 
  Rsa.p = RandomPrime((char)16);  //随机生成两个素数 
  Rsa.q = RandomPrime((char)16); 
  Rsa.n = Rsa.p * Rsa.q; 
  Rsa.f = (Rsa.p - 1) * (Rsa.q - 1); 
 do 
  { 
  Rsa.e = g_Rnd.Random(65536);  //小于2^16,65536=2^16 
  Rsa.e |= 1;  //保证最低位是1,即保证是奇数,因f一定是偶数,要互素,只能是奇数 
 } while (SteinGcd(Rsa.e, Rsa.f) != 1); Rsa.d = Euclid(Rsa.e, Rsa.f); 
  Rsa.s = 0; 
  t = Rsa.n >> 1; 
 while (0 != t)//(t) 
  { 
  Rsa.s++;  //s=log2(n) 
 t >>= 1; 
  } return Rsa; 
 } 

  /* 拉宾-米勒测试 */ 
  void TestRM() 
  { 
  UInt32 k = 0; 
 Console.Write(" - Rabin-Miller prime check.\n\n"); 
 for (UInt64 i = 4197900001; i < 4198000000; i += 2) 
  { 
 if (0 != RabinMiller(i, 30)) 
 { 
 k++; 
  Console.WriteLine(i); 
  } 
  } 
  Console.WriteLine("Total: " + k); 
 } 

 /* RSA加密解密 */ 
  void TestRSA() 
 { 
 RSA_PARAM r; 
 string pSrc = "abcdefghijklmnopqrstuvwxyz"; 
  UInt32 n = (uint)pSrc.Length; 
 //unsigned char  *q, pDec[n]; 
  byte[] pDec = new byte[n]; 
 UInt64[] pEnc = new UInt64[n]; 
 r = RsaGetParam(); 
 Console.WriteLine("p=" + r.p); 
 Console.WriteLine("q=" + r.q); 
 Console.WriteLine("f=(p-1)*(q-1)=" + r.f); 
 Console.WriteLine("n=p*q=" + r.n); 
  Console.WriteLine("e=" + r.e); 
 Console.WriteLine("d=" + r.d); 
 Console.WriteLine("s=" + r.s); 
 Console.WriteLine("Source:" + pSrc); 
 //q= (unsigned char *)pSrc; 
 Console.Write("Encode:"); 
 for (int i = 0; i < (int)n; i++) 
 { 
 //pEnc[i]=PowMod(q[i], r.e, r.n); 
  pEnc[i] = PowMod((ulong)pSrc[i], r.e, r.n); 
 Console.Write(pEnc[i].ToString() + " "); 
  } Console.WriteLine(""); 
 Console.Write("Decode:"); 
 for (int i = 0; i < (int)n; i++) 
 { 
 pDec[i] = (byte)PowMod((ulong)pEnc[i], r.d, r.n); 
 Console.Write((UInt32)pDec[i] + " "); 
  } Console.WriteLine(""); 
 Console.WriteLine(Encoding.Default.GetString(pDec)); 
 }/* */ 


 static void Main(string[] args) 
  { 
 new Program().TestRSA();
 Console.ReadLine();

  } 
  } 
} 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -