首页
社区
课程
招聘
《浅谈利用RSA算法防止非法注册机的制作》
发表于: 2004-5-20 16:06 13939

《浅谈利用RSA算法防止非法注册机的制作》

2004-5-20 16:06
13939

              《浅谈利用RSA算法防止非法注册机的制作》

                  RSA Demo 1.0源码下载

一: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,整理如下:

  p=11
  q=13
  n=143
  e=7
  d=103
  (n,e)=(143,7)
  (n,d)=(143,103)

  以数据加密为例:

  甲向乙发送机密数据信息m=85,并已知乙的公钥(n,e)=(143,7),于是可计算出:
c=m^e mod n=85^7 mod 143=123
甲将c发送至乙,乙利用私钥(n,d)=(143,103)对c进行计算:
m=c^d mod n=123^103 mod 143=85
现乙已经得到甲向其要发送的机密数据信息。在这里,甲向乙发送信息,甲所拥有的仅仅是乙的公钥。

  以数字签名为例:

  乙要向甲发送信息,并要让甲确信此信息是由乙本人所发出的,于是,乙将能代表自己身份的编码值(如:123),利用私钥(n,d)=(143,103)进行计算,并将结果发送给甲:
m=c^d mod n=123^103 mod 143=85
甲接受到乙的数字签名后利用乙的公钥(n,e)=(143,7)进行计算,得出代表乙身份的编码:
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进行计算:
m=c^d mod n=123^103 mod 143=85
甲得到计算后的结果85(序列号),提供给共享软件的注册程序进行计算:
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,注册机的关键代码:

void CKeyGenDlg::OnGen()
{
// TODO: Add your control notification handler code here

/* KeyGen 1.0 版
* 版权所有 (C) 2004 赵春生
* 2004.04.25
* http://timw.yeah.net
* http://timw.126.com
* 本程序调用Miracl ver 4.82大数运算库,详见其附带手册。
*/

//////////////////////////////////////////////////////////////////////////

//P(HEX)=E34436F5F48A227B
//Q(HEX)=A92FA24467C4E3E3
//N(HEX)=963251DC5A9C90D9F203A03C363BA411
//D(HEX)=56157D29A89D77BF2F669A8F0B123CC9
//E(HEX)=10001
//Keysize(Bits)=128

UpdateData(TRUE);

int namelen=m_name.GetWindowTextLength (); //获取Name的长度

//务必满足:Name的长度<=(Keysize/8),使M<N成立。
if (namelen!=0&&namelen<=16) //如果不为空且<=128/8则开始计算SN
{
miracl *mip=mirsys(100,0);
mip->IOBASE=16; //16进制模式

//定义并初始化变量
big m=mirvar(0); //m 放明文:注册码SN
big c=mirvar(0); //c 放密文:用户名Name
big n=mirvar(0); //n 模数
big d=mirvar(0); //d 私钥
TCHAR Name[256]={0};
TCHAR SN[256]={0};

m_name.GetWindowText (Name,namelen+1); //获取Name
bytes_to_big(namelen,Name,c); //转换成16进制
cinstr(n,"963251DC5A9C90D9F203A03C363BA411"); //初始化模数n
cinstr(d,"56157D29A89D77BF2F669A8F0B123CC9"); //初始化私钥d
powmod(c,d,n,m); //计算m=c^d mod n
cotstr(m,SN); //将m以16进制串写入SN
m_sn.SetWindowText (SN); //输出16进制SN

//释放内存
mirkill(m);
mirkill(c);
mirkill(n);
mirkill(d);
mirexit();
}
else
m_sn.SetWindowText ("Error: Invalid registration name.");

UpdateData(FALSE);
}

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

void CRSAApplicationDlg::OnReg()
{
// TODO: Add your control notification handler code here

/* RSA Application 1.0 版
* 版权所有 (C) 2004 赵春生
* 2004.04.25
* http://timw.yeah.net
* http://timw.126.com
* 本程序调用Miracl ver 4.82大数运算库,详见其附带手册。
*/

//////////////////////////////////////////////////////////////////////////

//P(HEX)=E34436F5F48A227B
//Q(HEX)=A92FA24467C4E3E3
//N(HEX)=963251DC5A9C90D9F203A03C363BA411
//D(HEX)=56157D29A89D77BF2F669A8F0B123CC9
//E(HEX)=10001
//Keysize(Bits)=128

UpdateData(TRUE);

miracl *mip=mirsys(100,0);
mip->IOBASE=16; //16进制模式

//定义并初始化变量
big m=mirvar(0); //m 放明文:注册码SN
big c=mirvar(0); //c 放密文:用户名Name
big n=mirvar(0); //n 模数
big e=mirvar(0); //e 公钥
TCHAR Name[256]={0};
TCHAR SN[256]={0};
TCHAR temp[256]={0};
int len=0;
int i,j;

//获取Name
len=m_name.GetWindowTextLength ();
m_name.GetWindowText (Name,len+1);

//获取SN
len=m_sn.GetWindowTextLength ();
m_sn.GetWindowText (SN,len+1);

//检查SN是否为16进制
for (i=0,j=0;i<len;i++)
{
if(isxdigit(SN[i])==0)
{
j=1;
break;
}
}

//如果输入的SN为16进制且长度不为0
if (j!=1&&len!=0)
{

cinstr(m,SN); //初始化明文m
cinstr(n,"963251DC5A9C90D9F203A03C363BA411"); //初始化模数n
cinstr(e,"10001"); //初始化公钥e

//当m<n时
if(compare(m,n)==-1)
{
powmod(m,e,n,c);//计算c=m^e mod n
big_to_bytes(256,c,temp,FALSE);//将c转换成数组写入temp

//释放内存
mirkill(m);
mirkill(c);
mirkill(n);
mirkill(e);
mirexit();
}
else
j=1;

}

//对Name、temp, m、n, SN的长度进行检查
if(lstrcmp(Name,temp)!=0||j==1||len==0)
MessageBox("Please check your NAME and SN, then try again.","RSA Application");
else
MessageBox("Congratulate!!!","Registration complete!");

UpdateData(FALSE);

}

//////////////////////////////////////////////////////////////////////////////////

编译提示:

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

2:将ms32.lib添加到工程中(图2)。

3:MIRACL是C库。

extern "C"
{
#include "miracl.h"
#include "mirdef.h"
}

#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


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 10
支持
分享
最新回复 (13)
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
2
这篇拙文是我学习RSA时写的,里面有我在学习中理解的一些东西,可能有误,还请这里的前辈们多多指教,谢谢大家!
2004-5-20 16:11
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
支持。
2004-5-20 20:33
0
雪    币: 14940
活跃值: (4728)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
说实话算法偶最头疼。搞的脑袋都大了。。555:(

不过还是支持你!
2004-5-20 21:01
0
雪    币: 295
活跃值: (506)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
支持。。。
2004-5-20 21:22
0
雪    币: 231
活跃值: (115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
说起来,如果没有类似MD5的单向函数,只靠RSA还是不行的。
2004-5-21 08:48
0
雪    币: 420
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
好!看上去有点懂了。
2004-5-21 08:54
0
雪    币: 226
活跃值: (72)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
COPY下来,慢慢学习吧。
2004-5-21 08:57
0
雪    币: 213
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
增加RSA算法的N的长度能够有效保护程序不被破解么?

当RSA算法的N足够大时,分解便不太可能?

前几天看了篇文章,说可以自己生成一个N去替换程序中的模数!

这样就通过更改算法的参数来实现破解(与爆破不同)!

看来通过增加N的长度未必能起到好的保护效果!
2004-6-19 21:24
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
10
最初由 xiaoyudian 发布
增加RSA算法的N的长度能够有效保护程序不被破解么?

当RSA算法的N足够大时,分解便不太可能?

前几天看了篇文章,说可以自己生成一个N去替换程序中的模数!

这样就通过更改算法的参数来实现破解(与爆破不同)!

看来通过增加N的长度未必能起到好的保护效果!

想起ACP..;)
替换n属于爆破范畴吧?:D
2004-6-20 07:05
0
雪    币: 220
活跃值: (100)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
只要分析出是RSA算法,就会有办法破解,甚至做出注册机;

有一个设想不知可行否:在给定的注册环境下,通过假设的注册吗来求得用户名,最终完成注册。
2004-6-20 09:06
0
雪    币: 231
活跃值: (115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
严格来说,替换N等参数属于爆破范畴,但这个方法不必关心程序中其他地方的陷阱,应该说是一种很好的办法。当然,如果N本来就是陷阱的话,呵呵。
2004-6-20 09:09
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
13
最初由 funlove 发布
只要分析出是RSA算法,就会有办法破解,甚至做出注册机;

有一个设想不知可行否:在给定的注册环境下,通过假设的注册吗来求得用户名,最终完成注册。


这种方法可行,确实能完成软件的注册。

但你却无法使用自己的ID来注册软件。

最近一直在想:***在花同样的时间用来加密的前提下,***是不是防止文件被修改比应用高强度的算法更有意义?
2004-6-20 11:25
0
雪    币: 231
活跃值: (115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
加一个Hash就能阻止了。
2004-6-20 17:55
0
游客
登录 | 注册 方可回帖
返回
//