(一)实验要求:
1、编写程序构造一公钥密码算法(RSA)的密钥;
2、编写程序生成大素数;
3、编程实现一公钥密码算法。
(二)实验原理
1.首先是密钥对的生成:
(1)选取两个大素数p和q
(2)计算乘积n=p*q,Φ(n)=(p-1)(q-1),其中Φ(n)为n的欧拉函数
(3)随机选取整数e(1<e<Φ(n))作为公钥d,要求满足e与Φ(n)的最大公约数为1,即两者互素
(4)用Euclid扩展算法计算私钥d,已满足d * e ≡ 1 (mod Φ(n)),
即d ≡ e^(-1) (mod Φ(n))。则e与n是公钥,d是私钥
注意:e与n应公开,两个素数p和q不再需要,可销毁,但绝不可泄露。
2.加密过程:C=M^e mod N
3.解密过程:M=C^d mod N
(三)主要代码
1.生成大素数(生成大素数,素性检测)
因为没有想到如何实现生成并使用大素数,p,q只使用了1000以内随机生成的素数
(1)生成大素数
int ProducePrimeNumber(int prime[])//生成1000以内素数
{
int c = 0, vis[1001];
memset(vis, 0, sizeof(vis));
for (int i = 2; i <= 1000; i++)if (!vis[i])
{
prime[c++] = i;
for (int j = i * i; j <= 1000; j += i)
vis[j] = 1;
}
return c;
}
(2)素性测试
bool Miller_Rabin(ll n) //Miller-Rabin素性测试算法
{
ll r = 0;
ll z = 0;
ll m = 0;
ll s = 0;
m = n - 1;
if (n < 2)
return false;
else if (n == 2)
return true;
while (m % 2 == 0) {
m /= 2;
s = s + 1;
}
srand(time(NULL));
ll b = rand() % (n - 2) + 2;
/*for(int i = 0;i < m - 1;i++)
z1 = b*b;
z1 = ((z1 % n) + n)% n;*/
z = Power_mul(b, m, 1, n);
if (z == 1 || z == n - 1)
return true;
else
{
while (1) {
if (r == (s - 1))
return false;
else
{
r = r + 1;
z = Power_mul(z, 2, 1, n);
if (z == (n - 1))
return true;
}
}
}
}
void MR()
{
ll N;
bool result;
cout << "请输入N:";
cin >> N;
result = Miller_Rabin(N);
if (result)
cout << N << "是素数" << endl;
else
cout << "不是素数" << endl;
}
2. 密钥产生
void RSA_Initialize()
{
//取出1000内素数保存在prime[]数组中
int prime[5000];
int count_Prime = ProducePrimeNumber(prime);
//随机取两个素数p,q
srand((unsigned)time(NULL));
int ranNum1 = rand() % count_Prime;
int ranNum2 = rand() % count_Prime;
int p = prime[ranNum1], q = prime[ranNum2];
cout << "大素数 : p = " << p << " q = " << q << endl;
n = p * q;
int On = (p - 1)*(q - 1);
//用欧几里德扩展算法求e,d
for (int j = 2; j < On; j += 1331)
{
d = ExtendEculid(On, j, 0, 1);
if (gcd(On,j) == 1 & d>0)
{
e = j;
break;
}
}
cout << "选择e = " << e << " d = " << d << endl;
cout << "计算d = " << d << endl;
}
3. 广义欧几里得计算乘法逆元
//记gcd(a,b)表示非负整数a,b的最大公因数,那么:gcd(a,b)=gcd(b,a%b)
ll gcd(ll a, ll b)
{
if (a < b)
{
ll temp = b;
b = a;
a = temp;
}
if (a%b == 0)
return b;
else
return gcd(b, a%b);
}
//gcd(n,u)=an+bu;
ll ExtendEculid(ll n1, ll n2, ll b1, ll b2)
{
ll q, r;
q = n1 / n2;
r = n1 - q*n2;
if (r != 0)
{
ll temp = b1 - q*b2;
ExtendEculid(n2, r, b2, temp);
}
if (n2 == 1)
return b2;
}
//调用过程
void Inverse_element()
{
cout << "u * v == 1(mod n)\n";
cout << "";
ll u, n, t;
cout << "请输入u:";
cin >> u;
cout << "请输入n:";
cin >> n;
if (gcd(n, u) != 1)
cout << "两个数不互素,没有乘法逆元!" << endl << endl;
else
{
t = ExtendEculid(n, u, 0, 1);
if (t < 0)
t += n;
cout << u << "mod" << n << "的逆元为" << t << endl;
}
}
4. 模n的大数幂乘的快速算法
ll Power_mul(ll a,ll b,ll c,ll n)
{
//初始a=x,b=r,c=1
while (b != 0)
{
while (b % 2 == 0)
{
b /= 2;
a = (a * a) % n;
}
b -= 1;
c = (c * a) % n;
}
return c;
}
void PM()
{
cout << "x^r mod n" << endl;
ll x, r, n;
cout << "请输入x:";
cin >> x;
cout << "请输入r:";
cin >> r;
cout << "请输入n:";
cin >> n;
ll out = Power_mul(x, r, 1, n);
cout << x << "^" << r << " mod " << n << " = " << out << endl;
}
5. RSA 加密
void RSA_Encrypt()
{
int p,q;
cout << endl;
cout << "公钥(n, e) : n = " << n << " e = " << e << endl;
cout << "私钥(d, p, q) : d = " << d << " p = " << p << " q = " << q<< endl;
int i = 0;
for (i = 0; i < 100; i++)
Ciphertext[i] = Power_mul(Plaintext[i], e, 1, n);
cout << endl;
cout << "用公钥(n, e)加密出的密文如下:" ;
for (i = 0; i < 100; i++)
cout << Ciphertext[i] << " ";
cout << endl;
}
6. RSA 解密
void RSA_Decrypt()
{
int i = 0;
for (i = 0; i < 100; i++)
Plaintext_C[i] = Power_mul(Ciphertext[i], d, 1, n);
cout << endl;
cout << "密文为:" ;
for (i = 0; i < 100; i++)
cout << Ciphertext[i] << " ";
cout << endl;
cout << endl;
cout << "用私钥(n ,e)解密出的明文如下:" ;
for (i = 0; i < 100; i++)
printf("%c", Plaintext_C[i]);
cout << endl;
}
7主函数
int main()
{
Initialize();
while (!e)
RSA_Initialize();
RSA_Encrypt();
RSA_Decrypt();
getchar();
return 0;
}
实验结果
1.素数生成
图1 生成的大素数
2.密钥生成
图2 生成的密钥
3.RSA加密
图3 RSA加密的明文
图4 RSA加密的密文
4.RSA解密
图5 RSA解密的明文和密文
P.S.大素数的生成即首先随机生成一个大奇数并检测它是否为一个素数,迭代直到生成一个符合要求的大素数。大素数的检测使用的是基于大整数运算的Miller-Rabin算法。