generate ec and rsa keypiars for web
This commit is contained in:
parent
7591e3fbdd
commit
9537737d19
|
@ -0,0 +1,134 @@
|
|||
;(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
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "keypairs",
|
||||
"version": "1.0.0",
|
||||
"description": "Interchangeably use RSA & ECDSA with PEM and JWK for Signing, Verifying, CSR generation and JOSE. Ugh... that was a mouthful.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.coolaj86.com/coolaj86/keypairs.js"
|
||||
},
|
||||
"keywords": [
|
||||
"EC",
|
||||
"RSA",
|
||||
"ECDSA",
|
||||
"PEM",
|
||||
"JWK",
|
||||
"CSR",
|
||||
"JOSE"
|
||||
],
|
||||
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
|
||||
"license": "(MIT OR Apache-2.0)"
|
||||
}
|
Loading…
Reference in New Issue