1 //RSA密码 2 /*理解算法最重要,最好自己动手实现试试看,可以使用MFC写一个简单的交互界面*/ 3 4 #include <iostream> 5 #include <cstdlib> 6 #include <ctime> 7 #include <cstring> 8 using namespace std; 9 //RSA算法所需参数 10 typedef struct RSA_PARAM_Tag 11 { 12 unsigned __int64 p, q; //两个素数,不参与加密解密运算 13 unsigned __int64 f; //f=(p-1)*(q-1),不参与加密解密运算 14 unsigned __int64 n, e; //公匙,n=p*q,gcd(e,f)=1 15 unsigned __int64 d; //私匙,e*d=1 (mod f),gcd(n,d)=1 16 unsigned __int64 s; //块长,满足2^s<=n的最大的s,即log2(n) 17 } RSA_PARAM; 18 //小素数表 19 const static long g_PrimeTable[]= 20 { 21 3,5,7,11,13,17,19,23,29,31,37,41,43, 22 47,53,59,61,67,71,73,79,83,89,97 23 }; 24 const static long g_PrimeCount=sizeof(g_PrimeTable) / sizeof(long);const unsigned __int64 multiplier=12747293821; 25 const unsigned __int64 adder=1343545677842234541;//随机数类 26 class RandNumber 27 { 28 private: 29 unsigned __int64 randSeed; 30 public: 31 RandNumber(unsigned __int64 s=0); 32 unsigned __int64 Random(unsigned __int64 n); 33 }; 34 RandNumber::RandNumber(unsigned __int64 s) 35 { 36 if(!s) 37 { 38 randSeed= (unsigned __int64)time(NULL); 39 } 40 else 41 { 42 randSeed=s; 43 } 44 } 45 unsigned __int64 RandNumber::Random(unsigned __int64 n) 46 { 47 randSeed=multiplier * randSeed + adder; 48 return randSeed % n; 49 }static RandNumber g_Rnd; 50 51 //模乘运算,返回值 x=a*b mod n 52 inline unsigned __int64 MulMod(unsigned __int64 a, unsigned __int64 b, unsigned __int64 n) 53 { 54 return a * b % n; 55 } 56 57 //模幂运算,返回值 x=base^pow mod n 58 unsigned __int64 PowMod(unsigned __int64 &base, unsigned __int64 &pow, unsigned __int64 &n) 59 { 60 unsigned __int64 a=base, b=pow, c=1; 61 while(b) 62 { 63 while(!(b & 1)) 64 { 65 b>>=1; //a=a * a % n; //函数看起来可以处理64位的整数,但由于这里a*a在a>=2^32时已经造成了溢出,因此实际处理范围没有64位 66 a=MulMod(a, a, n); 67 } b--; //c=a * c % n; //这里也会溢出,若把64位整数拆为两个32位整数不知是否可以解决这个问题。 68 c=MulMod(a, c, n); 69 } return c; 70 } 71 /* 72 Rabin-Miller素数测试,通过测试返回1,否则返回0。 73 n是待测素数。 74 */ 75 long RabinMillerKnl(unsigned __int64 &n) 76 { 77 unsigned __int64 b, m, j, v, i; 78 m=n - 1; 79 j=0; //计算出m、j,使得n-1=m*2^j,其中m是正奇数,j是非负整数 80 while(!(m & 1)) 81 { 82 ++j; 83 m>>=1; 84 } //随机取一个b,2<=b<n-1 85 b=2 + g_Rnd.Random(n - 3); //算v=b^m mod n 86 v=PowMod(b, m, n); //如果v==1,通过测试 87 if(v == 1) 88 { 89 return 1; 90 } //令i=1 91 i=1; //v=n-1,通过测试 92 while(v != n - 1) 93 { 94 //i==l,非素数,结束 95 if(i == j) 96 { 97 return 0; 98 } //v=v^2 mod n,i=i+1 99 unsigned long long xxx; 100 int xxxx = 2; 101 xxx = xxxx; 102 v = PowMod(v, xxx, n); 103 ++i; //循环到5 104 } return 1; 105 } 106 /* 107 Rabin-Miller素数测试,循环调用核心loop次 108 全部通过返回1,否则返回0 109 */ 110 long RabinMiller(unsigned __int64 &n, long loop) 111 { 112 //用小素数筛选一次,提高效率 113 for(long i=0; i < g_PrimeCount; i++) 114 { 115 if(n % g_PrimeTable[i] == 0) 116 { 117 return 0; 118 } 119 } //循环调用Rabin-Miller测试loop次,使得非素数通过测试的概率降为(1/4)^loop 120 for(long i=0; i < loop; i++) 121 { 122 if(!RabinMillerKnl(n)) 123 { 124 return 0; 125 } 126 } return 1; 127 }/* 128 随机生成一个bits位(二进制位)的素数,最多32位 129 */ 130 unsigned __int64 RandomPrime(char bits) 131 { 132 unsigned __int64 base; 133 do 134 { 135 base= (unsigned long)1 << (bits - 1); //保证最高位是1 136 base+=g_Rnd.Random(base); //再加上一个随机数 137 base|=1; //保证最低位是1,即保证是奇数 138 } while(!RabinMiller(base, 30)); //进行拉宾-米勒测试30次 139 return base; //全部通过认为是素数 140 }/* 141 欧几里得法求最大公约数 142 */ 143 unsigned __int64 EuclidGcd(unsigned __int64 &p, unsigned __int64 &q) 144 { 145 unsigned __int64 a=p > q ? p : q; 146 unsigned __int64 b=p < q ? p : q; 147 unsigned __int64 t; 148 if(p == q) 149 { 150 return p; //两数相等,最大公约数就是本身 151 } 152 else 153 { 154 while(b) //辗转相除法,gcd(a,b)=gcd(b,a-qb) 155 { 156 a=a % b; 157 t=a; 158 a=b; 159 b=t; 160 } return a; 161 } 162 }/* 163 Stein法求最大公约数 164 */ 165 unsigned __int64 SteinGcd(unsigned __int64 &p, unsigned __int64 &q) 166 { 167 unsigned __int64 a=p > q ? p : q; 168 unsigned __int64 b=p < q ? p : q; 169 unsigned __int64 t, r=1; 170 if(p == q) 171 { 172 return p; //两数相等,最大公约数就是本身 173 } 174 else 175 { 176 while((!(a & 1)) && (!(b & 1))) 177 { 178 r<<=1; //a、b为偶数时,gcd(a,b)=2*gcd(a/2,b/2) 179 a>>=1; 180 b>>=1; 181 } if(!(a & 1)) 182 { 183 t=a; //a为偶数,交换a,b 184 a=b; 185 b=t; 186 } do 187 { 188 while(!(b & 1)) 189 { 190 b>>=1; //b为偶数,a为奇数时,gcd(b,a)=gcd(b/2,a) 191 } if(b < a) 192 { 193 t=a; //b小于a,交换a,b 194 a=b; 195 b=t; 196 } b=(b - a) >> 1; //b、a都是奇数,gcd(b,a)=gcd((b-a)/2,a) 197 } while(b); 198 return r * a; 199 } 200 }/* 201 已知a、b,求x,满足a*x =1 (mod b) 202 相当于求解a*x-b*y=1的最小整数解 203 */ 204 unsigned __int64 Euclid(unsigned __int64 &a, unsigned __int64 &b) 205 { 206 unsigned __int64 m, e, i, j, x, y; 207 long xx, yy; 208 m=b;e=a;x=0;y=1;xx=1;yy=1; 209 while(e) 210 { 211 i=m / e;j=m % e; 212 m=e;e=j;j=y;y*=i; 213 if(xx == yy) 214 { 215 if(x > y) 216 y=x - y; 217 else{ 218 y-=x; 219 yy=0; 220 } 221 } 222 else 223 { 224 y+=x; 225 xx=1 - xx; 226 yy=1 - yy; 227 } x=j; 228 } 229 if(xx == 0) 230 x=b - x; 231 return x; 232 }/* 233 随机产生一个RSA加密参数 234 */ 235 RSA_PARAM RsaGetParam(void) 236 { 237 RSA_PARAM Rsa={ 0 }; 238 unsigned __int64 t; 239 Rsa.p=RandomPrime(16); //随机生成两个素数 240 Rsa.q=RandomPrime(16); 241 Rsa.n=Rsa.p * Rsa.q; 242 Rsa.f=(Rsa.p - 1) * (Rsa.q - 1); 243 do 244 { 245 Rsa.e=g_Rnd.Random(65536); //小于2^16,65536=2^16 246 Rsa.e|=1; //保证最低位是1,即保证是奇数,因f一定是偶数,要互素,只能是奇数 247 } while(SteinGcd(Rsa.e, Rsa.f) != 1); 248 Rsa.d=Euclid(Rsa.e, Rsa.f); 249 Rsa.s=0; 250 t=Rsa.n >> 1; 251 while(t) 252 { 253 Rsa.s++; //s=log2(n) 254 t>>=1; 255 } 256 return Rsa; 257 }/* 258 拉宾-米勒测试 259 */ 260 void TestRM(void) 261 { 262 unsigned long k=0; 263 cout << "拉宾-米勒测试\n" << endl; 264 for(unsigned __int64 i=4197900001; i < 4198000000; i+=2) 265 { 266 if(RabinMiller(i, 30)) 267 { 268 k++; 269 cout << i << endl; 270 } 271 } cout << "Total: " << k << endl; 272 }/* 273 RSA加密解密 274 */ 275 void TestRSA(void) 276 { 277 cout << "请输入待加密的内容(支持字母、汉字、以及其他符号和下划线):\n"; 278 RSA_PARAM r; 279 string in_1; 280 //char pSrc[123]; 281 /* char *pSrc; 282 getline(cin, in_1); 283 getline(cin, in_1);*/ 284 // char pSrc[100]; 285 fflush(stdin); 286 char pSrc[100]; 287 scanf("%[^\n]s",pSrc); 288 //scanf("%[^\n]s",pSrc); 289 //puts(pSrc); 290 //fflush(stdin); 291 // pSrc = const_cast<char *>(in_1.data()); 292 293 const unsigned long n = sizeof(pSrc); 294 unsigned char *q, pDec[n]; 295 unsigned __int64 pEnc[n]; 296 r = RsaGetParam(); 297 cout << "---------------------------------\n"; 298 cout << "p=" << r.p << endl; 299 cout << "q=" << r.q << endl; 300 cout << "f=(p-1)*(q-1)=" << r.f << endl; 301 cout << "n=p*q=" << r.n << endl; 302 cout << "e=" << r.e << endl; 303 cout << "d=" << r.d << endl; 304 cout << "s=" << r.s << endl; 305 cout << "---------------------------------\n"; 306 307 q = (unsigned char*)pSrc; 308 //cout<<q<<"&&&&&\n";//================= 309 cout << "Encode:\n"; 310 for (unsigned long i = 0; i < n; i++) 311 { 312 unsigned long long xxx; 313 int xxxx = q[i]; 314 xxx = xxxx; 315 pEnc[i] = PowMod(xxx, r.e, r.n); 316 cout << hex << pEnc[i] << " "; 317 } 318 cout << "\n\n"; 319 320 cout << "Decode:\n"; 321 for (unsigned long i = 0; i < n; i++) 322 { 323 pDec[i] = PowMod(pEnc[i], r.d, r.n); 324 cout << hex << (unsigned long)pDec[i] << " "; 325 } 326 cout << "\n\n"; 327 328 cout << "解密后的文档:\n"; 329 cout << (char *)pDec << endl; 330 }/* */ 331 int main(void) 332 { 333 cout << "Start~!\n\n"; 334 char inorder; 335 /*cin >> inorder; 336 fflush(stdin); 337 if (inorder == '1') 338 TestRSA(); 339 // TestRSA();*/ 340 cout << "如果想进行下一个加密过程,请输入n键,退出请输入q键:\n\n"; 341 while (cin >> inorder && inorder == 'n') 342 { 343 system("cls"); 344 TestRSA(); 345 cout << "如果想进行下一个加密过程,请输入n键,退出请输入q键:\n\n"; 346 } 347 if (inorder == 'q') 348 cout << "谢谢使用~!下次再见 > . < ~\n"; 349 return 0; 350 }