RSA加密算法

一、RSA简介

RSA公开密钥密码系统是由R.Rivest,A.Shamir,L.Adleman提出的,不仅仅可用于数据的加密,也可用于数字签名,其算法如下:

1、取两个相近的大素数p、q;

2、计算n=p*q,z=(p-1)*(q-1);

3、任取一个与z互素的整数e;

4、计算满足e*d=1 mod z 的整数d;

5、将明文m分成字符块s加密,每个块s小于n。现设明文m小于n,加密后形成密文c。 加密、解密过程如下:

加密:c=m^e mod n

解密:m=c^d mod n

6、(n,e)和(n,d)分别称为“公开密钥”和“秘密密钥”。根据Euler定理可得:

m=c^d mod n=(m^e mod n)^d mod n=m

现举例说明其工作过程:取两个素数p=11,q=13,n=p*q=11*13=143,z=(p-1)*(q-1)=(11-1)*(13-1)=120,再选取与z=120互素的整数e,如e=7,现可计算出满足7*d=1 mod 120的整数d=103,即:7*103=1 mod 120,7*103/120余1,整理如下:

1.   
2.     p=11
3.   q=13
4.   n=143
5.   e=7
6.   d=103
7.   (n,e)=(143,7)
8.   (n,d)=(143,103)

以数据加密为例:

甲向乙发送机密数据信息m=85,并已知乙的公钥(n,e)=(143,7),于是可计算出:

1.    c=m^e mod n=85^7 mod 143=123

甲将c发送至乙,乙利用私钥(n,d)=(143,103)对c进行计算:

1.    m=c^d mod n=123^103 mod 143=85

现乙已经得到甲向其要发送的机密数据信息。在这里,甲向乙发送信息,甲所拥有的仅仅是乙的公钥。

以数字签名为例:

乙要向甲发送信息,并要让甲确信此信息是由乙本人所发出的,于是,乙将能代表自己身份的编码值(如:123),利用私钥(n,d)=(143,103)进行计算,并将结果发送给甲:

1. m=c^d mod n=123^103 mod 143=85

甲接受到乙的数字签名后利用乙的公钥(n,e)=(143,7)进行计算,得出代表乙身份的编码:

1. c=m^e mod n=85^7 mod 143=123

现甲经过验证已确信信息的发送方为乙。因为只有乙拥有私钥(n,d),来对代表自己身份的编码123进行计算。在不知道乙私钥(n,d)的情况下,任何人都不会算出85这一签名来冒充乙。在这里,乙向甲发送信息并进行签名,甲所拥有的也仅仅是乙的公钥来验证乙的签名。

从上面两个例子中我们可以更好得理解这一结论,即:由(n,e)加密的数据只能用(n,d)解密,反之亦然。

二、在基于序列号保护的共享软件中应用RSA

结合数字签名的实例能更好得理解这一应用:在某一共享软件中,甲想用123为注册名进行软件注册,他现在拥有的仅仅是存在于共享软件程序中的公钥(n,e)=(143,7)。甲现将123为注册名向乙提出注册申请,乙得知此申请并通过此申请后,便利用所拥有的私钥(n,d)对注册名123进行计算:

1. m=c^d mod n=123^103 mod 143=85

甲得到计算后的结果85(序列号),提供给共享软件的注册程序进行计算:

1. c=m^e mod n=85^7 mod 143=123

然后注册程序将判断计算结果c是否为123(注册名),以决定注册是否通过。

如果甲随意输入一组序列号利用公钥(n,e)进行计算,那他得到的结果将不是123,注册也就失败了。注意,在这里,共享软件的注册程序比较的是注册名,而不是序列号。如果甲跟踪注册程序得到了他所随意输入的序列号所产生的注册名,将其提供给注册程序,那注册程序也能够通过注册,但他由于没有(n,d),所以他无法用自己的注册名进行软件注册,也就防止了非法注册机的制作。

将RSA应用于此的目的仅仅是防止非法注册机的制作,在以上描述中,n=143,包括以下Demo中的n(HEX)=963251DC5A9C90D9F203A03C363BA411,以现在的计算机处理速度,能很快地将其因式分解得到相应的p,q,再结合暴露在共享软件注册程序中的e,从而计算出d,那么这个共享软件的保护就完全被破解了。解决的方法是要避免n过短,以及结合MD5等加密算法……

三、具体实践

/* RSA Demo 1.0 版

* 版权所有 (C) 2004 赵春生

* 2004.04.25

* http://timw.yeah.net

* http://timw.126.com

* 本程序调用Miracl ver 4.82大数运算库,详见其附带手册。

* P,Q,N,D,E使用RSATool2生成。

*/

1、注册机的关键代码:

01. void CKeyGenDlg::OnGen() 
02. {
03.     // TODO: Add your control notification handler code here
04.       
05.     /* KeyGen 1.0 版
06.     * 版权所有 (C) 2004 赵春生
07.     * 2004.04.25
08.     * http://timw.yeah.net
09.     * http://timw.126.com
10.     * 本程序调用Miracl ver 4.82大数运算库,详见其附带手册。
11.     */
12.       
13.     
14.       
15.     //P(HEX)=E34436F5F48A227B
16.     //Q(HEX)=A92FA24467C4E3E3
17.     //N(HEX)=963251DC5A9C90D9F203A03C363BA411
18.     //D(HEX)=56157D29A89D77BF2F669A8F0B123CC9
19.     //E(HEX)=10001
20.     //Keysize(Bits)=128
21.       
22.     UpdateData(TRUE);
23.       
24.     int namelen=m_name.GetWindowTextLength (); //获取Name的长度
25.       
26.     //务必满足:Name的长度<=(Keysize/8),使M < N成立。
27.     if (namelen!=0&&namelen<=16) //如果不为空且< =128/8则开始计算SN
28.     {
29.         miracl *mip=mirsys(100,0);
30.         mip->IOBASE=16; //16进制模式
31.           
32.         //定义并初始化变量
33.         big m=mirvar(0); //m 放明文:注册码SN
34.         big c=mirvar(0); //c 放密文:用户名Name
35.         big n=mirvar(0); //n 模数
36.         big d=mirvar(0); //d 私钥
37.         TCHAR Name[256]={0};
38.         TCHAR SN[256]={0};
39.           
40.         m_name.GetWindowText (Name,namelen+1); //获取Name
41.         bytes_to_big(namelen,Name,c); //转换成16进制
42.         cinstr(n,"963251DC5A9C90D9F203A03C363BA411"); //初始化模数n 
43.         cinstr(d,"56157D29A89D77BF2F669A8F0B123CC9"); //初始化私钥d
44.         powmod(c,d,n,m); //计算m=c^d mod n
45.         cotstr(m,SN); //将m以16进制串写入SN
46.         m_sn.SetWindowText (SN); //输出16进制SN
47.           
48.         //释放内存
49.         mirkill(m);
50.         mirkill(c);
51.         mirkill(n);
52.         mirkill(d);
53.         mirexit();
54.     }
55.     else
56.         m_sn.SetWindowText ("Error: Invalid registration name.");
57.   
58.     UpdateData(FALSE);
59. }

2,软件中注册程序的关键代码:

01. void CRSAApplicationDlg::OnReg() 
02. {
03.     // TODO: Add your control notification handler code here
04.       
05.     /* RSA Application 1.0 版
06.     * 版权所有 (C) 2004 赵春生
07.     * 2004.04.25
08.     * http://timw.yeah.net
09.     * http://timw.126.com
10.     * 本程序调用Miracl ver 4.82大数运算库,详见其附带手册。
11.     */
12.       
13.     /
14.       
15.     //P(HEX)=E34436F5F48A227B
16.     //Q(HEX)=A92FA24467C4E3E3
17.     //N(HEX)=963251DC5A9C90D9F203A03C363BA411
18.     //D(HEX)=56157D29A89D77BF2F669A8F0B123CC9
19.     //E(HEX)=10001
20.     //Keysize(Bits)=128
21.       
22.     UpdateData(TRUE);
23.       
24.     miracl *mip=mirsys(100,0);
25.     mip->IOBASE=16; //16进制模式
26.       
27.     //定义并初始化变量
28.     big m=mirvar(0); //m 放明文:注册码SN
29.     big c=mirvar(0); //c 放密文:用户名Name
30.     big n=mirvar(0); //n 模数
31.     big e=mirvar(0); //e 公钥
32.     TCHAR Name[256]={0};
33.     TCHAR SN[256]={0};
34.     TCHAR temp[256]={0};
35.     int len=0;
36.     int i,j;
37.       
38.     //获取Name
39.     len=m_name.GetWindowTextLength ();
40.     m_name.GetWindowText (Name,len+1);
41.       
42.     //获取SN
43.     len=m_sn.GetWindowTextLength ();
44.     m_sn.GetWindowText (SN,len+1);
45.       
46.     //检查SN是否为16进制
47.     for (i=0,j=0;i< len;i++)
48.     {
49.         if(isxdigit(SN[i])==0)
50.         {
51.             j=1;
52.             break;
53.         }
54.     }
55.       
56.     //如果输入的SN为16进制且长度不为0
57.     if (j!=1&&len!=0)
58.     {
59.           
60.         cinstr(m,SN); //初始化明文m
61.         cinstr(n,"963251DC5A9C90D9F203A03C363BA411"); //初始化模数n 
62.         cinstr(e,"10001"); //初始化公钥e
63.           
64.         //当m< n时
65.         if(compare(m,n)==-1)
66.         {
67.             powmod(m,e,n,c);//计算c=m^e mod n
68.             big_to_bytes(256,c,temp,FALSE);//将c转换成数组写入temp
69.               
70.             //释放内存
71.             mirkill(m);
72.             mirkill(c);
73.             mirkill(n);
74.             mirkill(e);
75.             mirexit();
76.         }
77.         else
78.             j=1;
79.           
80.     }
81.       
82.     //对Name、temp, m、n, SN的长度进行检查
83.     if(lstrcmp(Name,temp)!=0||j==1||len==0)
84.         MessageBox("Please check your NAME and SN, then try again.","RSA Application");
85.     else
86.         MessageBox("Congratulate!!!","Registration complete!");
87.       
88.     UpdateData(FALSE);
89. }

//

编译提示:

1、将 Project-Settings-Settings For(All Configuration)-C/C++中Category 项的 Precompiled Headers设置成:Automatic use of precompiled headers(如图一)。

图一

2、将 ms32.lib 添加到工程中(如图二)。

图二

3、MIRACL是C库。

1. extern "C"
2. {
3. #include "miracl.h"
4. #include "mirdef.h"
5. }
6.   
7. #pragma comment( lib, "ms32.lib" )

四、以上代码在Win2000P+SP4 + VC6+SP5测试通过

RSA Demo 1.0 源码也可从我的个人主页下载。

http://timw.yeah.net

http://timw.126.com

14:15 2004-4-26

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值