Generate RSA key pair using WebCrypto API and protect it with passphrase
标题说明了一切。我想知道如何使用 WebCrypto API 生成 RSA 密钥对,以及如何使用密码保护它,以便将其存储在数据库中。
您可以使用 WebCrypto 生成 RSA 密钥对并将其导出为 jwk (Json Web Key)、pkcs#8 (private) 或 spki (public)。请参阅 SubtleCrypto.exportKey() 和下面的示例代码
要以受保护的方式将密钥导出到外部系统,您可以使用如下标准:
-
PKCS#8:在 IETF Public Key-Cryptographic Standard Encryption #8 中定义的 PKCS#8 私钥格式。允许使用密码进行加密,但 WebCryptography exportKey 不支持。它提供 PrivateKeyInfo
-
PKCS#12:PKCS#12 是一种密钥库交换格式。它可以包含私钥、带有公钥的证书和证书链。内容使用密码进行 3DES 加密。文件的扩展名通常为 .pfx 或 .p12
很遗憾,WebCrypto 不支持以具有加密的通用格式导出,例如 PKCS#8 - 加密或 PKCS#12。您可以使用第三方库(如 forge
)以其中一种格式导出密钥
示例代码
WebCrypto RSASSA-PKCS1-v1_5 - generateKey
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | window.crypto.subtle.generateKey( { name:"RSASSA-PKCS1-v1_5", modulusLength: 2048, //can be 1024, 2048, or 4096 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: {name:"SHA-256"}, //can be"SHA-1","SHA-256","SHA-384", or"SHA-512" }, true, //whether the key is extractable (i.e. can be used in exportKey) ["sign","verify"] //can be any combination of"sign" and"verify" ) .then(function(key){ //returns a keypair object console.log(key); console.log(key.publicKey); console.log(key.privateKey); }) .catch(function(err){ console.error(err); }); |
WebCrypto RSASSA-PKCS1-v1_5 - 导出密钥
1 2 3 4 5 6 7 8 9 10 11 | window.crypto.subtle.exportKey( "pkcs8", //can be"jwk" (public or private),"spki" (public only), or"pkcs8" (private only) privateKey //can be a publicKey or privateKey, as long as extractable was true ) .then(function(keydata){ //returns the exported key data console.log(keydata); }) .catch(function(err){ console.error(err); }); |
锻造-PKCS#8
1 2 3 4 5 6 7 | //needed: wrap webcrypto pkcs#8 to forge privateKey (see doc) // encrypts a PrivateKeyInfo and outputs an EncryptedPrivateKeyInfo var encryptedPrivateKeyInfo = pki.encryptPrivateKeyInfo( privateKeyInfo, 'password', { algorithm: 'aes256', // 'aes128', 'aes192', 'aes256', '3des' }); |
// 将 EncryptedPrivateKeyInfo 转换为 PEM
var pem = pki.encryptedPrivateKeyToPem(encryptedPrivateKeyInfo);
锻造 - PKCS#12
1 2 3 4 5 6 7 8 9 | //needed: wrap webcrypto pkcs#8 to forge privateKey (see doc) // generate a p12 that can be imported by Chrome/Firefox // (requires the use of Triple DES instead of AES) var p12Asn1 = forge.pkcs12.toPkcs12Asn1(privateKey, certChain, password, {algorithm: '3des'}); // base64-encode p12 var p12Der = forge.asn1.toDer(p12Asn1).getBytes(); var p12b64 = forge.util.encode64(p12Der); |
下载这个名为 OpenCrypto 的小型加密库,它允许您使用密码将私钥加密为 PKCS #8 RFC 5208 EncryptedPrivateKeyInfo 格式。库仅使用纯 JavaScript、WebCrypto API 以及 Promises。
这里是图书馆的链接:https://github.com/PeterBielak/OpenCrypto
该库在 MIT 许可下可免费用于商业用途。享受! ;)
这是一个简单的例子:
1 2 3 4 5 6 7 8 9 | var crypt = new OpenCrypto(); crypt.getKeyPair().then(function(keyPair) { crypt.encryptPrivateKey(keyPair.privateKey,'securepassword').then(function(encryptedPrivateKey) { // This PEM Encrypted Private Key is fully compatiable with OpenSSL console.log(encryptedPrivateKey); }); }); |