用非对称暗码算法建造共享软件的注册码
副标题#e#
网上大大都共享软件的注册码(又称为序列号)的设计都不是很好,较量容易被破解者做出注册机来。下面先容一种操作公钥算法(又称为非对称算法)RSA建造注册码的要领。回收这种要领,不知道密钥的话时很难写出注册机来。实际上有部门软件已经利用了这类要领。
各人都知道RSA回收一对密钥,即公钥和私钥,从公钥难于推出私钥,反之亦然,这个难度是基于大数解析的难度。操作RSA生成共享软件注册码的思路如下:
1、先随机生成一对公钥E和私钥D;
2、软件作者本身写一个注册机,注册机完成的事情就是把用户名M用私钥D加密,密文C就是注册码。由于密文往往包括不行显示字符,所以最好把密文举办编码,酿成可显示字符,好比回收base64、uuencode编码等。
密文C = (M ^ D) mod N
个中^暗示乘幂,mod暗示求余,N为RSA的模数。
3、共享软件将用户输入的注册码先举办解码(如base64解码等),获得密文,然后用公钥E对密文举办解密,获得明文M’,假如明文和用户名沟通(即满意M’ = M),则说明注册码正确,不然就是犯科的注册码。破解者可以通过跟踪你的软件获得公钥E,但无法获得私钥D。
明文M’ = (C ^ E) mod D
有几点需要说明:
1、模数N太短时不安详,容易被解析。以今朝的计较本领,发起N取值在512-bit以上。但这样注册码的长度也变长了,大概给用户带来不利便。一般要回收大数运算库来实现RSA。
2、随机生成密钥对时,要回收尽大概好的随机数生成算法,不然N照旧很有大概被解析。
3、也可以在注册机顶用公钥E对用户名加密获得注册码,在软件中对用户输入的注册码用私钥D举办解密获得用户名。此时公钥E就不能取常用的3、65537等牢靠值,不然一旦被猜出E,则也可以写出注册机,因为此时破解者可以从你的软件中获得私钥D。
4、这种要领只是为了防备被人写出注册机,它无法防备通过修改措施中跳转指令的要领来破解你的软件。为了防备别人修改你的措施文件,可以用注册码中的一部门来加密你的措施代码或数据。
5、这种要领稍加窜改即可防备正版用户披发注册码,即回收一机一码的要领,将用户名替换成用户呆板的硬软件信息即可,这个硬软件信息应能独一地暗示用户的呆板,不然也容易被伪造。
6、回收了上面的要领之后,只有知道至少一个正当注册码的人才气将措施破解。
下面举一个例子,回收大数运算库Freelip(http://www.und.nodak.edu/org/crypto/crypto/numbers/programs/freelip/freelip_1.1.tar.gz)来实现RSA。该库是用C写的,贸易利用需要许可证。
1、首先随机生成密钥对。可以本身编程随机搜索大素数。此处由于是举例,我们回收RSATool(http://www.secretashell.com/TMG/RSATool2v15.zip)生成64-bit RSA的参数:
大素数P = A57F2B33, 大素数Q = E7C441B3, 模数N = 95D49FD119EF27A9, 私钥D = 76D2A6E2AC86CC99, 公钥E = 65537
2、建造注册机。将用户名用私钥D举办加密,获得的密文作为注册码:
首先界说宏WIN32(VC自带,但BCB中需要本身界说),然后包括头文件"lip.h":
#ifndef WIN32
#define WIN32
#endif
#include "lip.h"
并把"lip.c"插手到project中。
然后将用户名的ASCII码转换成相应的十六进制串:
char UserName[] = "4E6574677579";
char SerialNumber[256];
verylong N = 0, D = 0, M = 0, C = 0; //Freelip中的大数范例为verylong。
zhsread( UserName, &M); //初始化明文M,M便是用户名的十六进制暗示
zhsread("95D49FD119EF27A9", &N); //初始化模数N
zhsread("76D2A6E2AC86CC99", &D); //初始化私钥D
zexpmod(M, D, N, &C); //计较密文C = (M ^ D) mod N
zswrite(SerialNumber, C); //将C的十进制串暗示写入SerialNumber中,即为注册码
#p#副标题#e#
3、在软件中判定注册码。
char UserNameString[ ] = "4E6574677579"; //用户输入的用户名
char SerialNumber[ ] = "1876542098762625173846272838"; //用户输入的注册码
verylong N = 0, E = 0, C = 0, UserName = , DecryptedUserName = 0 ;
zhsread(SerialNumber, &C); //初始化密文C
zhsread("95D49FD119EF27A9", &N); //初始化模数N
zsread("65537", &E); //初始化公钥E
zexpmod(C, E, N, &DecryptedUserName); //计较明文DecryptedUserName = (C ^ E) mod N
zhsread(UserNameString, &UserName); //用户输入的用户名
if (zcompare(UserName, DecryptedUsername))
{
//错误的注册码
}
else
{
//正确的注册码
}
附:常用的大数运算库的地点(有些固然不是专门的大数运算库,可是带有相关的库)
1、Crypto++:http://www.eskimo.com/~weidai/cryptlib.html(C++)
2、MIRACL:http://indigo.ie/~mscott/(C/C++)
3、GNU MP:http://www.swox.com/gmp/ (C)
4、Piologie: http://www.hipilib.de/pidownload.htm
5、cryptlib:http://www.cs.auckland.ac.nz/~pgut001/cryptlib/
6、RSAEuro:http://www.rsaeuro.com/products/RSAEuro/
7、OpenSSL:http://www.openssl.org/
9、RSARef:http://download.gale.org/rsaref20.tar.Z
10、GInt:http://triade.studentenweb.org/GInt/gint.html (Delphi)