| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  | /*! | 
					
						
							|  |  |  |  * rsa-compat | 
					
						
							|  |  |  |  * Copyright(c) 2016 AJ ONeal <aj@daplie.com> https://daplie.com
 | 
					
						
							|  |  |  |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 'use strict'; | 
					
						
							| 
									
										
										
										
											2016-08-03 22:23:07 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-29 02:39:10 -06:00
										 |  |  | try { | 
					
						
							|  |  |  |   require('buffer-v6-polyfill'); | 
					
						
							|  |  |  | } catch(e) { | 
					
						
							|  |  |  |   /* ignore */ | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-03 22:23:07 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  | var RSA = {}; | 
					
						
							|  |  |  | var NOBJ = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function create(deps) { | 
					
						
							|  |  |  |   var crypto = require('crypto'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   deps = deps || {}; | 
					
						
							|  |  |  |   deps.NOBJ = {}; | 
					
						
							|  |  |  |   deps.RSA = RSA; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |   try { | 
					
						
							|  |  |  |     RSA._URSA = require('ursa'); | 
					
						
							|  |  |  |   } catch(e) { | 
					
						
							|  |  |  |     // ignore
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |   RSA.utils = require('./lib/key-utils.js'); | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |   RSA.utils.toWebsafeBase64 = function (b64) { | 
					
						
							|  |  |  |     return b64.replace(/[+]/g, "-").replace(/\//g, "_").replace(/=/g,""); | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 05:36:39 -04:00
										 |  |  |   RSA.utils._forgeBytesToBuf = function (bytes) { | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |     var forge = require("node-forge"); | 
					
						
							|  |  |  |     return new Buffer(forge.util.bytesToHex(bytes), "hex"); | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2016-07-30 19:09:37 -04:00
										 |  |  |   RSA._internal = require('./lib/node');//.create(deps);
 | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 12:35:23 -04:00
										 |  |  |   RSA._thumbprintInput = function (n, e) { | 
					
						
							|  |  |  |     // #L147 const rsaThumbprintTemplate = `{"e":"%s","kty":"RSA","n":"%s"}`
 | 
					
						
							|  |  |  |     return new Buffer('{"e":"'+ e + '","kty":"RSA","n":"'+ n +'"}', 'ascii'); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   RSA.thumbprint = function (keypair) { | 
					
						
							|  |  |  |     var publicKeyJwk = RSA.exportPublicJwk(keypair); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!publicKeyJwk.e || !publicKeyJwk.n) { | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |       throw new Error("You must provide an RSA jwk with 'e' and 'n' (the public components)"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-02 12:35:23 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     var input = RSA._thumbprintInput(publicKeyJwk.n, publicKeyJwk.e); | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |     var base64Digest = crypto.createHash('sha256').update(input).digest('base64'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return RSA.utils.toWebsafeBase64(base64Digest); | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RSA.generateKeypair = function (length, exponent, options, cb) { | 
					
						
							| 
									
										
										
										
											2016-08-01 10:22:17 -04:00
										 |  |  |     if (!RSA._URSA && /arm|mips/i.test(require('os').arch) && !RSA._SLOW_WARN) { | 
					
						
							|  |  |  |       console.warn("================================================================"); | 
					
						
							|  |  |  |       console.warn("                         WARNING"); | 
					
						
							|  |  |  |       console.warn("================================================================"); | 
					
						
							|  |  |  |       console.warn(""); | 
					
						
							|  |  |  |       console.warn("WARNING: You are generating an RSA key using pure JavaScript on"); | 
					
						
							|  |  |  |       console.warn("         a VERY SLOW cpu. This could take DOZENS of minutes!"); | 
					
						
							|  |  |  |       console.warn(""); | 
					
						
							|  |  |  |       console.warn("         We recommend installing a C compiler and 'ursa'"); | 
					
						
							|  |  |  |       console.warn(""); | 
					
						
							|  |  |  |       console.warn("EXAMPLE:"); | 
					
						
							|  |  |  |       console.warn(""); | 
					
						
							|  |  |  |       console.warn("        sudo apt-get install build-essential && npm install ursa"); | 
					
						
							|  |  |  |       console.warn(""); | 
					
						
							|  |  |  |       console.warn("================================================================"); | 
					
						
							|  |  |  |       RSA._SLOW_WARN = true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |     var keypair = { | 
					
						
							|  |  |  |       privateKeyPem: undefined | 
					
						
							|  |  |  |     , publicKeyPem: undefined | 
					
						
							|  |  |  |     , privateKeyJwk: undefined | 
					
						
							|  |  |  |     , publicKeyJwk: undefined | 
					
						
							|  |  |  |     , _ursa: undefined | 
					
						
							| 
									
										
										
										
											2016-08-03 22:00:30 -04:00
										 |  |  |     , _ursaPublic: undefined | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |     , _forge: undefined | 
					
						
							| 
									
										
										
										
											2016-08-03 22:00:30 -04:00
										 |  |  |     , _forgePublic: undefined | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     options = options || NOBJ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-30 23:47:52 -04:00
										 |  |  |     RSA._internal.generateKeypair(length, exponent, options, function (err, keys) { | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |       if (false !== options.jwk || options.thumbprint) { | 
					
						
							|  |  |  |         keypair.privateKeyJwk = RSA._internal.exportPrivateJwk(keys); | 
					
						
							|  |  |  |         if (options.public) { | 
					
						
							|  |  |  |           keypair.publicKeyJwk = RSA._internal.exportPublicJwk(keys); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (options.pem) { | 
					
						
							|  |  |  |         keypair.privateKeyPem = RSA._internal.exportPrivatePem(keys); | 
					
						
							|  |  |  |         if (options.public) { | 
					
						
							|  |  |  |           keypair.publicKeyPem = RSA._internal.exportPublicPem(keys); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (options.thumprint) { | 
					
						
							| 
									
										
										
										
											2016-08-02 12:35:23 -04:00
										 |  |  |         keypair.thumbprint = RSA.thumbprint(keypair); | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (options.internal) { | 
					
						
							|  |  |  |         //keypair._ursa = undefined;
 | 
					
						
							|  |  |  |         //keypair._forge = undefined;
 | 
					
						
							|  |  |  |         keypair._ursa = keys._ursa; | 
					
						
							|  |  |  |         keypair._forge = keys._forge; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       cb(null, keypair); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |   RSA.import = function (keypair/*, options*/) { | 
					
						
							| 
									
										
										
										
											2016-08-02 16:42:44 -04:00
										 |  |  |     keypair = RSA._internal.import(keypair, { internal: true }); | 
					
						
							|  |  |  |     keypair = RSA._internal.importForge(keypair, { internal: true }); | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |     //options = options || NOBJ; // ignore
 | 
					
						
							| 
									
										
										
										
											2016-08-01 09:50:46 -04:00
										 |  |  |     if (keypair.privateKeyJwk || keypair.privateKeyPem || keypair._ursa || keypair._forge) { | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |       keypair.privateKeyJwk = RSA._internal.exportPrivateJwk(keypair, { internal: true }); | 
					
						
							|  |  |  |       //keypair.privateKeyPem = RSA._internal.exportPrivatePem(keypair, { internal: true });
 | 
					
						
							|  |  |  |       return keypair; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 09:50:46 -04:00
										 |  |  |     if (keypair.publicKeyJwk || keypair.publicKeyPem || keypair._ursaPublic || keypair._forgePublic) { | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |       keypair.publicKeyJwk = RSA._internal.exportPublicJwk(keypair, { internal: true }); | 
					
						
							|  |  |  |       //keypair.publicKeyPem = RSA._internal.exportPublicPem(keypair, { internal: true });
 | 
					
						
							|  |  |  |       return keypair; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     throw new Error('found neither private nor public keypair in any supported format'); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RSA._ursaGenerateSig = function (keypair, sha256Buf) { | 
					
						
							|  |  |  |     var sig = keypair._ursa.sign('sha256', sha256Buf); | 
					
						
							|  |  |  |     var sig64 = RSA.utils.toWebsafeBase64(sig.toString('base64')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return sig64; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   RSA._forgeGenerateSig = function (keypair, sha256Buf) { | 
					
						
							|  |  |  |     var forge = require('node-forge'); | 
					
						
							| 
									
										
										
										
											2016-08-01 04:12:01 -04:00
										 |  |  |     var bufF = forge.util.createBuffer(sha256Buf.toString('binary'), 'binary'); | 
					
						
							|  |  |  |     var md = { | 
					
						
							|  |  |  |       algorithm: 'sha256' | 
					
						
							|  |  |  |     , blockLength: 64 | 
					
						
							|  |  |  |     , digestLength: 20 | 
					
						
							|  |  |  |     , digest: function () { | 
					
						
							|  |  |  |         return bufF; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |     var sigF = keypair._forge.sign(md); | 
					
						
							|  |  |  |     var sig64 = RSA.utils.toWebsafeBase64( | 
					
						
							|  |  |  |       new Buffer(forge.util.bytesToHex(sigF), "hex").toString('base64') | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return sig64; | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2016-08-01 04:44:55 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   RSA.signJws = RSA.generateJws = RSA.generateSignatureJws = RSA.generateSignatureJwk = | 
					
						
							| 
									
										
										
										
											2018-03-20 21:33:26 -06:00
										 |  |  |   function (keypair, header, protect, payload) { | 
					
						
							|  |  |  |   // old   (keypair, payload, nonce)
 | 
					
						
							|  |  |  |     var nonce; | 
					
						
							| 
									
										
										
										
											2018-03-21 15:16:44 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     keypair = RSA._internal.import(keypair); | 
					
						
							|  |  |  |     keypair = RSA._internal.importForge(keypair); | 
					
						
							|  |  |  |     keypair.publicKeyJwk = RSA.exportPublicJwk(keypair); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-20 21:33:26 -06:00
										 |  |  |     if ('string' === typeof protect || ('undefined' === typeof protect && 'undefined' === typeof payload)) { | 
					
						
							|  |  |  |       console.warn("deprecation notice: new signature for signJws(keypair, header, protect, payload)"); | 
					
						
							|  |  |  |       // old API
 | 
					
						
							|  |  |  |       payload = header; | 
					
						
							|  |  |  |       nonce = protect; | 
					
						
							|  |  |  |       protect = undefined; | 
					
						
							|  |  |  |       header = { | 
					
						
							|  |  |  |         alg: "RS256" | 
					
						
							|  |  |  |       , jwk: keypair.publicKeyJwk | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |       protect = { nonce: nonce }; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Compute JWS signature
 | 
					
						
							|  |  |  |     var protectedHeader = ""; | 
					
						
							| 
									
										
										
										
											2018-03-20 21:33:26 -06:00
										 |  |  |     if (protect) { | 
					
						
							|  |  |  |       protectedHeader = JSON.stringify(protect); // { alg: prot.alg, nonce: prot.nonce, url: prot.url });
 | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |     } | 
					
						
							|  |  |  |     var protected64 = RSA.utils.toWebsafeBase64(new Buffer(protectedHeader).toString('base64')); | 
					
						
							|  |  |  |     var payload64 = RSA.utils.toWebsafeBase64(payload.toString('base64')); | 
					
						
							|  |  |  |     var raw = protected64 + "." + payload64; | 
					
						
							|  |  |  |     var sha256Buf = crypto.createHash('sha256').update(raw).digest(); | 
					
						
							|  |  |  |     var sig64; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (RSA._URSA) { | 
					
						
							|  |  |  |       sig64 = RSA._ursaGenerateSig(keypair, sha256Buf); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       sig64 = RSA._forgeGenerateSig(keypair, sha256Buf); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return { | 
					
						
							| 
									
										
										
										
											2018-03-20 21:33:26 -06:00
										 |  |  |       header: header | 
					
						
							| 
									
										
										
										
											2016-08-01 04:03:50 -04:00
										 |  |  |     , protected: protected64 | 
					
						
							|  |  |  |     , payload: payload64 | 
					
						
							|  |  |  |     , signature: sig64 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 05:36:39 -04:00
										 |  |  |   //
 | 
					
						
							|  |  |  |   // Generate CSR
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   RSA._generateCsrForge = function (keypair, names) { | 
					
						
							|  |  |  |     var forge = require('node-forge'); | 
					
						
							|  |  |  |     keypair = RSA._internal.importForge(keypair); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Create and sign the CSR
 | 
					
						
							|  |  |  |     var csr = forge.pki.createCertificationRequest(); | 
					
						
							|  |  |  |     csr.publicKey = keypair._forgePublic; | 
					
						
							|  |  |  |     // TODO should the commonName be shift()ed off so that it isn't also in altNames?
 | 
					
						
							|  |  |  |     // http://stackoverflow.com/questions/5935369/ssl-how-do-common-names-cn-and-subject-alternative-names-san-work-together
 | 
					
						
							|  |  |  |     csr.setSubject([{ name: 'commonName', value: names[0] }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var sans = names.map(function (name) { | 
					
						
							|  |  |  |       return { type: 2, value: name }; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     csr.setAttributes([{ | 
					
						
							|  |  |  |       name: 'extensionRequest', | 
					
						
							|  |  |  |       extensions: [{name: 'subjectAltName', altNames: sans}] | 
					
						
							|  |  |  |     }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // TODO wrap with node crypto (as done for signature)
 | 
					
						
							|  |  |  |     csr.sign(keypair._forge, forge.md.sha256.create()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return csr; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   RSA.generateCsrAsn1 = function (keypair, names) { | 
					
						
							|  |  |  |     var forge = require('node-forge'); | 
					
						
							|  |  |  |     var csr = RSA._generateCsrForge(keypair, names); | 
					
						
							|  |  |  |     var asn1 = forge.pki.certificationRequestToAsn1(csr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return RSA.utils._forgeBytesToBuf(asn1); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   RSA.generateCsrPem = function (keypair, names) { | 
					
						
							|  |  |  |     var forge = require('node-forge'); | 
					
						
							|  |  |  |     var csr = RSA._generateCsrForge(keypair, names); | 
					
						
							|  |  |  |     return forge.pki.certificationRequestToPem(csr); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   RSA.generateCsrDer = function (keypair, names) { | 
					
						
							|  |  |  |     var forge = require('node-forge'); | 
					
						
							|  |  |  |     var csr = RSA._generateCsrForge(keypair, names); | 
					
						
							|  |  |  |     var asn1 = forge.pki.certificationRequestToAsn1(csr); | 
					
						
							|  |  |  |     var der = forge.asn1.toDer(asn1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return RSA.utils._forgeBytesToBuf(der); | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2016-08-01 05:44:46 -04:00
										 |  |  |   RSA.generateCsrDerWeb64 =RSA.generateCsrWeb64 = function (keypair, names) { | 
					
						
							| 
									
										
										
										
											2016-08-01 05:36:39 -04:00
										 |  |  |     var buf = RSA.generateCsrDer(keypair, names); | 
					
						
							|  |  |  |     var b64 = buf.toString('base64'); | 
					
						
							|  |  |  |     var web64 = RSA.utils.toWebsafeBase64(b64); | 
					
						
							|  |  |  |     return web64; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-30 23:47:52 -04:00
										 |  |  |   RSA.exportPrivateKey = RSA._internal.exportPrivatePem; | 
					
						
							|  |  |  |   RSA.exportPublicKey = RSA._internal.exportPublicPem; | 
					
						
							| 
									
										
										
										
											2016-07-31 00:48:54 -04:00
										 |  |  |   RSA.exportPrivatePem = RSA._internal.exportPrivatePem; | 
					
						
							|  |  |  |   RSA.exportPublicPem = RSA._internal.exportPublicPem; | 
					
						
							| 
									
										
										
										
											2016-07-30 23:47:52 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   RSA.exportPrivateJwk = RSA._internal.exportPrivateJwk; | 
					
						
							|  |  |  |   RSA.exportPublicJwk = RSA._internal.exportPublicJwk; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-30 16:00:08 -04:00
										 |  |  |   return RSA; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports.RSA = create(/*require('./lib/node')*/); | 
					
						
							|  |  |  | //module.exports.RSA.create = create;
 |