原文链接:http://blog.csdn.net/ddk3001/article/details/54585854
1 目的说明
本文用两个简单的例子说明RSA算法过程:
1、如何计算公钥和私钥?
2、如何对消息进行加密和解密?
这两个例子都可以用计算器进行验证,目的是了解RSA算法的基本过程。
本文不对RSA算法的严格描述和证明做深入解释,有兴趣的读者请看参考链接。
最后给出了一个实现RSA算法的C语言程序。
参考:
http://www.cnblogs.com/hykun/p/RSA.html
http://blog.csdn.net/sunmenggmail/article/details/11994013
http://www.360doc.com/content/14/0517/19/7385274_378568902.shtml
2 计算公钥和私钥
RSA算法:
1、选择两个质数p和q,计算:
- N = p * q
- r = (p-1)(q-1)
2、计算模反元素:
模反元素:如果两个正整数e和r互质,那么一定能找到整数d,使得 ed%r=1 ,即 (ed-1)%r=0,则称d为e的模反元素。
- 随机选择一个整数e : 1 < e < r,且e与r互质
- 计算e关于模r的模反元素d : (ed-1)/r=k 或 ed-kr=1(k为任意正整数)
- 将e和r的值代入,得到一个二元一次方程。对它求解,求得一组解(d和k)即可。
3、把 p 和 q 扔掉
4、公钥是 (N,e),私钥是 (N,d)
【例1】
1、p = 3 , q = 11
- N = pq = 33
- r = (p-1)(q-1) = (3-1)(11-1) = 20
2、计算模反元素:
- r=20,选择e=3,得到二元一次方程:3d-20k=1
- 获得一组解:d=7,k=1
3、因此,公钥是 (N, e) = (33, 3),私钥是 (N, d) = (33, 7)。
【例2】
1、p = 13 , q = 5
- N = pq = 65
- r = (p-1)(q-1) = (13-1)(5-1) = 48
2、计算模反元素:
- r=48,选择e=5,得到二元一次方程:5d-48k=1
- 获得一组解:d=29,k=3
3、因此,公钥是 (N, e) = (65, 5),私钥是 (N, d) = (65, 29)。
3 加密消息
RSA算法:
- 公钥:(N,e)
- 明文转换:
- 将消息m转换为一个整数n ( n < N )
- 如果消息很长,则将消息分成多段,将每段转换为一个整数n ( n < N )
- 加密公式:c = (n^e)%N
明文转换的例子:
将明文中的每一个字转换为这个字的Unicode码,然后将这些Unicode码连在一起组成一个数字n。
反之,将n划分为Unicode码串,每个Unicode码还原为一个字,这样就得到了原来的明文。
【例1】
- 公钥: (N, e) = (33, 3)
- 明文:消息m转换为整数24
- 计算:c = (24^3)%33 = 30
- 因此:24被加密为30
【例2】
- 公钥: (N, e) = (65, 5)
- 明文:消息m转换为整数3
- 计算:c = (3^5)%65 = 48
- 因此:3被加密为48
4 解密消息
RSA算法:
- 私钥: (N,e)
- 解密公式:n = (c^d)%N
- 将整数n转换为消息m
【例1】
- 私钥: (N, d) = (65, 29)
- 密文:c=48
- 计算:n = (48^29)%65 = 3
- 因此:48被解密为3
【例2】
- 私钥是 (N, d) = (33, 7)
- 密文是:c=30
- 计算:n = (30^7)%33 = 24
- 这样,30被解密为24
5 一点说明
RSA算法使用两个素数p和q计算N=pq,然后再经过一些计算得到公钥(N,e)和私钥(N,d)。
根据RSA加解密公式,使用公钥加密后只能使用私钥解密,使用私钥加密后只能使用公钥解密。
因为公钥是公开的,如果能破解出私钥,就能够解密密文消息,而破解需要把N分解为两个素数p和q,如果p和q足够大,则很难分解,类似于单向函数。
6 编程实现
说明:此C语言程序非本人所写,网上找到的。
/*********************************************/
// RSA
/*********************************************/
#include<stdio.h>
// 数据处理函数,实现幂的取余运算
int candp(int a, int b, int c)
{
int r = 1;
b = b + 1;
while(b != 1)
{
r = r * a;
r = r % c;
b--;
}
printf("%d\n", r);
return r;
}
// 公钥e与t的互素判断
int fun(int x, int y)
{
int t;
while(y)
{
t = x;
x = y;
y = t % y;
}
if(x == 1)
return 0; // x与y互素时返回0
else
return 1; // x与y不互素时返回1
}
// 主函数
int main( )
{
int p, q, e, d, m, n, t, c, r;
printf("请输入两个素数p,q:");
scanf("%d%d", &p, &q);
n= p * q;
printf("计算得n为%3d\n", n);
// 求n的欧拉数
t= (p - 1) * (q - 1);
printf("计算得t为%3d\n", t);
printf("请输入公钥e:");
scanf("%d", &e);
if(e < 1 || e > t || fun(e, t))
{
// e<1 或 e>t 或 e与t不互素时,重新输入
printf("e不合要求,请重新输入:");
scanf("%d", &e);
}
d= 1;
// 由公钥e求出私钥d
while(((e * d) % t) != 1)
d++;
printf("经计算d为%d\n", d);
// 加密或解密选择
printf("加密请输入1\n");
printf("解密请输入2\n");
scanf("%d", &r);
switch( r )
{
case 1:
printf("请输入明文m:"); // 输入要加密的明文数字
scanf("%d", &m);
c = candp(m, e, n);
printf("密文为%d\n", c);
break;
case 2:
printf("请输入密文c:"); // 输入要解密的密文数字
scanf("%d", &c);
m = candp(c, d, n);
printf("明文为%d\n", m);
break;
default:
;
}
return 0;
}