使用RSA非對稱密鑰算法實現硬件設備受權

 
1、硬件設備受權
即用戶在硬件設備輸入一個序列號(或一個包含 受權信息的文件),而後硬件設備即可正常使用. 
 
2、受權方案
構思受權方案時,參考了下面網址的思路:

  • 1.用戶提供本身的硬件ID,從設備廠家獲得一串受權序列號,在設備中輸入序列號,設備便可激活使用.
序列號形如 :
1330-1440-1602-3671-9749-7897
XDM3T-W3T3V-MGJWK-8BFVD-GVPKY
技術實現:
受權序列號,是通過私鑰加密的受權信息的字符串,設備中使用公鑰解密,獲得正確受權信息,則設備被激活. RSA非對稱加密算法
限制:受權信息須要儘可能短,由於rsa 加密算法庫(openssl)可加密長度有限制(與私鑰長度有關,未具體瞭解),因此要用盡可能少的數據保存儘可能長的受權信息.
 
  • 2.用戶提供本身的硬件ID,從設備廠家獲得一個受權文件,在設備中上傳受權文件,設備便可激活使用
受權文件中的內容形如:
{
 "ver": 1,
 "info": {
  "productid": "vW2TNOMlLvZdAgAF",
  "invaliddate": "2014-05-16 11:40:30",
  "userlimit": 100
 },
 "signature": [25, 218, 203, 190, 99, 76, 192, 136, 176, 181, 198, 128, 14, 250, 189, 198, 152, 208, 15, 202, 233, 77, 189, 3, 44, 113, 65, 231, 51, 100, 208, 127, 19, 255, 139, 174, 62, 9, 76, 165, 137, 15, 165, 178, 138, 9, 32, 218, 209, 222, 6, 234, 94, 5, 41, 130, 27, 232, 37, 195, 52, 120, 81, 143, 103, 40, 90, 93, 240, 115, 5, 117, 230, 65, 243, 182, 141, 64, 179, 140, 137, 155, 219, 75, 87, 83, 36, 49, 178, 210, 53, 171, 254, 28, 88, 39, 241, 57, 68, 204, 46, 231, 180, 133, 134, 108, 114, 243, 163, 30, 201, 103, 138, 15, 23, 247, 54, 32, 64, 181, 71, 12, 14, 88, 247, 156, 138, 32]
}
技術實現:
受權文件包含明文的"受權信息"以及使用私鑰進行的"受權信息的 簽名"組成的字符串.設備使用公鑰進行簽名的驗證.
(相對於序列號的幾十個字符串來講,這裏的字符串確定會超過幾百個,因此保存在文件中方便用戶輸入設備).
 
  • 3.用戶提供本身的硬件ID,設備廠家更新"受權服務器"中指定硬件的受權信息,設備會自動激活
技術實現:
須要有一臺公網服務器,處理查詢受權信息的請求.
用戶不須要輸入任何序列號,只須要點擊一個"更新"按鈕,設備主動發送自身的硬件惟一ID,向某一服務器請求受權信息(獲得第2種方案中的受權文件),成功獲取到後,設備會自動激活.
 
3、結論
第1個方案須要嚴格定義受權信息,以便加密後的序列號長度儘可能短,我的以爲實現起來不方便.
第3個方案須要額外設備一臺服務器,增長了工做量,並且超出現有需求,此功能主要目的只是爲了限制指定設備的時間,因此只須要每一個硬件設備單獨的序列號激活便可.
第2個方案能實現同第1個方案相同的效果,並且在之後改成在線激活時,能夠輕鬆擴展.(基本原有功能能夠不變,只須要增長一個公網服務器;增長一個自動從公網服務器獲取受權文件的動做便可)
因此我選擇了第2個方案,
那麼,此時能夠肯定的是,我須要完成三個程序的編碼.
1)新增 一個生成受權文件的程序,叫作gen

 



2)新增 一個驗證受權文件是否合法的程序,叫作verify

 

 
 
3)修改 現有系統內的程序,  驗證受權文件的合法性 ->提取受權文件中的"受權信息" -> 檢驗當前設備中的相應信息,根據狀況設置相應的限制
 
 
4、編碼實現
 
Hash值
使用md5或者sh1等摘要算法獲得的數據指紋。
 
受權信息
生成的序列號(或受權文件)中所包括的信息,這些信息指定了硬件設備可用的功能。好比受權到期時間、限制可用人數、限制硬件ID等等。
 
RSA非對稱加密算法
非對稱加密技術有兩個密鑰,「公開密鑰」和「私有密鑰」。使用「公開密鑰」加密,則可用「私有密鑰」解密;使用「私有密鑰」加密,則可用「公開密鑰」解密。RSA算法中非對稱加密技術的一種。具體原理可參考  RSA算法原理(一)
使用openssl中的rsa加密算法,對加密的數據長度有限制,因此通常只用於加密較短的Hash值。具體緣由,查看 API說明
私有密鑰  --  公開密鑰  可互相推導?
 
加密算法庫
網上搜索加密算法庫有不少,我本次使用的是openssl。

簽名
使用私鑰對「數據」的Hash值加密生成一個「簽名值」,將「數據」和「簽名值」一塊兒發送出去。接收方使用公鑰解密「簽名值」獲得一個Hash值h1,再對原始數據經過計算Hash值H2,對比H1和H2數據相同,則能保證此條信息是私鑰擁有者發佈的。其實和人類在合同上「簽名」、「蓋章」的方法同樣,只是爲了校驗信息發佈者的真僞。
 
 
生成RSA算法公鑰和私鑰的方法:
生成2048位的私鑰文件,private.pem
openssl genrsa -out private.pem 2048
生成對應的公鑰文件,public.pem
openssl rsa -in private.pem -pubout -out public.pem
從文件中讀取密鑰:
int readpub_rsakey(const char *filename, RSA **prsa)
{
  FILE *fp = fopen(filename, "r");
  if (NULL == fp) {
    printf("fopen() fail!\n");
    return -1;
  }
  *prsa =  PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
  if (NULL == *prsa) {
    printf("read_rsa_pubkey() fail!\n");
    fclose(fp);
    return -1;
  }
  fclose(fp);
  return 0;
}
int readpri_rsakey(const char *filename, RSA **prsa)
{
  FILE *fp = fopen(filename, "r");
  if (NULL == fp) {
    printf("fopen fail!\n");
    return -1;
  }
  *prsa =  PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
  if (NULL == *prsa) {
    printf("read_rsa_prikey() fail!\n");
    fclose(fp);
    return -1;
  }
  fclose(fp);
  return 0;
}
從字符串中讀取密鑰:
int getpub_rsakey(const char *key, RSA **prsa)
{
  BIO *bio = NULL;
  if (NULL == (bio = BIO_new_mem_buf((void*)key, -1))) {
    printf("BIO_new_membuf() fail!\n");
    return -1;
  }
  *prsa =  PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
  if (!(*prsa)) {
    printf("PEM_readbio_RSA_PUBKEY() fali!\n");
    BIO_free_all(bio);
    return -1;
  }
  return 0;
}
int getpri_rsakey(const char *key, RSA **prsa)
{
  BIO *bio = NULL;
  if (NULL == (bio = BIO_new_mem_buf((void*)key, -1))) {
    printf("BIO_new_membuf() fail!\n");
    return -1;
  }
  *prsa =  PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
  if (!(*prsa)) {
    printf("PEM_read_bio_RSAPrivateKey() fail!\n");
    BIO_free_all(bio);
    return -1;
  }
  return 0;
}

5、參考
網上開源 RSA公鑰加密算法 實現庫
openssl 強大的工具集合
crypto++ 過於複雜的封裝,特別是rsa實現模塊。
速度上有優點的:XySSL, CyaSSL(都使用的LibTomMath)
邏輯上有優點的:axcrypto, raknet
還有一些大數庫: vlong,WinNTL
對於公鑰簽名認證, google android自帶的libmincrypt有超快的實現方法,惋惜代碼只是爲了一家優化,僅提供e=3的加速。而網上一般的ASN.1證書,都用了e=63357。
 
int RSA_public_encrypt(int flen, const unsigned char *from,
  unsigned char *to, RSA *rsa,int padding);
 
openssl接口使用方法:
《精通pki網絡安全認證技術與編程實現》
 
證書格式說明:(帶有私鑰的證書 、二進制編碼的證書 、Base64編碼的證書 )
 
密鑰編碼格式:(DER、PEM、NET )
 
加密、解密、簽名等概念:
相關文章
相關標籤/搜索