RSA是一套用了多年的加密系统,主要运用了数论中大数难以分解但是一个大的素数又相对比较容易判断的性质,关键理论可以查询 欧拉定理、大数运算、素数判定、快速指数模运算,扩展欧几里得算法。
代码如下:采用long long 类型使用小素数进行算法演示,未进行分段处理,所以单个字符加密结果一样。
- /*
- 此程序用于演示RSA加密原理
- winxos 2010-3-25*/
- #include <iostream>
- #include <cmath>
- #include <ctime>
- #include <string>
- #include <vector>
- #include <iomanip>
- using namespace std;
- typedef long long BIG;
- /*欧几里得扩展算法,计算乘法逆元*/
- BIG gcdx(BIG a,BIG b,BIG &x,BIG &y)
- {
- if (a == 1)
- {
- x = 1;
- y = 0;
- return a;
- }
- BIG r = gcdx(b,a%b,x,y);
- BIG t = x;
- x = y;
- y = t - a / b * y;
- return r;
- }
- /*快速指数模运算*/
- BIG powmod(BIG a,BIG b,BIG n)
- {
- if (b <= 0) return 1;
- if (b == 1) return a % n;
- BIG temp = powmod(a,b/2,n);
- temp = temp * temp % n;
- if (b % 2 == 1) //如果奇数要多乘一次
- {
- temp = temp * a % n;
- }
- return temp;
- }
- /*简易素数判定*/
- bool isprime(BIG n)
- {
- if (n == 2 || n == 3 || n == 5)
- return true;
- if (n < 2 || n % 2 == 0 ||
- n % 3 == 0 || n % 5 == 0)
- return false;
- for (BIG i = 5;i <= sqrt(static_cast<double>(n));i += 6)
- {
- if (n % i == 0 || n % (i+2) == 0)
- {
- return false;
- }
- }
- return true;
- }
- /*得到下一个素数*/
- BIG nextprime(BIG n)
- {
- BIG t = n;
- while (!isprime(++t));
- return t;
- }
- //RSA加密算法演示,采用BIG类型演示原理,当然实际要采用上数百位的素数合成n
- /*本函数用于加密一个基本元数据*/
- BIG unitRSAencrypt(BIG source_data_unit,BIG encrypt_key, BIG n_modkey)
- {
- return powmod(source_data_unit,encrypt_key,n_modkey);
- }
- /*本函数用于解密一个基本元数据*/
- BIG unitRSAdecrypt(BIG encrypted_data_unit,BIG decrypt_key, BIG n_modkey)
- {
- return powmod(encrypted_data_unit,decrypt_key,n_modkey);
- }
- /*
- 密钥生成参数选择:来自维基百科http://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95
- 素数p和q还要满足一定的要求,首先它们不能太靠近,此外p-1或q-1的因子不能太小,否则的话N也可以被很快地分解。
- 此外寻找�||数的算法不能给攻击者任何信息,这些�||数是怎样找到的,尤其产生随机数的软件必须非常好。要求是随机和不可预测。这两个要求并不相同。一个随机过程可能可以产生一个不相关的数的系列,但假如有人能够预测出(或部分地预测出)这个系列的话,那么它就已经不可靠了。比如有一些非常好的随机数算法,但它们都已经被发表,因此它们不能被使用,因为假如一个攻击者可以猜出p和q一半的位的话,那么他们就已经可以轻而易举地推算出另一半。此外密钥d必须足够大,年有人证明假如p大于q而小于q(这是一个很经常的情况)而d < N1/4/3,那么从N and e可以很有效地推算出d。此外e = 2永远不应该被使用。*/
- /*密钥创建函数,生成e, d, n*/
- void create_random_keys(BIG &encrypt_key,BIG &decrypt_key,BIG &n_modkeky)
- {
- srand(static_cast<unsigned int>(time(NULL)));
- BIG seed,p1,p2,phi,temp;
- seed = rand() % 10000 + 10000; // the range of the first prime
- p1 = nextprime(seed); // create the first prime.
- seed += rand() % 10000 + 10000; //
- p2 = nextprime(seed); // create the second prime, bigger than the first one.
- n_modkeky = p1 * p2; // set the n_modkey
- phi = (p1 - 1) * (p2 - 1); // calculator the function phi(n).
- do
- {
- seed = rand() % 100 + 3;
- encrypt_key = nextprime(seed); // create encrypt key, do not need very big
- } while (gcdx(encrypt_key,phi,seed,temp) != 1);
- gcdx(encrypt_key,phi,decrypt_key,temp); // get the decrypt key
- if (decrypt_key < 0) //if decrypt_key is blow zero, need to convert it to the positive filed.
- {
- decrypt_key += phi;
- }
- }
- void print(vector<BIG> data)
- {
- for (size_t i = 0;i < data.size();i++)
- {
- cout<<setw(20)<<data[i];
- }
- cout<<endl;
- }
- vector<BIG> predeal_string(string msg)
- {
- return vector<BIG> (msg.begin(),msg.end());
- }
- string recover_string(vector<BIG> c_msg)
- {
- string str_ret = "";
- for (size_t si = 0;si < c_msg.size();si++)
- {
- str_ret += static_cast<char> (c_msg[si]);
- }
- return str_ret;
- }
- vector<BIG> RSAengypt(string s,BIG e,BIG n)
- {
- vector<BIG> s_ret = predeal_string(s);
- for (size_t i = 0;i < s_ret.size();i++)
- {
- s_ret[i] = unitRSAencrypt(s_ret[i],e,n);
- }
- return s_ret;
- }
- string RSAdegypt(vector<BIG> s,BIG d,BIG n)
- {
- for (size_t i = 0;i < s.size();i++)
- {
- s[i] = unitRSAencrypt(s[i],d,n);
- }
- string str_ret = recover_string(s);
- return str_ret;
- }
- int main()
- {
- BIG e,d,n;
- string s = "hello world! how are you been these days? ~!@#$%^&*()_+|`1234567890-=;',./";
- cout<<"原始密文:\n"<<s<<endl;
- create_random_keys(e,d,n);
- cout<<"公钥:"<<e<<", "<<n<<" 密钥:"<<d<<", "<<n<<endl;
- vector<BIG> t = RSAengypt(s,e,n);
- cout<<"加密后数据内容:"<<endl;
- print(t);
- string s2 = RSAdegypt(t,d,n);
- cout<<"解密密文:\n"<<s2<<endl;
- return 0;
- }
-----------运行结果--------------------
原始密文:
hello world! how are you been these days? ~!@#$%^&*()_+|`1234567890-=;',./
公钥:89, 481406479 密钥:275835689, 481406479
加密后数据内容:
26043171 327399490 230621758 230621758
231959055 260178933 414628633 231959055
164067963 230621758 205590903 203384337
260178933 26043171 231959055 414628633
260178933 80201433 164067963 327399490
260178933 140426015 231959055 407828208
260178933 19332027 327399490 327399490
481256803 260178933 239604623 26043171
327399490 139578934 327399490 260178933
205590903 80201433 140426015 139578934
313413852 260178933 99061361 203384337
207195739 109971008 274464649 162447453
140289974 449722463 404921537 55375979
467769239 244872881 23021321 378874344
23104759 189537375 231354613 435450394
478134577 65343791 416929531 258498836
359182479 14267219 98398916 262255901
144277209 64215557 32213092 114061293
7902659 109199965
解密密文:
hello world! how are you been these days? ~!@#$%^&*()_+|`1234567890-=;',./
请按任意键继续. . .
2010-3-25