generate ec and rsa keypiars for web
This commit is contained in:
		
							parent
							
								
									7591e3fbdd
								
							
						
					
					
						commit
						9537737d19
					
				
							
								
								
									
										134
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
							
								
								
									
										24
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user