node-rsa非對稱加密

寫在最前:此文的目的是介紹編碼,減小剛接觸時的彎路,因此內容且不作詳細累述node

一.使用 node-rsa 進行非對稱加解密

  • 由於 比特幣 中使用的非對稱加密,因此在npm中對比找到一個比較方便也直觀的庫:node-rsa
  • 非對稱加密的關鍵在於 有 公鑰 / 私鑰
    用法:
    a.生成一對公鑰私鑰
    b.公鑰加密 -> 對應私鑰解密
    c.私鑰加密 -> 對應公鑰解密算法

  • 非對稱加密的常見應用方式
    a.公鑰加密,發給私鑰擁有者,私鑰解密得到明文。其它人用公鑰解不開
    b.私鑰加密(簽名)npm

  • 公鑰的傳輸(混合加密)
    a.使用對稱加密算法發佈公鑰
    b.使用對稱加密算法解密公鑰,再使用公鑰加密明文,發給私鑰擁有者測試

注:不能 公鑰加密公鑰解密 或 私鑰加密私鑰解密ui

二.幾個重要概念

祕鑰內容格式與傳輸格式
1. DER 和 PEM 編碼編碼

  • DER: 基於二進制的編碼。能夠用CER或者CRT做爲擴展名的的整數。比較合適的說法是「我有一個DER編碼的證書」,而不是「我有一個DER證書」。【編碼規則參考】加密

  • PEM: 基於ASCII(Base64)的編碼。OpenSSL 使用 PEM 文件格式存儲證書和密鑰。【編碼規則參考】
    PEM 實質上是 base64 編碼的二進制內容,再進行增長或裁剪特殊字符-、\n、\r、begin信息、end信息等,如:
-----BEGIN CERTIFICATE-----
內容
-----END CERTIFICATE-----

注:本文中的私鑰公鑰都是用 pem 格式url

2. PKCS(The Public-Key Cryptography Standards).net

  • 由美國RSA公司及其合做夥伴制定的一組公鑰密碼學標準,其中包括證書申請、證書更新、證書做廢表發佈、擴展證書內容以及數字簽名、數字信封的格式等方面的一系列相關協議。
  • 版本:現有PCKS1,PCKS3,PCKS5,PKCS6,PKCS7,PKCS8,PKCS9,PKCS10,PKCS11,PKCS12,PKCS13,PKCS14,PKCS15 共 13個版本
    經常使用:PCKS1 和 PCKS8,本文使用 PCKS8 標準

注:因爲PKCS內容規範設計二進制,不方便使用,因此通常轉成 base64 後,用 pem 格式規範顯示設計

  • PCKS1 的pem格式頭:
//公鑰
-----BEGIN RSA PUBLIC KEY-----
MEgCQQCpb53RwojJX+lxHiEMfNmixx+eIV+u+d9e61Ecx8MVBW0tzAoxTpdTKrgN
9hdBqaP6rtQMxOp/4++C5+3zh6D1AgMBAAE=
-----END RSA PUBLIC KEY-----
//私鑰
-----BEGIN RSA PRIVATE KEY-----
MIIBPAIBAAJBAKlvndHCiMlf6XEeIQx82aLHH54hX675317rURzHwxUFbS3MCjFO
l1MquA32F0Gpo/qu1AzE6n/j74Ln7fOHoPUCAwEAAQJAJO8tyeHMC4may4uzzJMS
pgcd/0xrHSte48QMBGgPQG95imYXELKQUV2rjzsua9xJP5huQjhe+qrmBpEqrtf7
wQIhANccK0zuFaH4CoIuKsp92YB6OGwndy6UJaiX2RoUw0V5AiEAyaTTkar73r4d
OB2s4Ofj+UkGX/aspp0dM+7V5HathF0CIQCezlYNSmvAEr23U9wVeAmd9x02g4BS
a97Nc6U8wv1SiQIhAKap7ZTA1l1MlaoEHRfnkq5AhVxb7mfoBHMgPPoQfWqhAiEA
npkku9LfP2mlCCB85/zxsUehZOwoMVLlF2dSLWsrURs=
-----END RSA PRIVATE KEY-----
  • PCKS8 的pem格式頭:注意私鑰頭中沒有 RSA
//公鑰
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKzY3F21g7UWaTcIk/ltUy4LuuHK5Hhl
9ZpdxDr4+WA7pNwhCzhgBKbWUa+XotUYet841I2mYPJ6+6X32LwotF0CAwEAAQ==
-----END PUBLIC KEY-----
//私鑰
-----BEGIN PRIVATE KEY-----
MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEArNjcXbWDtRZpNwiT
+W1TLgu64crkeGX1ml3EOvj5YDuk3CELOGAEptZRr5ei1Rh63zjUjaZg8nr7pffY
vCi0XQIDAQABAkBUJ3GDHnD1peesJ70D37pz3LosXMBH7jxZ3/U+USH5O8M7ixzt
lpYa+ITcuL0MKxvVyVYw5Pvaui1+Nq9LV17xAiEA5VMCIgtn3WFEOpP+sVhHlqPc
VbTfE3g0RlDfUt/sQ5sCIQDA9AiJ65G3pHJJxYNc9RB/lVav3anFkbgnGKolPw8T
ZwIhAIs7QLpGzoLcgT5HiIVIIf7V8fqfXClH/AUNKOn6RkotAiEAo6HQY/ZMeyqQ
aZOA1aJWPXxOKZKX2R68xxsZn8Ccbl0CIQDck74y8SzLRSBB6JgVZ6NoWkWI5tyj
V8RFCZU9VUinQA==
-----END PRIVATE KEY-----

三.代碼示例

/** from: @jameszou707
 * 1.使用 node-rsa 生成 公鑰和私鑰,並進行服務端測試
 * @param pkcsType :pkcs版本(pkcs1/pkcs8),默認爲 pkcs8
 */
function generateKeyPair() {
  pkcsType = pkcsType ? pkcsType : 'pkcs8';//不爲空則 設置爲傳入參數,爲空則 設置爲 pkcs8
  console.log('pkcsType=' + pkcsType);

  //1.建立RSA對象,並指定 祕鑰長度
  var key = new NodeRSA({ b: pkcsSize });
  key.setOptions({ encryptionScheme: 'pkcs1' });//指定加密格式

  //2.生成 公鑰私鑰,使用 pkcs8標準,pem格式
  var publicPem = key.exportKey(pkcsType+'-public-pem');//制定輸出格式
  var privatePem = key.exportKey(pkcsType + '-private-pem');
  //console.log(key.$options);
  console.log(pkcsType+'公鑰:\n',publicPem);
  console.log(pkcsType+'私鑰:\n', privatePem);
  
  //---------------------測試1:服務端私鑰加密公鑰解密------------------------
  //3.使用 私鑰 加密 數據,並指定 字符編碼 和 字符集
  var encryData = key.encryptPrivate('服務端測試 -> jameszou love code~~~', 'base64','utf8');
  console.log('\n私鑰加密後的數據:\n', encryData); //加密後數據爲 base64 編碼

  //4.使用 公鑰 解密 數據,並指定字符集
  var decryptData = key.decryptPublic(encryData,'utf8');
  console.log('\n公鑰解密後的數據:\n', decryptData);

  //---------------------測試2:服務端加載公鑰後解密------------------------
  //1.建立RSA對象,並指定 祕鑰長度
  var key2 = new NodeRSA({ b: pkcsSize });
  //2.導入 公鑰,並指定使用 pkcs標準,pem格式
  key2.importKey(publicPem, pkcsType+'-public-pem');

  //3.使用 公鑰 解密數據
  var decrypted = key2.decryptPublic(encryData, 'utf8');  
  console.log('\n使用公鑰解密後的數據:\n',decrypted);
}

四.可能遇到的錯誤

  • 暫無
相關文章
相關標籤/搜索