;(function (exports) { 'use strict'; var PromiseA; try { /*global Promise*/ PromiseA = Promise; } catch(e) { PromiseA = require('bluebird'); } // https://stackoverflow.com/questions/40314257/export-webcrypto-key-to-pem-format function derToPem(keydata, pemName, privacy){ var keydataS = arrayBufferToString(keydata); var keydataB64 = window.btoa(keydataS); var keydataB64Pem = formatAsPem(keydataB64, pemName, privacy); return keydataB64Pem; } function arrayBufferToString( buffer ) { var binary = []; var bytes = new Uint8Array( buffer ); var len = bytes.byteLength; for (var i = 0; i < len; i++) { binary.push(String.fromCharCode( bytes[ i ] )); } return binary.join(''); } function formatAsPem(str, pemName, privacy) { var privstr = (privacy ? privacy + ' ' : ''); var finalString = '-----BEGIN ' + pemName + ' ' + privstr + 'KEY-----\n'; while (str.length > 0) { finalString += str.substring(0, 64) + '\n'; str = str.substring(64); } finalString = finalString + '-----END ' + pemName + ' ' + privstr + 'KEY-----'; return finalString; } var Keypairs = exports.Keypairs = { generate: function(opts) { if (!opts) { opts = {}; } if (!opts.type) { opts.type = 'EC'; } var supported = [ 'EC', 'RSA' ]; if (-1 === supported.indexOf(opts.type)) { return PromiseA.reject(new Error("'" + opts.type + "' not implemented. Try one of " + supported.join(', '))); } if ('EC' === opts.type) { return Keypairs._generateEc(opts); } if ('RSA' === opts.type) { return Keypairs._generateRsa(opts); } } , _generateEc: function (opts) { if (!opts.namedCurve) { opts.namedCurve = 'P-256'; } if ('P-256' !== opts.namedCurve) { console.warn("'" + opts.namedCurve + "' is not supported, but it _might_ happen to work anyway."); } // https://github.com/diafygi/webcrypto-examples#ecdsa---generatekey var extractable = true; return window.crypto.subtle.generateKey( { name: "ECDSA", namedCurve: opts.namedCurve } , extractable , [ 'sign', 'verify' ] ).then(function (result) { return window.crypto.subtle.exportKey( "jwk" , result.privateKey ).then(function (jwk) { return window.crypto.subtle.exportKey( "pkcs8" , result.privateKey ).then(function (keydata) { return { type: 'EC' , privateJwk: jwk , privatePem: derToPem(keydata, 'EC', 'PRIVATE') }; }); }); }); } , _generateRsa: function (opts) { if (!opts.bitlength) { opts.bitlength = 2048; } if (-1 === [ 2048, 4096 ].indexOf(opts.bitlength)) { return PromiseA.reject("opts.bitlength = (" + typeof opts.bitlength + ") " + opts.bitlength + ": Are you serious?"); } // https://github.com/diafygi/webcrypto-examples#rsa---generatekey var extractable = true; return window.crypto.subtle.generateKey( { name: "RSASSA-PKCS1-v1_5" , modulusLength: opts.bitlength , publicExponent: new Uint8Array([0x01, 0x00, 0x01]) , hash: { name: "SHA-256" } } , extractable , [ 'sign', 'verify' ] ).then(function (result) { return window.crypto.subtle.exportKey( "jwk" , result.privateKey ).then(function (jwk) { return window.crypto.subtle.exportKey( "pkcs8" , result.privateKey ).then(function (keydata) { return { type: 'RSA' , privateJwk: jwk , privatePem: derToPem(keydata, 'RSA', 'PRIVATE') }; }); }); }); } }; }('undefined' === typeof module ? window : module.exports)); // How we might use this // var Keypairs = require('keypairs').Keypairs