Generate RSA key pair using WebCrypto API and protect it with passphrase

ε祈祈猫儿з 提交于 2019-12-06 11:09:08

问题


title says it all. I was wondering how do I generate RSA key pair using WebCrypto API and how do I secure it with a passphrase so I can store it in a database.


回答1:


You can generate an RSA key pair with WebCrypto and export it as jwk (Json Web Key), pkcs#8 (private) or spki (public). See SubtleCrypto.exportKey() and the example code bellow

To export the key to an external system in a protected way you could use an standard like:

  • PKCS#8: The PKCS#8 private key format defined at IETF Public Key-Cryptographic Standard Encryption #8. allow encryption with a passphrase, but WebCryptography exportKey does not support it. It provides PrivateKeyInfo

  • PKCS#12: PKCS#12 is a keystore exchange format. It can contain private keys, certificates with the public key and the certification chain. The content is 3DES encrypted with a passphrase. Files are usually found with extension .pfx or .p12

Unfortunately WebCrypto does not support exporting in a common format with encryption such as PKCS#8 - encrypted or PKCS#12. You could export the keys in one of these formats using a third party library like forge

Example code

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

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

// converts an EncryptedPrivateKeyInfo to PEM var pem = pki.encryptedPrivateKeyToPem(encryptedPrivateKeyInfo);

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



回答2:


Download this little crypto library called OpenCrypto which allows you to encrypt private key using your passphrase into PKCS #8 RFC 5208 EncryptedPrivateKeyInfo format. Library uses only plain JavaScript, WebCrypto API and also Promises.

Here is the link for the library: https://github.com/PeterBielak/OpenCrypto The library is free for commercial use under MIT license. Enjoy! ;)

and here is a simple example:

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

});


来源:https://stackoverflow.com/questions/38413391/generate-rsa-key-pair-using-webcrypto-api-and-protect-it-with-passphrase

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!