寫在最前:此文的目的是介紹編碼,減少剛接觸時的彎路,所以內容且不做詳細累述
一.使用 node-rsa 進行非對稱加解密
-
因為
比特幣
中使用的非對稱加密,所以在npm中對比找到一個比較方便也直觀的庫:node-rsa。 -
非對稱加密的關鍵在於 有 公鑰 / 私鑰
用法:
a.生成一對公鑰私鑰
b.公鑰加密 -> 對應私鑰解密
c.私鑰加密 -> 對應公鑰解密 -
非對稱加密的常見應用方式
a.公鑰加密,發給私鑰擁有者,私鑰解密獲得明文。其它人用公鑰解不開
b.私鑰加密(簽名) -
公鑰的傳輸(混合加密)
a.使用對稱加密算法發布公鑰
b.使用對稱加密算法解密公鑰,再使用公鑰加密明文,發給私鑰擁有者
注:不能 公鑰加密公鑰解密 或 私鑰加密私鑰解密
二.幾個重要概念
1. DER 和 PEM 編碼
-
DER: 基於二進制的編碼。可以用CER或者CRT作為擴展名的的整數。比較合適的說法是“我有一個DER編碼的證書”,而不是“我有一個DER證書”。【編碼規則參考】
-
PEM: 基於ASCII(Base64)的編碼。OpenSSL 使用 PEM 文件格式存儲證書和密鑰。【編碼規則參考】
PEM 實質上是 base64 編碼的二進制內容,再進行增加或裁剪特殊字符-、\n、\r、begin信息、end信息等,如:
-----BEGIN CERTIFICATE-----
內容
-----END CERTIFICATE-----
注:本文中的私鑰公鑰都是用 pem 格式
2. PKCS(The Public-Key Cryptography Standards)
- 由美國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);
}
四.可能遇到的錯誤
- 暫無