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