使用WebCrypto API生成RSA密钥对,并使用密码保护它

时间:2016-07-16 16:47:46

标签: javascript cryptography private-key passphrase webcryptoapi

标题说明了一切。我想知道如何使用WebCrypto API生成RSA密钥对,以及如何使用密码来保护它,以便将其存储在数据库中。

2 个答案:

答案 0 :(得分:5)

您可以使用WebCrypto生成RSA密钥对并将其导出,如jwk(Json Web Key),pkcs#8(私有)或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

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 - exportKey

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

//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

//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);

答案 1 :(得分:3)

下载名为OpenCrypto的小型加密库,它允许您使用密码加密私钥到PKCS#8 RFC 5208 EncryptedPrivateKeyInfo格式。 Library只使用纯JavaScript,WebCrypto API和Promises。

以下是图书馆的链接:https://github.com/PeterBielak/OpenCrypto 该图书馆在MIT许可下可免费用于商业用途。请享用! ;)

这是一个简单的例子:

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);
    });

});