用非對稱密碼算法制做共享軟件的註冊碼 ---- 加密二

來源:Internet
做者:未知

[資料是從免費網站上獲取的,上載在這裏,只爲交流學習目的,文章原做者保留全部權力,
如本博客的內容侵犯了你的權益,請與如下地址聯繫,本人獲知後,立刻刪除。同時本人深表歉意,並致以崇高的謝意!
]


網上大多數共享軟件的註冊碼(又稱爲序列號)的設計都不是很好,比較容易被破解者作出註冊機來。下面介紹一種利用公鑰算法(又稱爲非對稱算法)RSA製做註冊碼的方法。採用這種方法,不知道密鑰的話時很難寫出註冊機來。實際上有部分軟件已經使用了這類方法。

  你們都知道RSA採用一對密鑰,即公鑰和私鑰,從公鑰難於推出私鑰,反之亦然,這個難度是基於大數分解的難度。利用RSA生成共享軟件註冊碼的思路以下:
一、先隨機生成一對公鑰E和私鑰D;
二、軟件做者本身寫一個註冊機,註冊機完成的工做就是把用戶名M用私鑰D加密,密文C就是註冊碼。因爲密文每每包含不可顯示字符,因此最好把密文進行編碼,變成可顯示字符,好比採用base6四、uuencode編碼等。
  密文C = (M ^ D) mod N
  其中^表示乘冪,mod表示求餘,N爲RSA的模數。
  三、共享軟件將用戶輸入的註冊碼先進行解碼(如base64解碼等),獲得密文,而後用公鑰E對密文進行解密,獲得明文M',若是明文和用戶名相同(即知足M' = M),則說明註冊碼正確,不然就是非法的註冊碼。破解者能夠經過跟蹤你的軟件獲得公鑰E,但沒法獲得私鑰D。
明文M' = (C ^ E) mod D

  有幾點須要說明:
  一、模數N過短時不安全,容易被分解。以目前的計算能力,建議N取值在512-bit以上。但這樣註冊碼的長度也變長了,可能給用戶帶來不方便。通常要採用大數運算庫來實現RSA。
  二、隨機生成密鑰對時,要採用儘量好的隨機數生成算法,不然N仍是頗有可能被分解。
  三、也能夠在註冊機中用公鑰E對用戶名加密獲得註冊碼,在軟件中對用戶輸入的註冊碼用私鑰D進行解密獲得用戶名。此時公鑰E就不能取經常使用的三、65537等固定值,不然一旦被猜出E,則也能夠寫出註冊機,由於此時破解者能夠從你的軟件中獲得私鑰D。
  四、這種方法只是爲了防止被人寫出註冊機,它沒法防止經過修改程序中跳轉指令的方法來破解你的軟件。爲了防止別人修改你的程序文件,能夠用註冊碼中的一部分來加密你的程序代碼或數據。
  五、這種方法稍加改動便可防止正版用戶散發註冊碼,即採用一機一碼的方法,將用戶名替換成用戶機器的硬軟件信息便可,這個硬軟件信息應能惟一地表示用戶的機器,不然也容易被僞造。
  六、採用了上面的方法以後,只有知道至少一個合法註冊碼的人才能將程序破解。

下面舉一個例子,採用大數運算庫Freelip([url]http://www.und.nodak.edu/org/crypto/crypto/numbers/programs/freelip/freelip_1.1.tar.gz[/url])來實現RSA。該庫是用C寫的,商業使用須要許可證。
  一、首先隨機生成密鑰對。能夠本身編程隨機搜索大素數。此處因爲是舉例,咱們採用RSATool([url]http://www.secretashell.com/TMG/RSATool2v15.zip[/url])生成64-bit RSA的參數:
大素數P = A57F2B33, 大素數Q = E7C441B3, 模數N = 95D49FD119EF27A9, 私鑰D = 76D2A6E2AC86CC99, 公鑰E = 65537
  二、製做註冊機。將用戶名用私鑰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中,即爲註冊碼

  三、在軟件中判斷註冊碼。
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
{
//正確的註冊碼
}


附:經常使用的大數運算庫的地址(有些雖然不是專門的大數運算庫,可是帶有相關的庫)
一、Crypto++: http://www.eskimo.com/~weidai/cryptlib.html(C++)
二、MIRACL: http://indigo.ie/~mscott/(C/C++)
三、GNU MP: http://www.swox.com/gmp/(C)
四、Piologie: http://www.hipilib.de/pidownload.htm
五、cryptlib: http://www.cs.auckland.ac.nz/~pgut001/cryptlib/
六、RSAEuro: http://www.rsaeuro.com/products/RSAEuro/
七、OpenSSL: http://www.openssl.org/
九、RSARef: http://download.gale.org/rsaref20.tar.Z
十、GInt: http://triade.studentenweb.org/GInt/gint.html(Delphi)

 

出處:http://www.cnblogs.com/erwin/archive/2007/06/13/782759.htmlhtml

相關文章
相關標籤/搜索