/*global Promise*/ (function (exports) { 'use strict'; var Keypairs = exports.Keypairs = {}; Keypairs._stance = "We take the stance that if you're knowledgeable enough to" + " properly and securely use non-standard crypto then you shouldn't need Bluecrypt anyway."; Keypairs._universal = "Bluecrypt only supports crypto with standard cross-browser and cross-platform support."; Keypairs.generate = function (opts) { var wcOpts = {}; if (!opts) { opts = {}; } if (!opts.kty) { opts.kty = 'EC'; } // ECDSA has only the P curves and an associated bitlength if (/^EC/i.test(opts.kty)) { wcOpts.name = 'ECDSA'; if (!opts.namedCurve) { opts.namedCurve = 'P-256'; } wcOpts.namedCurve = opts.namedCurve; // true for supported curves if (/256/.test(wcOpts.namedCurve)) { wcOpts.namedCurve = 'P-256'; wcOpts.hash = { name: "SHA-256" }; } else if (/384/.test(wcOpts.namedCurve)) { wcOpts.namedCurve = 'P-384'; wcOpts.hash = { name: "SHA-384" }; } else { return Promise.Reject(new Error("'" + wcOpts.namedCurve + "' is not an NIST approved ECDSA namedCurve. " + " Please choose either 'P-256' or 'P-384'. " + Keypairs._stance)); } } else if (/^RSA$/i.test(opts.kty)) { // Support PSS? I don't think it's used for Let's Encrypt wcOpts.name = 'RSASSA-PKCS1-v1_5'; if (!opts.modulusLength) { opts.modulusLength = 2048; } wcOpts.modulusLength = opts.modulusLength; if (wcOpts.modulusLength >= 2048 && wcOpts.modulusLength < 3072) { // erring on the small side... for no good reason wcOpts.hash = { name: "SHA-256" }; } else if (wcOpts.modulusLength >= 3072 && wcOpts.modulusLength < 4096) { wcOpts.hash = { name: "SHA-384" }; } else if (wcOpts.modulusLength < 4097) { wcOpts.hash = { name: "SHA-512" }; } else { // Public key thumbprints should be paired with a hash of similar length, // so anything above SHA-512's keyspace would be left under-represented anyway. return Promise.Reject(new Error("'" + wcOpts.modulusLength + "' is not within the safe and universally" + " acceptable range of 2048-4096. Typically you should pick 2048, 3072, or 4096, though other values" + " divisible by 8 are allowed. " + Keypairs._stance)); } // TODO maybe allow this to be set to any of the standard values? wcOpts.publicExponent = new Uint8Array([0x01, 0x00, 0x01]); } else { return Promise.Reject(new Error("'" + opts.kty + "' is not a well-supported key type." + Keypairs._universal + " Please choose either 'EC' or 'RSA' keys.")); } var extractable = true; return window.crypto.subtle.generateKey( wcOpts , extractable , [ 'sign', 'verify' ] ).then(function (result) { return window.crypto.subtle.exportKey( "jwk" , result.privateKey ).then(function (privJwk) { // TODO remove console.log('private jwk:'); console.log(JSON.stringify(privJwk, null, 2)); return { privateKey: privJwk }; }); }); }; }(window));