forked from root/acme.js
		
	testing working
This commit is contained in:
		
							parent
							
								
									96b491a9c0
								
							
						
					
					
						commit
						2b0fce0869
					
				
							
								
								
									
										208
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										208
									
								
								README.md
									
									
									
									
									
								
							@ -1,25 +1,35 @@
 | 
				
			|||||||
# Bluecrypt™ [ACME.js](https://git.rootprojects.org/root/bluecrypt-acme.js) | A [Root](https://rootprojects.org/acme/) project
 | 
					# [ACME.js](https://git.rootprojects.org/root/bluecrypt-acme.js)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Free SSL Certificates from Let's Encrypt, right in your Web Browser
 | 
					Free SSL Certificates from Let's Encrypt, for Node.js and Web Browsers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Lightweight. Fast. Modern Crypto. Zero dependecies.
 | 
					Lightweight. Fast. Modern Crypto. Zero dependecies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(a port of [acme.js](https://git.coolaj86.com/coolaj86/acme-v2.js) to the browser)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Features
 | 
					# Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 15k gzipped | 55k minified | 88k (2,500 loc) source with comments |
 | 
					| 15k gzipped | 55k minified | 88k (2,500 loc) source with comments |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* [x] Let's Encrypt
 | 
					-   [x] Let's Encrypt v2.1+ (November 2019)
 | 
				
			||||||
  * [x] ACME draft 15 (supports POST-as-GET)
 | 
					    -   [x] ACME draft 15 (supports POST-as-GET)
 | 
				
			||||||
  * [x] Secure support for EC and RSA for account and server keys
 | 
					    -   [x] Secure support for EC and RSA for account and server keys
 | 
				
			||||||
  * [x] Simple and lightweight PEM, DER, ASN1, X509, and CSR implementations
 | 
					    -   [x] Simple and lightweight PEM, DER, ASN1, X509, and CSR implementations
 | 
				
			||||||
* [x] VanillaJS, Zero Dependencies
 | 
					-   [x] Supports International Domain Names (i.e. `.中国`)
 | 
				
			||||||
 | 
					-   [x] VanillaJS, Zero External Dependencies
 | 
				
			||||||
 | 
					    -   [x] Node.js
 | 
				
			||||||
 | 
					    -   [x] WebPack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Want Quick and Easy?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ACME.js is a low-level tool for building Let's Encrypt clients in Node and Browsers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you're looking for maximum convenience, try
 | 
				
			||||||
 | 
					[Greenlock.js](https://git.rootprojects.org/root/greenlock-express.js).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-   <https://git.rootprojects.org/root/greenlock-express.js>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Online Demos
 | 
					# Online Demos
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Greenlock for the Web <https://greenlock.domains>
 | 
					-   Greenlock for the Web <https://greenlock.domains>
 | 
				
			||||||
* Bluecrypt ACME Demo <https://rootprojects.org/acme/>
 | 
					-   ACME.js Demo <https://rootprojects.org/acme/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
We expect that our hosted versions will meet all of yours needs.
 | 
					We expect that our hosted versions will meet all of yours needs.
 | 
				
			||||||
If they don't, please open an issue to let us know why.
 | 
					If they don't, please open an issue to let us know why.
 | 
				
			||||||
@ -29,34 +39,59 @@ However, in keeping to our values we've made the source visible for others to in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# QuickStart
 | 
					# QuickStart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Bluecrypt ACME embeds [Keypairs.js](https://git.rootprojects.org/root/bluecrypt-keypairs.js)
 | 
					To make it easy to generate, encode, and decode keys and certificates,
 | 
				
			||||||
 | 
					ACME.js embeds [Keypairs.js](https://git.rootprojects.org/root/bluecrypt-keypairs.js)
 | 
				
			||||||
and [CSR.js](https://git.rootprojects.org/root/bluecrypt-csr.js)
 | 
					and [CSR.js](https://git.rootprojects.org/root/bluecrypt-csr.js)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`bluecrypt-acme.js`
 | 
					## Node.js
 | 
				
			||||||
```html
 | 
					
 | 
				
			||||||
<script src="https://rootprojects.org/acme/bluecrypt-acme.js"></script>
 | 
					```js
 | 
				
			||||||
 | 
					var ACME = require('@root/acme');
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`bluecrypt-acme.min.js`
 | 
					## WebPack
 | 
				
			||||||
```html
 | 
					
 | 
				
			||||||
<script src="https://rootprojects.org/acme/bluecrypt-acme.min.js"></script>
 | 
					```js
 | 
				
			||||||
 | 
					var ACME = require('@root/acme');
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can see `index.html` and `app.js` in the repo for full example usage.
 | 
					## Vanilla JS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Instantiate Bluecrypt ACME
 | 
					```js
 | 
				
			||||||
 | 
					var ACME = window.ACME;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Although built for Let's Encrypt, Bluecrypt ACME will work with any server
 | 
					`acme.js`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<script src="https://unpkg.com/@root/acme/dist/acme.js"></script>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`acme.min.js`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<script src="https://unpkg.com/@root/acme/dist/acme.min.js"></script>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can see `tests/index.js`, `examples/index.html`, `examples/app.js` in the repo for full example usage.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Instantiate ACME.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Although built for Let's Encrypt, ACME.js will work with any server
 | 
				
			||||||
that supports draft-15 of the ACME spec (includes POST-as-GET support).
 | 
					that supports draft-15 of the ACME spec (includes POST-as-GET support).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The `init()` method takes a _directory url_ and initializes internal state according to its response.
 | 
					The `init()` method takes a _directory url_ and initializes internal state according to its response.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```js
 | 
					```js
 | 
				
			||||||
var acme = ACME.create({});
 | 
					var acme = ACME.create({});
 | 
				
			||||||
acme.init('https://acme-staging-v02.api.letsencrypt.org/directory').then(function () {
 | 
					acme.init('https://acme-staging-v02.api.letsencrypt.org/directory').then(
 | 
				
			||||||
  // Ready to use, show page
 | 
						function() {
 | 
				
			||||||
  $('body').hidden = false;
 | 
							// Ready to use, show page
 | 
				
			||||||
});
 | 
							$('body').hidden = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Create ACME Account with Let's Encrypt
 | 
					### Create ACME Account with Let's Encrypt
 | 
				
			||||||
@ -69,20 +104,26 @@ A public account key must be registered before an SSL certificate can be request
 | 
				
			|||||||
var accountPrivateKey;
 | 
					var accountPrivateKey;
 | 
				
			||||||
var account;
 | 
					var account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Keypairs.generate({ kty: 'EC' }).then(function (pair) {
 | 
					Keypairs.generate({ kty: 'EC' }).then(function(pair) {
 | 
				
			||||||
  accountPrivateKey = pair.private;
 | 
						accountPrivateKey = pair.private;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return acme.accounts.create({
 | 
						return acme.accounts
 | 
				
			||||||
    agreeToTerms: function (tos) {
 | 
							.create({
 | 
				
			||||||
      if (window.confirm("Do you agree to the Bluecrypt and Let's Encrypt Terms of Service?")) {
 | 
								agreeToTerms: function(tos) {
 | 
				
			||||||
        return Promise.resolve(tos);
 | 
									if (
 | 
				
			||||||
      }
 | 
										window.confirm(
 | 
				
			||||||
    }
 | 
											"Do you agree to the ACME.js and Let's Encrypt Terms of Service?"
 | 
				
			||||||
  , accountKeypair: { privateKeyJwk: pair.private }
 | 
										)
 | 
				
			||||||
  , email: $('.js-email-input').value
 | 
									) {
 | 
				
			||||||
  }).then(function (_account) {
 | 
										return Promise.resolve(tos);
 | 
				
			||||||
    account = _account;
 | 
									}
 | 
				
			||||||
  });
 | 
								},
 | 
				
			||||||
 | 
								accountKeypair: { privateKeyJwk: pair.private },
 | 
				
			||||||
 | 
								email: $('.js-email-input').value
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							.then(function(_account) {
 | 
				
			||||||
 | 
								account = _account;
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -97,26 +138,27 @@ is a required part of the process, which requires `set` and `remove` callbacks/p
 | 
				
			|||||||
```js
 | 
					```js
 | 
				
			||||||
var serverPrivateKey;
 | 
					var serverPrivateKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Keypairs.generate({ kty: 'EC' }).then(function (pair) {
 | 
					Keypairs.generate({ kty: 'EC' }).then(function(pair) {
 | 
				
			||||||
  serverPrivateKey = pair.private;
 | 
						serverPrivateKey = pair.private;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return acme.certificates.create({
 | 
					 | 
				
			||||||
    agreeToTerms: function (tos) {
 | 
					 | 
				
			||||||
      return tos;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  , account: account
 | 
					 | 
				
			||||||
  , accountKeypair: { privateKeyJwk: accountPrivateKey }
 | 
					 | 
				
			||||||
  , serverKeypair: { privateKeyJwk: serverPrivateKey }
 | 
					 | 
				
			||||||
  , domains: ['example.com','www.example.com']
 | 
					 | 
				
			||||||
  , challenges: challenges // must be implemented
 | 
					 | 
				
			||||||
  , skipDryRun: true
 | 
					 | 
				
			||||||
  }).then(function (results) {
 | 
					 | 
				
			||||||
    console.log('Got SSL Certificate:');
 | 
					 | 
				
			||||||
    console.log(results.expires);
 | 
					 | 
				
			||||||
    console.log(results.cert);
 | 
					 | 
				
			||||||
    console.log(results.chain);
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return acme.certificates
 | 
				
			||||||
 | 
							.create({
 | 
				
			||||||
 | 
								agreeToTerms: function(tos) {
 | 
				
			||||||
 | 
									return tos;
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								account: account,
 | 
				
			||||||
 | 
								accountKeypair: { privateKeyJwk: accountPrivateKey },
 | 
				
			||||||
 | 
								serverKeypair: { privateKeyJwk: serverPrivateKey },
 | 
				
			||||||
 | 
								domains: ['example.com', 'www.example.com'],
 | 
				
			||||||
 | 
								challenges: challenges, // must be implemented
 | 
				
			||||||
 | 
								skipDryRun: true
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							.then(function(results) {
 | 
				
			||||||
 | 
								console.log('Got SSL Certificate:');
 | 
				
			||||||
 | 
								console.log(results.expires);
 | 
				
			||||||
 | 
								console.log(results.cert);
 | 
				
			||||||
 | 
								console.log(results.chain);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -131,22 +173,42 @@ reserved for server-side plugins.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```js
 | 
					```js
 | 
				
			||||||
var challenges = {
 | 
					var challenges = {
 | 
				
			||||||
  'http-01': {
 | 
						'http-01': {
 | 
				
			||||||
    set: function (opts) {
 | 
							set: function(opts) {
 | 
				
			||||||
      console.info('http-01 set challenge:');
 | 
								console.info('http-01 set challenge:');
 | 
				
			||||||
      console.info(opts.challengeUrl);
 | 
								console.info(opts.challengeUrl);
 | 
				
			||||||
      console.info(opts.keyAuthorization);
 | 
								console.info(opts.keyAuthorization);
 | 
				
			||||||
      while (!window.confirm("Upload the challenge file before continuing.")) {}
 | 
								while (
 | 
				
			||||||
      return Promise.resolve();
 | 
									!window.confirm('Upload the challenge file before continuing.')
 | 
				
			||||||
    }
 | 
								) {}
 | 
				
			||||||
  , remove: function (opts) {
 | 
								return Promise.resolve();
 | 
				
			||||||
      console.log('http-01 remove challenge:', opts.challengeUrl);
 | 
							},
 | 
				
			||||||
      return Promise.resolve();
 | 
							remove: function(opts) {
 | 
				
			||||||
    }
 | 
								console.log('http-01 remove challenge:', opts.challengeUrl);
 | 
				
			||||||
  }
 | 
								return Promise.resolve();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# IDN - International Domain Names
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Convert domain names to `punycode` before creating the certificate:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					var punycode = require('punycode');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					acme.certificates.create({
 | 
				
			||||||
 | 
						// ...
 | 
				
			||||||
 | 
						domains: ['example.com', 'www.example.com'].map(function(name) {
 | 
				
			||||||
 | 
							return punycode.toASCII(name);
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The punycode library itself is lightweight and dependency-free.
 | 
				
			||||||
 | 
					It is available both in node and for browsers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Full Documentation
 | 
					# Full Documentation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
See [acme.js](https://git.coolaj86.com/coolaj86/acme-v2.js).
 | 
					See [acme.js](https://git.coolaj86.com/coolaj86/acme-v2.js).
 | 
				
			||||||
@ -175,16 +237,16 @@ We also offer consulting for all-things-ACME and Let's Encrypt.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Legal & Rules of the Road
 | 
					# Legal & Rules of the Road
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Bluecrypt™ and Greenlock™ are [trademarks](https://rootprojects.org/legal/#trademark) of AJ ONeal
 | 
					Greenlock™ is a [trademark](https://rootprojects.org/legal/#trademark) of AJ ONeal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The rule of thumb is "attribute, but don't confuse". For example:
 | 
					The rule of thumb is "attribute, but don't confuse". For example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> Built with [Bluecrypt ACME](https://git.rootprojects.org/root/bluecrypt-acme.js) (a [Root](https://rootprojects.org) project).
 | 
					> Built with [ACME.js](https://git.rootprojects.org/root/bluecrypt-acme.js) (a [Root](https://rootprojects.org) project).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Please [contact us](mailto:aj@therootcompany.com) if have any questions in regards to our trademark,
 | 
					Please [contact us](mailto:aj@therootcompany.com) if have any questions in regards to our trademark,
 | 
				
			||||||
attribution, and/or visible source policies. We want to build great software and a great community.
 | 
					attribution, and/or visible source policies. We want to build great software and a great community.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[bluecrypt.js](https://git.coolaj86.com/coolaj86/bluecrypt.js) |
 | 
					[ACME.js](https://git.rootprojects.org/root/acme.js) |
 | 
				
			||||||
MPL-2.0 |
 | 
					MPL-2.0 |
 | 
				
			||||||
[Terms of Use](https://therootcompany.com/legal/#terms) |
 | 
					[Terms of Use](https://therootcompany.com/legal/#terms) |
 | 
				
			||||||
[Privacy Policy](https://therootcompany.com/legal/#privacy)
 | 
					[Privacy Policy](https://therootcompany.com/legal/#privacy)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										174
									
								
								examples/server.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								examples/server.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,174 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var crypto = require('crypto');
 | 
				
			||||||
 | 
					//var dnsjs = require('dns-suite');
 | 
				
			||||||
 | 
					var dig = require('dig.js/dns-request');
 | 
				
			||||||
 | 
					var request = require('util').promisify(require('@root/request'));
 | 
				
			||||||
 | 
					var express = require('express');
 | 
				
			||||||
 | 
					var app = express();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var nameservers = require('dns').getServers();
 | 
				
			||||||
 | 
					var index = crypto.randomBytes(2).readUInt16BE(0) % nameservers.length;
 | 
				
			||||||
 | 
					var nameserver = nameservers[index];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app.use('/', express.static(__dirname));
 | 
				
			||||||
 | 
					app.use('/api', express.json());
 | 
				
			||||||
 | 
					app.get('/api/dns/:domain', function(req, res, next) {
 | 
				
			||||||
 | 
						var domain = req.params.domain;
 | 
				
			||||||
 | 
						var casedDomain = domain
 | 
				
			||||||
 | 
							.toLowerCase()
 | 
				
			||||||
 | 
							.split('')
 | 
				
			||||||
 | 
							.map(function(ch) {
 | 
				
			||||||
 | 
								// dns0x20 takes advantage of the fact that the binary operation for toUpperCase is
 | 
				
			||||||
 | 
								// ch = ch | 0x20;
 | 
				
			||||||
 | 
								return Math.round(Math.random()) % 2 ? ch : ch.toUpperCase();
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							.join('');
 | 
				
			||||||
 | 
						var typ = req.query.type;
 | 
				
			||||||
 | 
						var query = {
 | 
				
			||||||
 | 
							header: {
 | 
				
			||||||
 | 
								id: crypto.randomBytes(2).readUInt16BE(0),
 | 
				
			||||||
 | 
								qr: 0,
 | 
				
			||||||
 | 
								opcode: 0,
 | 
				
			||||||
 | 
								aa: 0, // Authoritative-Only
 | 
				
			||||||
 | 
								tc: 0, // NA
 | 
				
			||||||
 | 
								rd: 1, // Recurse
 | 
				
			||||||
 | 
								ra: 0, // NA
 | 
				
			||||||
 | 
								rcode: 0 // NA
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							question: [
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									name: casedDomain,
 | 
				
			||||||
 | 
									//, type: typ || 'A'
 | 
				
			||||||
 | 
									typeName: typ || 'A',
 | 
				
			||||||
 | 
									className: 'IN'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						var opts = {
 | 
				
			||||||
 | 
							onError: function(err) {
 | 
				
			||||||
 | 
								next(err);
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onMessage: function(packet) {
 | 
				
			||||||
 | 
								var fail0x20;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (packet.id !== query.id) {
 | 
				
			||||||
 | 
									console.error(
 | 
				
			||||||
 | 
										"[SECURITY] ignoring packet for '" +
 | 
				
			||||||
 | 
											packet.question[0].name +
 | 
				
			||||||
 | 
											"' due to mismatched id"
 | 
				
			||||||
 | 
									);
 | 
				
			||||||
 | 
									console.error(packet);
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								packet.question.forEach(function(q) {
 | 
				
			||||||
 | 
									// if (-1 === q.name.lastIndexOf(cli.casedQuery))
 | 
				
			||||||
 | 
									if (q.name !== casedDomain) {
 | 
				
			||||||
 | 
										fail0x20 = q.name;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								['question', 'answer', 'authority', 'additional'].forEach(function(
 | 
				
			||||||
 | 
									group
 | 
				
			||||||
 | 
								) {
 | 
				
			||||||
 | 
									(packet[group] || []).forEach(function(a) {
 | 
				
			||||||
 | 
										var an = a.name;
 | 
				
			||||||
 | 
										var i = domain
 | 
				
			||||||
 | 
											.toLowerCase()
 | 
				
			||||||
 | 
											.lastIndexOf(a.name.toLowerCase()); // answer is something like ExAMPle.cOM and query was wWw.ExAMPle.cOM
 | 
				
			||||||
 | 
										var j = a.name
 | 
				
			||||||
 | 
											.toLowerCase()
 | 
				
			||||||
 | 
											.lastIndexOf(domain.toLowerCase()); // answer is something like www.ExAMPle.cOM and query was ExAMPle.cOM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// it's important to note that these should only relpace changes in casing that we expected
 | 
				
			||||||
 | 
										// any abnormalities should be left intact to go "huh?" about
 | 
				
			||||||
 | 
										// TODO detect abnormalities?
 | 
				
			||||||
 | 
										if (-1 !== i) {
 | 
				
			||||||
 | 
											// "EXamPLE.cOm".replace("wWw.EXamPLE.cOm".substr(4), "www.example.com".substr(4))
 | 
				
			||||||
 | 
											a.name = a.name.replace(
 | 
				
			||||||
 | 
												casedDomain.substr(i),
 | 
				
			||||||
 | 
												domain.substr(i)
 | 
				
			||||||
 | 
											);
 | 
				
			||||||
 | 
										} else if (-1 !== j) {
 | 
				
			||||||
 | 
											// "www.example.com".replace("EXamPLE.cOm", "example.com")
 | 
				
			||||||
 | 
											a.name =
 | 
				
			||||||
 | 
												a.name.substr(0, j) +
 | 
				
			||||||
 | 
												a.name.substr(j).replace(casedDomain, domain);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// NOTE: right now this assumes that anything matching the query matches all the way to the end
 | 
				
			||||||
 | 
										// it does not handle the case of a record for example.com.uk being returned in response to a query for www.example.com correctly
 | 
				
			||||||
 | 
										// (but I don't think it should need to)
 | 
				
			||||||
 | 
										if (a.name.length !== an.length) {
 | 
				
			||||||
 | 
											console.error(
 | 
				
			||||||
 | 
												"[ERROR] question / answer mismatch: '" +
 | 
				
			||||||
 | 
													an +
 | 
				
			||||||
 | 
													"' != '" +
 | 
				
			||||||
 | 
													a.length +
 | 
				
			||||||
 | 
													"'"
 | 
				
			||||||
 | 
											);
 | 
				
			||||||
 | 
											console.error(a);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (fail0x20) {
 | 
				
			||||||
 | 
									console.warn(
 | 
				
			||||||
 | 
										";; Warning: DNS 0x20 security not implemented (or packet spoofed). Queried '" +
 | 
				
			||||||
 | 
											casedDomain +
 | 
				
			||||||
 | 
											"' but got response for '" +
 | 
				
			||||||
 | 
											fail0x20 +
 | 
				
			||||||
 | 
											"'."
 | 
				
			||||||
 | 
									);
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								res.send({
 | 
				
			||||||
 | 
									header: packet.header,
 | 
				
			||||||
 | 
									question: packet.question,
 | 
				
			||||||
 | 
									answer: packet.answer,
 | 
				
			||||||
 | 
									authority: packet.authority,
 | 
				
			||||||
 | 
									additional: packet.additional,
 | 
				
			||||||
 | 
									edns_options: packet.edns_options
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onListening: function() {},
 | 
				
			||||||
 | 
							onSent: function(/*res*/) {},
 | 
				
			||||||
 | 
							onTimeout: function(res) {
 | 
				
			||||||
 | 
								console.error('dns timeout:', res);
 | 
				
			||||||
 | 
								next(new Error('DNS timeout - no response'));
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onClose: function() {},
 | 
				
			||||||
 | 
							//, mdns: cli.mdns
 | 
				
			||||||
 | 
							nameserver: nameserver,
 | 
				
			||||||
 | 
							port: 53,
 | 
				
			||||||
 | 
							timeout: 2000
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dig.resolveJson(query, opts);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					app.get('/api/http', function(req, res) {
 | 
				
			||||||
 | 
						var url = req.query.url;
 | 
				
			||||||
 | 
						return request({ method: 'GET', url: url }).then(function(resp) {
 | 
				
			||||||
 | 
							res.send(resp.body);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					app.get('/api/_acme_api_', function(req, res) {
 | 
				
			||||||
 | 
						res.send({ success: true });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = app;
 | 
				
			||||||
 | 
					if (require.main === module) {
 | 
				
			||||||
 | 
						// curl -L http://localhost:3000/api/dns/example.com?type=A
 | 
				
			||||||
 | 
						console.info('Listening on localhost:3000');
 | 
				
			||||||
 | 
						app.listen(3000);
 | 
				
			||||||
 | 
						console.info('Try this:');
 | 
				
			||||||
 | 
						console.info("\tcurl -L 'http://localhost:3000/api/_acme_api_/'");
 | 
				
			||||||
 | 
						console.info(
 | 
				
			||||||
 | 
							"\tcurl -L 'http://localhost:3000/api/dns/example.com?type=A'"
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						console.info(
 | 
				
			||||||
 | 
							"\tcurl -L 'http://localhost:3000/api/http/?url=https://example.com'"
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										123
									
								
								lib/acme.js
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								lib/acme.js
									
									
									
									
									
								
							@ -5,10 +5,11 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
/* globals Promise */
 | 
					/* globals Promise */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require('@root/encoding/bytes');
 | 
				
			||||||
 | 
					var Enc = require('@root/encoding/base64');
 | 
				
			||||||
var ACME = module.exports;
 | 
					var ACME = module.exports;
 | 
				
			||||||
//var Keypairs = exports.Keypairs || {};
 | 
					//var Keypairs = exports.Keypairs || {};
 | 
				
			||||||
//var CSR = exports.CSR;
 | 
					//var CSR = exports.CSR;
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					 | 
				
			||||||
var sha2 = require('./node/sha2.js');
 | 
					var sha2 = require('./node/sha2.js');
 | 
				
			||||||
var http = require('./node/http.js');
 | 
					var http = require('./node/http.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -37,21 +38,22 @@ ACME.challengePrefixes = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
ACME.challengeTests = {
 | 
					ACME.challengeTests = {
 | 
				
			||||||
	'http-01': function(me, auth) {
 | 
						'http-01': function(me, auth) {
 | 
				
			||||||
		return me.http01(auth).then(function(keyAuth) {
 | 
							var ch = auth.challenge;
 | 
				
			||||||
 | 
							return me.http01(ch).then(function(keyAuth) {
 | 
				
			||||||
			var err;
 | 
								var err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// TODO limit the number of bytes that are allowed to be downloaded
 | 
								// TODO limit the number of bytes that are allowed to be downloaded
 | 
				
			||||||
			if (auth.keyAuthorization === (keyAuth || '').trim()) {
 | 
								if (ch.keyAuthorization === (keyAuth || '').trim()) {
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			err = new Error(
 | 
								err = new Error(
 | 
				
			||||||
				'Error: Failed HTTP-01 Pre-Flight / Dry Run.\n' +
 | 
									'Error: Failed HTTP-01 Pre-Flight / Dry Run.\n' +
 | 
				
			||||||
					"curl '" +
 | 
										"curl '" +
 | 
				
			||||||
					auth.challengeUrl +
 | 
										ch.challengeUrl +
 | 
				
			||||||
					"'\n" +
 | 
										"'\n" +
 | 
				
			||||||
					"Expected: '" +
 | 
										"Expected: '" +
 | 
				
			||||||
					auth.keyAuthorization +
 | 
										ch.keyAuthorization +
 | 
				
			||||||
					"'\n" +
 | 
										"'\n" +
 | 
				
			||||||
					"Got: '" +
 | 
										"Got: '" +
 | 
				
			||||||
					keyAuth +
 | 
										keyAuth +
 | 
				
			||||||
@ -64,12 +66,13 @@ ACME.challengeTests = {
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	'dns-01': function(me, auth) {
 | 
						'dns-01': function(me, auth) {
 | 
				
			||||||
		// remove leading *. on wildcard domains
 | 
							// remove leading *. on wildcard domains
 | 
				
			||||||
		return me.dns01(auth).then(function(ans) {
 | 
							var ch = auth.challenge;
 | 
				
			||||||
 | 
							return me.dns01(ch).then(function(ans) {
 | 
				
			||||||
			var err;
 | 
								var err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (
 | 
								if (
 | 
				
			||||||
				ans.answer.some(function(txt) {
 | 
									ans.answer.some(function(txt) {
 | 
				
			||||||
					return auth.dnsAuthorization === txt.data[0];
 | 
										return ch.dnsAuthorization === txt.data[0];
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
			) {
 | 
								) {
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
@ -78,9 +81,9 @@ ACME.challengeTests = {
 | 
				
			|||||||
			err = new Error(
 | 
								err = new Error(
 | 
				
			||||||
				'Error: Failed DNS-01 Pre-Flight Dry Run.\n' +
 | 
									'Error: Failed DNS-01 Pre-Flight Dry Run.\n' +
 | 
				
			||||||
					"dig TXT '" +
 | 
										"dig TXT '" +
 | 
				
			||||||
					auth.dnsHost +
 | 
										ch.dnsHost +
 | 
				
			||||||
					"' does not return '" +
 | 
										"' does not return '" +
 | 
				
			||||||
					auth.dnsAuthorization +
 | 
										ch.dnsAuthorization +
 | 
				
			||||||
					"'\n" +
 | 
										"'\n" +
 | 
				
			||||||
					'See https://git.coolaj86.com/coolaj86/acme-v2.js/issues/4'
 | 
										'See https://git.coolaj86.com/coolaj86/acme-v2.js/issues/4'
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
@ -565,16 +568,21 @@ ACME._challengeToAuth = function(
 | 
				
			|||||||
			// For backwards compat with the v2.7 plugins
 | 
								// For backwards compat with the v2.7 plugins
 | 
				
			||||||
			auth.challenge = auth;
 | 
								auth.challenge = auth;
 | 
				
			||||||
			// TODO can we use just { challenge: auth }?
 | 
								// TODO can we use just { challenge: auth }?
 | 
				
			||||||
			auth.request = function() {
 | 
								// auth.request = ;
 | 
				
			||||||
				// TODO see https://git.rootprojects.org/root/acme.js/issues/###
 | 
					
 | 
				
			||||||
				console.warn(
 | 
								// TODO get rid of no-challenge backwards compat challenge
 | 
				
			||||||
					"[warn] deprecated use of request on '" +
 | 
								return {
 | 
				
			||||||
						auth.type +
 | 
									challenge: auth,
 | 
				
			||||||
						"' challenge object. Receive from challenger.init() instead."
 | 
									request: function() {
 | 
				
			||||||
				);
 | 
										// TODO see https://git.rootprojects.org/root/acme.js/issues/###
 | 
				
			||||||
				me.request.apply(null, arguments);
 | 
										console.warn(
 | 
				
			||||||
 | 
											"[warn] deprecated use of request on '" +
 | 
				
			||||||
 | 
												auth.type +
 | 
				
			||||||
 | 
												"' challenge object. Receive from challenger.init() instead."
 | 
				
			||||||
 | 
										);
 | 
				
			||||||
 | 
										me.request.apply(null, arguments);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			return auth;
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -592,8 +600,9 @@ ACME._postChallenge = function(me, options, auth) {
 | 
				
			|||||||
	var MAX_POLL = me.retryPoll || 8;
 | 
						var MAX_POLL = me.retryPoll || 8;
 | 
				
			||||||
	var MAX_PEND = me.retryPending || 4;
 | 
						var MAX_PEND = me.retryPending || 4;
 | 
				
			||||||
	var count = 0;
 | 
						var count = 0;
 | 
				
			||||||
 | 
						var ch = auth.challenge;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var altname = ACME._untame(auth.identifier.value, auth.wildcard);
 | 
						var altname = ACME._untame(ch.identifier.value, ch.wildcard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
   POST /acme/authz/1234 HTTP/1.1
 | 
					   POST /acme/authz/1234 HTTP/1.1
 | 
				
			||||||
@ -619,7 +628,7 @@ ACME._postChallenge = function(me, options, auth) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return ACME._jwsRequest(me, {
 | 
							return ACME._jwsRequest(me, {
 | 
				
			||||||
			options: options,
 | 
								options: options,
 | 
				
			||||||
			url: auth.url,
 | 
								url: ch.url,
 | 
				
			||||||
			protected: { kid: options._kid },
 | 
								protected: { kid: options._kid },
 | 
				
			||||||
			payload: Enc.strToBuf(JSON.stringify({ status: 'deactivated' }))
 | 
								payload: Enc.strToBuf(JSON.stringify({ status: 'deactivated' }))
 | 
				
			||||||
		}).then(function(resp) {
 | 
							}).then(function(resp) {
 | 
				
			||||||
@ -651,11 +660,11 @@ ACME._postChallenge = function(me, options, auth) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		// TODO POST-as-GET
 | 
							// TODO POST-as-GET
 | 
				
			||||||
		return me
 | 
							return me
 | 
				
			||||||
			.request({ method: 'GET', url: auth.url, json: true })
 | 
								.request({ method: 'GET', url: ch.url, json: true })
 | 
				
			||||||
			.then(function(resp) {
 | 
								.then(function(resp) {
 | 
				
			||||||
				if ('processing' === resp.body.status) {
 | 
									if ('processing' === resp.body.status) {
 | 
				
			||||||
					if (me.debug) {
 | 
										if (me.debug) {
 | 
				
			||||||
						console.debug('poll: again', auth.url);
 | 
											console.debug('poll: again', ch.url);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					return ACME._wait(RETRY_INTERVAL).then(pollStatus);
 | 
										return ACME._wait(RETRY_INTERVAL).then(pollStatus);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@ -668,7 +677,7 @@ ACME._postChallenge = function(me, options, auth) {
 | 
				
			|||||||
							.then(respondToChallenge);
 | 
												.then(respondToChallenge);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					if (me.debug) {
 | 
										if (me.debug) {
 | 
				
			||||||
						console.debug('poll: again', auth.url);
 | 
											console.debug('poll: again', ch.url);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					return ACME._wait(RETRY_INTERVAL).then(respondToChallenge);
 | 
										return ACME._wait(RETRY_INTERVAL).then(respondToChallenge);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@ -719,7 +728,7 @@ ACME._postChallenge = function(me, options, auth) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return ACME._jwsRequest(me, {
 | 
							return ACME._jwsRequest(me, {
 | 
				
			||||||
			options: options,
 | 
								options: options,
 | 
				
			||||||
			url: auth.url,
 | 
								url: ch.url,
 | 
				
			||||||
			protected: { kid: options._kid },
 | 
								protected: { kid: options._kid },
 | 
				
			||||||
			payload: Enc.strToBuf(JSON.stringify({}))
 | 
								payload: Enc.strToBuf(JSON.stringify({}))
 | 
				
			||||||
		}).then(function(resp) {
 | 
							}).then(function(resp) {
 | 
				
			||||||
@ -736,13 +745,14 @@ ACME._postChallenge = function(me, options, auth) {
 | 
				
			|||||||
	return respondToChallenge();
 | 
						return respondToChallenge();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
ACME._setChallenge = function(me, options, auth) {
 | 
					ACME._setChallenge = function(me, options, auth) {
 | 
				
			||||||
 | 
						var ch = auth.challenge;
 | 
				
			||||||
	return Promise.resolve().then(function() {
 | 
						return Promise.resolve().then(function() {
 | 
				
			||||||
		var challengers = options.challenges || {};
 | 
							var challengers = options.challenges || {};
 | 
				
			||||||
		var challenger = challengers[auth.type] && challengers[auth.type].set;
 | 
							var challenger = challengers[ch.type] && challengers[ch.type].set;
 | 
				
			||||||
		if (!challenger) {
 | 
							if (!challenger) {
 | 
				
			||||||
			throw new Error(
 | 
								throw new Error(
 | 
				
			||||||
				"options.challenges did not have a valid entry for '" +
 | 
									"options.challenges did not have a valid entry for '" +
 | 
				
			||||||
					auth.type +
 | 
										ch.type +
 | 
				
			||||||
					"'"
 | 
										"'"
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -760,7 +770,7 @@ ACME._setChallenge = function(me, options, auth) {
 | 
				
			|||||||
			});
 | 
								});
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			throw new Error(
 | 
								throw new Error(
 | 
				
			||||||
				"Bad function signature for '" + auth.type + "' challenge.set()"
 | 
									"Bad function signature for '" + ch.type + "' challenge.set()"
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
@ -957,6 +967,17 @@ ACME._getCertificate = function(me, options) {
 | 
				
			|||||||
		);
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// a cheap check to see if there are non-ascii characters in any of the domains
 | 
				
			||||||
 | 
						var nonAsciiDomains = options.domains.some(function(d) {
 | 
				
			||||||
 | 
							// IDN / unicode / utf-8 / punycode
 | 
				
			||||||
 | 
							return Enc.strToBin(d) !== d;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						if (nonAsciiDomains) {
 | 
				
			||||||
 | 
							throw new Error(
 | 
				
			||||||
 | 
								"please use the 'punycode' module to convert unicode domain names to punycode"
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// It's just fine if there's no account, we'll go get the key id we need via the existing key
 | 
						// It's just fine if there's no account, we'll go get the key id we need via the existing key
 | 
				
			||||||
	options._kid =
 | 
						options._kid =
 | 
				
			||||||
		options._kid ||
 | 
							options._kid ||
 | 
				
			||||||
@ -1034,7 +1055,10 @@ ACME._getCertificate = function(me, options) {
 | 
				
			|||||||
						return 0;
 | 
											return 0;
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
					.map(function(hostname) {
 | 
										.map(function(hostname) {
 | 
				
			||||||
						return { type: 'dns', value: hostname };
 | 
											return {
 | 
				
			||||||
 | 
												type: 'dns',
 | 
				
			||||||
 | 
												value: hostname
 | 
				
			||||||
 | 
											};
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
				//, "notBefore": "2016-01-01T00:00:00Z"
 | 
									//, "notBefore": "2016-01-01T00:00:00Z"
 | 
				
			||||||
				//, "notAfter": "2016-01-08T00:00:00Z"
 | 
									//, "notAfter": "2016-01-08T00:00:00Z"
 | 
				
			||||||
@ -1164,14 +1188,15 @@ ACME._getCertificate = function(me, options) {
 | 
				
			|||||||
						return;
 | 
											return;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if (!me._canUse[auth.type] || me.skipChallengeTest) {
 | 
										var ch = auth.challenge;
 | 
				
			||||||
 | 
										if (!me._canUse[ch.type] || me.skipChallengeTest) {
 | 
				
			||||||
						// not so much "valid" as "not invalid"
 | 
											// not so much "valid" as "not invalid"
 | 
				
			||||||
						// but in this case we can't confirm either way
 | 
											// but in this case we can't confirm either way
 | 
				
			||||||
						validAuths.push(auth);
 | 
											validAuths.push(auth);
 | 
				
			||||||
						return checkNext();
 | 
											return checkNext();
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					return ACME.challengeTests[auth.type](me, auth)
 | 
										return ACME.challengeTests[ch.type](me, auth)
 | 
				
			||||||
						.then(function() {
 | 
											.then(function() {
 | 
				
			||||||
							validAuths.push(auth);
 | 
												validAuths.push(auth);
 | 
				
			||||||
						})
 | 
											})
 | 
				
			||||||
@ -1272,10 +1297,7 @@ ACME._generateCsrWeb64 = function(me, options, validatedDomains) {
 | 
				
			|||||||
		return Promise.resolve(csr);
 | 
							return Promise.resolve(csr);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ACME._importKeypair(
 | 
						return ACME._importKeypair(me, options.serverKeypair).then(function(pair) {
 | 
				
			||||||
		me,
 | 
					 | 
				
			||||||
		options.serverKeypair || options.domainKeypair
 | 
					 | 
				
			||||||
	).then(function(pair) {
 | 
					 | 
				
			||||||
		return me.CSR.csr({
 | 
							return me.CSR.csr({
 | 
				
			||||||
			jwk: pair.private,
 | 
								jwk: pair.private,
 | 
				
			||||||
			domains: validatedDomains,
 | 
								domains: validatedDomains,
 | 
				
			||||||
@ -1302,8 +1324,8 @@ ACME.create = function create(me) {
 | 
				
			|||||||
	//me.Keypairs = me.Keypairs || require('keypairs');
 | 
						//me.Keypairs = me.Keypairs || require('keypairs');
 | 
				
			||||||
	//me.request = me.request || require('@root/request');
 | 
						//me.request = me.request || require('@root/request');
 | 
				
			||||||
	if (!me.dns01) {
 | 
						if (!me.dns01) {
 | 
				
			||||||
		me.dns01 = function(auth) {
 | 
							me.dns01 = function(ch) {
 | 
				
			||||||
			return ACME._dns01(me, auth);
 | 
								return ACME._dns01(me, ch);
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// backwards compat
 | 
						// backwards compat
 | 
				
			||||||
@ -1311,8 +1333,8 @@ ACME.create = function create(me) {
 | 
				
			|||||||
		me.dig = me.dns01;
 | 
							me.dig = me.dns01;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!me.http01) {
 | 
						if (!me.http01) {
 | 
				
			||||||
		me.http01 = function(auth) {
 | 
							me.http01 = function(ch) {
 | 
				
			||||||
			return ACME._http01(me, auth);
 | 
								return ACME._http01(me, ch);
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1505,9 +1527,9 @@ ACME._prnd = function(n) {
 | 
				
			|||||||
ACME._toHex = function(pair) {
 | 
					ACME._toHex = function(pair) {
 | 
				
			||||||
	return parseInt(pair, 10).toString(16);
 | 
						return parseInt(pair, 10).toString(16);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
ACME._dns01 = function(me, auth) {
 | 
					ACME._dns01 = function(me, ch) {
 | 
				
			||||||
	return new me.request({
 | 
						return new me.request({
 | 
				
			||||||
		url: me._baseUrl + '/api/dns/' + auth.dnsHost + '?type=TXT'
 | 
							url: me._baseUrl + '/api/dns/' + ch.dnsHost + '?type=TXT'
 | 
				
			||||||
	}).then(function(resp) {
 | 
						}).then(function(resp) {
 | 
				
			||||||
		var err;
 | 
							var err;
 | 
				
			||||||
		if (!resp.body || !Array.isArray(resp.body.answer)) {
 | 
							if (!resp.body || !Array.isArray(resp.body.answer)) {
 | 
				
			||||||
@ -1527,8 +1549,8 @@ ACME._dns01 = function(me, auth) {
 | 
				
			|||||||
		};
 | 
							};
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
ACME._http01 = function(me, auth) {
 | 
					ACME._http01 = function(me, ch) {
 | 
				
			||||||
	var url = encodeURIComponent(auth.challengeUrl);
 | 
						var url = encodeURIComponent(ch.challengeUrl);
 | 
				
			||||||
	return new me.request({
 | 
						return new me.request({
 | 
				
			||||||
		url: me._baseUrl + '/api/http?url=' + url
 | 
							url: me._baseUrl + '/api/http?url=' + url
 | 
				
			||||||
	}).then(function(resp) {
 | 
						}).then(function(resp) {
 | 
				
			||||||
@ -1537,20 +1559,27 @@ ACME._http01 = function(me, auth) {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
ACME._removeChallenge = function(me, options, auth) {
 | 
					ACME._removeChallenge = function(me, options, auth) {
 | 
				
			||||||
	var challengers = options.challenges || {};
 | 
						var challengers = options.challenges || {};
 | 
				
			||||||
	var removeChallenge =
 | 
						var ch = auth.challenge;
 | 
				
			||||||
		challengers[auth.type] && challengers[auth.type].remove;
 | 
						var removeChallenge = challengers[ch.type] && challengers[ch.type].remove;
 | 
				
			||||||
	if (!removeChallenge) {
 | 
						if (!removeChallenge) {
 | 
				
			||||||
		throw new Error('challenge plugin is missing remove()');
 | 
							throw new Error('challenge plugin is missing remove()');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (1 === removeChallenge.length) {
 | 
						if (1 === removeChallenge.length) {
 | 
				
			||||||
		return Promise.resolve(removeChallenge(auth)).then(
 | 
							return Promise.resolve(removeChallenge(auth)).then(
 | 
				
			||||||
			function() {},
 | 
								function() {},
 | 
				
			||||||
			function() {}
 | 
								function(e) {
 | 
				
			||||||
 | 
									console.error('Error during remove challenge:');
 | 
				
			||||||
 | 
									console.error(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
	} else if (2 === removeChallenge.length) {
 | 
						} else if (2 === removeChallenge.length) {
 | 
				
			||||||
		return new Promise(function(resolve) {
 | 
							return new Promise(function(resolve) {
 | 
				
			||||||
			removeChallenge(auth, function(err) {
 | 
								removeChallenge(auth, function(err) {
 | 
				
			||||||
				resolve();
 | 
									resolve();
 | 
				
			||||||
 | 
									if (err) {
 | 
				
			||||||
 | 
										console.error('Error during remove challenge:');
 | 
				
			||||||
 | 
										console.error(err);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				return err;
 | 
									return err;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
@ -1585,13 +1614,11 @@ ACME._getZones = function(me, presenter, dnsHosts) {
 | 
				
			|||||||
		dnsHosts: dnsHosts,
 | 
							dnsHosts: dnsHosts,
 | 
				
			||||||
		request: me.request
 | 
							request: me.request
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	// back/forwards-compat
 | 
					 | 
				
			||||||
	challenge.challenge = challenge;
 | 
					 | 
				
			||||||
	return ACME._wrapCb(
 | 
						return ACME._wrapCb(
 | 
				
			||||||
		me,
 | 
							me,
 | 
				
			||||||
		presenter,
 | 
							presenter,
 | 
				
			||||||
		'zones',
 | 
							'zones',
 | 
				
			||||||
		challenge,
 | 
							{ challenge: challenge },
 | 
				
			||||||
		'an array of zone names'
 | 
							'an array of zone names'
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ASN1 = module.exports;
 | 
					var ASN1 = module.exports;
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					var Enc = require('@root/encoding/hex');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Packer
 | 
					// Packer
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ASN1 = module.exports;
 | 
					var ASN1 = module.exports;
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					var Enc = require('@root/encoding/hex');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Parser
 | 
					// Parser
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								lib/csr.js
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								lib/csr.js
									
									
									
									
									
								
							@ -5,12 +5,13 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
/*global Promise*/
 | 
					/*global Promise*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Enc = require('@root/encoding');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ASN1 = require('./asn1/packer.js'); // DER, actually
 | 
					var ASN1 = require('./asn1/packer.js'); // DER, actually
 | 
				
			||||||
var Asn1 = ASN1.Any;
 | 
					var Asn1 = ASN1.Any;
 | 
				
			||||||
var BitStr = ASN1.BitStr;
 | 
					var BitStr = ASN1.BitStr;
 | 
				
			||||||
var UInt = ASN1.UInt;
 | 
					var UInt = ASN1.UInt;
 | 
				
			||||||
var Asn1Parser = require('./asn1/parser.js');
 | 
					var Asn1Parser = require('./asn1/parser.js');
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					 | 
				
			||||||
var PEM = require('./pem.js');
 | 
					var PEM = require('./pem.js');
 | 
				
			||||||
var X509 = require('./x509.js');
 | 
					var X509 = require('./x509.js');
 | 
				
			||||||
var Keypairs = require('./keypairs');
 | 
					var Keypairs = require('./keypairs');
 | 
				
			||||||
@ -155,7 +156,8 @@ X509.packCsr = function(asn1pubkey, domains) {
 | 
				
			|||||||
				Asn1(
 | 
									Asn1(
 | 
				
			||||||
					'30',
 | 
										'30',
 | 
				
			||||||
					Asn1('06', '550403'),
 | 
										Asn1('06', '550403'),
 | 
				
			||||||
					Asn1('0c', Enc.utf8ToHex(domains[0]))
 | 
										// TODO utf8 => punycode
 | 
				
			||||||
 | 
										Asn1('0c', Enc.strToHex(domains[0]))
 | 
				
			||||||
				)
 | 
									)
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
@ -184,7 +186,8 @@ X509.packCsr = function(asn1pubkey, domains) {
 | 
				
			|||||||
									'30',
 | 
														'30',
 | 
				
			||||||
									domains
 | 
														domains
 | 
				
			||||||
										.map(function(d) {
 | 
															.map(function(d) {
 | 
				
			||||||
											return Asn1('82', Enc.utf8ToHex(d));
 | 
																// TODO utf8 => punycode
 | 
				
			||||||
 | 
																return Asn1('82', Enc.strToHex(d));
 | 
				
			||||||
										})
 | 
															})
 | 
				
			||||||
										.join('')
 | 
															.join('')
 | 
				
			||||||
								)
 | 
													)
 | 
				
			||||||
@ -235,7 +238,6 @@ CSR._info = function(der) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	//c.children[1]; // signature type
 | 
						//c.children[1]; // signature type
 | 
				
			||||||
	var req = c.children[0];
 | 
						var req = c.children[0];
 | 
				
			||||||
	// TODO utf8
 | 
					 | 
				
			||||||
	if (4 !== req.children.length) {
 | 
						if (4 !== req.children.length) {
 | 
				
			||||||
		throw new Error(
 | 
							throw new Error(
 | 
				
			||||||
			"doesn't look like a certificate request: expected 4 parts to request"
 | 
								"doesn't look like a certificate request: expected 4 parts to request"
 | 
				
			||||||
@ -243,7 +245,7 @@ CSR._info = function(der) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// 0 null
 | 
						// 0 null
 | 
				
			||||||
	// 1 commonName / subject
 | 
						// 1 commonName / subject
 | 
				
			||||||
	var sub = Enc.bufToBin(
 | 
						var sub = Enc.bufToStr(
 | 
				
			||||||
		req.children[1].children[0].children[0].children[1].value
 | 
							req.children[1].children[0].children[0].children[1].value
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
	// 3 public key (type, key)
 | 
						// 3 public key (type, key)
 | 
				
			||||||
@ -305,8 +307,8 @@ CSR._info = function(der) {
 | 
				
			|||||||
					return seq2.children[1].children[0].children.map(function(
 | 
										return seq2.children[1].children[0].children.map(function(
 | 
				
			||||||
						name
 | 
											name
 | 
				
			||||||
					) {
 | 
										) {
 | 
				
			||||||
						// TODO utf8
 | 
											// TODO utf8 => punycode
 | 
				
			||||||
						return Enc.bufToBin(name.value);
 | 
											return Enc.bufToStr(name.value);
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				})[0];
 | 
									})[0];
 | 
				
			||||||
		})[0];
 | 
							})[0];
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,8 @@
 | 
				
			|||||||
/*global Promise*/
 | 
					/*global Promise*/
 | 
				
			||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Enc = require('@root/encoding');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var EC = module.exports;
 | 
					var EC = module.exports;
 | 
				
			||||||
var native = require('./node/ecdsa.js');
 | 
					var native = require('./node/ecdsa.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,7 +12,6 @@ var SSH;
 | 
				
			|||||||
var x509 = require('./x509.js');
 | 
					var x509 = require('./x509.js');
 | 
				
			||||||
var PEM = require('./pem.js');
 | 
					var PEM = require('./pem.js');
 | 
				
			||||||
//var SSH = require('./ssh-keys.js');
 | 
					//var SSH = require('./ssh-keys.js');
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					 | 
				
			||||||
var sha2 = require('./node/sha2.js');
 | 
					var sha2 = require('./node/sha2.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 1.2.840.10045.3.1.7
 | 
					// 1.2.840.10045.3.1.7
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										151
									
								
								lib/encoding.js
									
									
									
									
									
								
							
							
						
						
									
										151
									
								
								lib/encoding.js
									
									
									
									
									
								
							@ -1,151 +0,0 @@
 | 
				
			|||||||
(function(exports) {
 | 
					 | 
				
			||||||
	var Enc = (exports.Enc = {});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.bufToBin = function(buf) {
 | 
					 | 
				
			||||||
		var bin = '';
 | 
					 | 
				
			||||||
		// cannot use .map() because Uint8Array would return only 0s
 | 
					 | 
				
			||||||
		buf.forEach(function(ch) {
 | 
					 | 
				
			||||||
			bin += String.fromCharCode(ch);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		return bin;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.bufToHex = function toHex(u8) {
 | 
					 | 
				
			||||||
		var hex = [];
 | 
					 | 
				
			||||||
		var i, h;
 | 
					 | 
				
			||||||
		var len = u8.byteLength || u8.length;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < len; i += 1) {
 | 
					 | 
				
			||||||
			h = u8[i].toString(16);
 | 
					 | 
				
			||||||
			if (h.length % 2) {
 | 
					 | 
				
			||||||
				h = '0' + h;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			hex.push(h);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return hex.join('').toLowerCase();
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.urlBase64ToBase64 = function urlsafeBase64ToBase64(str) {
 | 
					 | 
				
			||||||
		var r = str % 4;
 | 
					 | 
				
			||||||
		if (2 === r) {
 | 
					 | 
				
			||||||
			str += '==';
 | 
					 | 
				
			||||||
		} else if (3 === r) {
 | 
					 | 
				
			||||||
			str += '=';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return str.replace(/-/g, '+').replace(/_/g, '/');
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.base64ToBuf = function(b64) {
 | 
					 | 
				
			||||||
		return Enc.binToBuf(atob(b64));
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	Enc.binToBuf = function(bin) {
 | 
					 | 
				
			||||||
		var arr = bin.split('').map(function(ch) {
 | 
					 | 
				
			||||||
			return ch.charCodeAt(0);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		return 'undefined' !== typeof Uint8Array ? new Uint8Array(arr) : arr;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	Enc.bufToHex = function(u8) {
 | 
					 | 
				
			||||||
		var hex = [];
 | 
					 | 
				
			||||||
		var i, h;
 | 
					 | 
				
			||||||
		var len = u8.byteLength || u8.length;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < len; i += 1) {
 | 
					 | 
				
			||||||
			h = u8[i].toString(16);
 | 
					 | 
				
			||||||
			if (h.length % 2) {
 | 
					 | 
				
			||||||
				h = '0' + h;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			hex.push(h);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return hex.join('').toLowerCase();
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	Enc.numToHex = function(d) {
 | 
					 | 
				
			||||||
		d = d.toString(16);
 | 
					 | 
				
			||||||
		if (d.length % 2) {
 | 
					 | 
				
			||||||
			return '0' + d;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return d;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.bufToUrlBase64 = function(u8) {
 | 
					 | 
				
			||||||
		return Enc.base64ToUrlBase64(Enc.bufToBase64(u8));
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.base64ToUrlBase64 = function(str) {
 | 
					 | 
				
			||||||
		return str
 | 
					 | 
				
			||||||
			.replace(/\+/g, '-')
 | 
					 | 
				
			||||||
			.replace(/\//g, '_')
 | 
					 | 
				
			||||||
			.replace(/=/g, '');
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.bufToBase64 = function(u8) {
 | 
					 | 
				
			||||||
		var bin = '';
 | 
					 | 
				
			||||||
		u8.forEach(function(i) {
 | 
					 | 
				
			||||||
			bin += String.fromCharCode(i);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		return btoa(bin);
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.hexToBuf = function(hex) {
 | 
					 | 
				
			||||||
		var arr = [];
 | 
					 | 
				
			||||||
		hex.match(/.{2}/g).forEach(function(h) {
 | 
					 | 
				
			||||||
			arr.push(parseInt(h, 16));
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		return 'undefined' !== typeof Uint8Array ? new Uint8Array(arr) : arr;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.numToHex = function(d) {
 | 
					 | 
				
			||||||
		d = d.toString(16);
 | 
					 | 
				
			||||||
		if (d.length % 2) {
 | 
					 | 
				
			||||||
			return '0' + d;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return d;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	// JWK to SSH (tested working)
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	Enc.base64ToHex = function(b64) {
 | 
					 | 
				
			||||||
		var bin = atob(Enc.urlBase64ToBase64(b64));
 | 
					 | 
				
			||||||
		return Enc.binToHex(bin);
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.binToHex = function(bin) {
 | 
					 | 
				
			||||||
		return bin
 | 
					 | 
				
			||||||
			.split('')
 | 
					 | 
				
			||||||
			.map(function(ch) {
 | 
					 | 
				
			||||||
				var h = ch.charCodeAt(0).toString(16);
 | 
					 | 
				
			||||||
				if (h.length % 2) {
 | 
					 | 
				
			||||||
					h = '0' + h;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return h;
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
			.join('');
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// TODO are there any nuance differences here?
 | 
					 | 
				
			||||||
	Enc.utf8ToHex = Enc.binToHex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.hexToBase64 = function(hex) {
 | 
					 | 
				
			||||||
		return btoa(Enc.hexToBin(hex));
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.hexToBin = function(hex) {
 | 
					 | 
				
			||||||
		return hex
 | 
					 | 
				
			||||||
			.match(/.{2}/g)
 | 
					 | 
				
			||||||
			.map(function(h) {
 | 
					 | 
				
			||||||
				return String.fromCharCode(parseInt(h, 16));
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
			.join('');
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Enc.urlBase64ToBase64 = function urlsafeBase64ToBase64(str) {
 | 
					 | 
				
			||||||
		var r = str % 4;
 | 
					 | 
				
			||||||
		if (2 === r) {
 | 
					 | 
				
			||||||
			str += '==';
 | 
					 | 
				
			||||||
		} else if (3 === r) {
 | 
					 | 
				
			||||||
			str += '=';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return str.replace(/-/g, '+').replace(/_/g, '/');
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
})('undefined' !== typeof exports ? module.exports : window);
 | 
					 | 
				
			||||||
@ -1,11 +1,13 @@
 | 
				
			|||||||
/*global Promise*/
 | 
					/*global Promise*/
 | 
				
			||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require('@root/encoding/bytes');
 | 
				
			||||||
 | 
					var Enc = require('@root/encoding/base64');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var Keypairs = module.exports;
 | 
					var Keypairs = module.exports;
 | 
				
			||||||
var Rasha = require('./rsa.js');
 | 
					var Rasha = require('./rsa.js');
 | 
				
			||||||
var Eckles = require('./ecdsa.js');
 | 
					var Eckles = require('./ecdsa.js');
 | 
				
			||||||
var native = require('./node/keypairs.js');
 | 
					var native = require('./node/keypairs.js');
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Keypairs._stance =
 | 
					Keypairs._stance =
 | 
				
			||||||
	"We take the stance that if you're knowledgeable enough to" +
 | 
						"We take the stance that if you're knowledgeable enough to" +
 | 
				
			||||||
@ -224,7 +226,7 @@ Keypairs.signJws = function(opts) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			// Converting to a buffer, even if it was just converted to a string
 | 
								// Converting to a buffer, even if it was just converted to a string
 | 
				
			||||||
			if ('string' === typeof payload) {
 | 
								if ('string' === typeof payload) {
 | 
				
			||||||
				payload = Enc.binToBuf(payload);
 | 
									payload = Enc.strToBuf(payload);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var protected64 = Enc.strToUrlBase64(protectedHeader);
 | 
								var protected64 = Enc.strToUrlBase64(protectedHeader);
 | 
				
			||||||
@ -311,20 +313,3 @@ function setTime(time) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return now + mult * num;
 | 
						return now + mult * num;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
Enc.hexToBuf = function(hex) {
 | 
					 | 
				
			||||||
	var arr = [];
 | 
					 | 
				
			||||||
	hex.match(/.{2}/g).forEach(function(h) {
 | 
					 | 
				
			||||||
		arr.push(parseInt(h, 16));
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	return 'undefined' !== typeof Uint8Array ? new Uint8Array(arr) : arr;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
Enc.strToUrlBase64 = function(str) {
 | 
					 | 
				
			||||||
	return Enc.bufToUrlBase64(Enc.binToBuf(str));
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
Enc.binToBuf = function(bin) {
 | 
					 | 
				
			||||||
	var arr = bin.split('').map(function(ch) {
 | 
					 | 
				
			||||||
		return ch.charCodeAt(0);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	return 'undefined' !== typeof Uint8Array ? new Uint8Array(arr) : arr;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -118,7 +118,7 @@ function toJwks(oldpair) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO
 | 
					// TODO
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					var Enc = require('@root/encoding/base64');
 | 
				
			||||||
x509.parsePkcs1 = function parseRsaPkcs1(buf, asn1, jwk) {
 | 
					x509.parsePkcs1 = function parseRsaPkcs1(buf, asn1, jwk) {
 | 
				
			||||||
	if (
 | 
						if (
 | 
				
			||||||
		!asn1.children.every(function(el) {
 | 
							!asn1.children.every(function(el) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Enc = require('@root/encoding/base64');
 | 
				
			||||||
var PEM = module.exports;
 | 
					var PEM = module.exports;
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
PEM.packBlock = function(opts) {
 | 
					PEM.packBlock = function(opts) {
 | 
				
			||||||
	// TODO allow for headers?
 | 
						// TODO allow for headers?
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ var x509 = require('./x509.js');
 | 
				
			|||||||
var PEM = require('./pem.js');
 | 
					var PEM = require('./pem.js');
 | 
				
			||||||
//var SSH = require('./ssh-keys.js');
 | 
					//var SSH = require('./ssh-keys.js');
 | 
				
			||||||
var sha2 = require('./node/sha2.js');
 | 
					var sha2 = require('./node/sha2.js');
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					var Enc = require('@root/encoding/base64');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RSA._universal =
 | 
					RSA._universal =
 | 
				
			||||||
	'Bluecrypt only supports crypto with standard cross-browser and cross-platform support.';
 | 
						'Bluecrypt only supports crypto with standard cross-browser and cross-platform support.';
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ var ASN1 = require('./asn1/packer.js');
 | 
				
			|||||||
var Asn1 = ASN1.Any;
 | 
					var Asn1 = ASN1.Any;
 | 
				
			||||||
var UInt = ASN1.UInt;
 | 
					var UInt = ASN1.UInt;
 | 
				
			||||||
var BitStr = ASN1.BitStr;
 | 
					var BitStr = ASN1.BitStr;
 | 
				
			||||||
var Enc = require('omnibuffer');
 | 
					var Enc = require('@root/encoding');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 1.2.840.10045.3.1.7
 | 
					// 1.2.840.10045.3.1.7
 | 
				
			||||||
// prime256v1 (ANSI X9.62 named elliptic curve)
 | 
					// prime256v1 (ANSI X9.62 named elliptic curve)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										421
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										421
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -4,28 +4,17 @@
 | 
				
			|||||||
  "lockfileVersion": 1,
 | 
					  "lockfileVersion": 1,
 | 
				
			||||||
  "requires": true,
 | 
					  "requires": true,
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "@root/encoding": {
 | 
				
			||||||
 | 
					      "version": "1.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@root/encoding/-/encoding-1.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-OaEub02ufoU038gy6bsNHQOjIn8nUjGiLcaRmJ40IUykneJkIW5fxDqKxQx48cszuNflYldsJLPPXCrGfHs8yQ=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "@root/request": {
 | 
					    "@root/request": {
 | 
				
			||||||
      "version": "1.3.10",
 | 
					      "version": "1.3.10",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@root/request/-/request-1.3.10.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@root/request/-/request-1.3.10.tgz",
 | 
				
			||||||
      "integrity": "sha512-GSn8dfsGp0juJyXS9k7B/DjYm7Axe85wiCHfPs30eQ+/V6p2aqey45e1czb3ZwP+iPmzWCKXahhWnZhSDIil6w==",
 | 
					      "integrity": "sha512-GSn8dfsGp0juJyXS9k7B/DjYm7Axe85wiCHfPs30eQ+/V6p2aqey45e1czb3ZwP+iPmzWCKXahhWnZhSDIil6w==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "accepts": {
 | 
					 | 
				
			||||||
      "version": "1.3.6",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.6.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-QsaoUD2dpVpjENy8JFpQnXP9vyzoZPmAoKrE3S6HtSB7qzSebkJNnmdY4p004FQUSSiHXPueENpoeuUW/7a8Ig==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "mime-types": "~2.1.24",
 | 
					 | 
				
			||||||
        "negotiator": "0.6.1"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "array-flatten": {
 | 
					 | 
				
			||||||
      "version": "1.1.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "balanced-match": {
 | 
					    "balanced-match": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
 | 
				
			||||||
@ -38,24 +27,6 @@
 | 
				
			|||||||
      "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==",
 | 
					      "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "body-parser": {
 | 
					 | 
				
			||||||
      "version": "1.18.3",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "bytes": "3.0.0",
 | 
					 | 
				
			||||||
        "content-type": "~1.0.4",
 | 
					 | 
				
			||||||
        "debug": "2.6.9",
 | 
					 | 
				
			||||||
        "depd": "~1.1.2",
 | 
					 | 
				
			||||||
        "http-errors": "~1.6.3",
 | 
					 | 
				
			||||||
        "iconv-lite": "0.4.23",
 | 
					 | 
				
			||||||
        "on-finished": "~2.3.0",
 | 
					 | 
				
			||||||
        "qs": "6.5.2",
 | 
					 | 
				
			||||||
        "raw-body": "2.3.3",
 | 
					 | 
				
			||||||
        "type-is": "~1.6.16"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "brace-expansion": {
 | 
					    "brace-expansion": {
 | 
				
			||||||
      "version": "1.1.11",
 | 
					      "version": "1.1.11",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 | 
				
			||||||
@ -66,12 +37,6 @@
 | 
				
			|||||||
        "concat-map": "0.0.1"
 | 
					        "concat-map": "0.0.1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "bytes": {
 | 
					 | 
				
			||||||
      "version": "3.0.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "cli": {
 | 
					    "cli": {
 | 
				
			||||||
      "version": "1.0.1",
 | 
					      "version": "1.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz",
 | 
				
			||||||
@ -82,63 +47,12 @@
 | 
				
			|||||||
        "glob": "^7.1.1"
 | 
					        "glob": "^7.1.1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "commander": {
 | 
					 | 
				
			||||||
      "version": "2.20.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "concat-map": {
 | 
					    "concat-map": {
 | 
				
			||||||
      "version": "0.0.1",
 | 
					      "version": "0.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
 | 
					      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "content-disposition": {
 | 
					 | 
				
			||||||
      "version": "0.5.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "content-type": {
 | 
					 | 
				
			||||||
      "version": "1.0.4",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "cookie": {
 | 
					 | 
				
			||||||
      "version": "0.3.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "cookie-signature": {
 | 
					 | 
				
			||||||
      "version": "1.0.6",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "debug": {
 | 
					 | 
				
			||||||
      "version": "2.6.9",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "ms": "2.0.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "depd": {
 | 
					 | 
				
			||||||
      "version": "1.1.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "destroy": {
 | 
					 | 
				
			||||||
      "version": "1.0.4",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "dig.js": {
 | 
					    "dig.js": {
 | 
				
			||||||
      "version": "1.3.9",
 | 
					      "version": "1.3.9",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/dig.js/-/dig.js-1.3.9.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/dig.js/-/dig.js-1.3.9.tgz",
 | 
				
			||||||
@ -177,101 +91,12 @@
 | 
				
			|||||||
      "integrity": "sha512-GUE3gqcDCaMltj2++g6bRQ5rBJWtkWTmqmD0fo1RnnMuUqHNCt2oTPeDnS9n6fKYvlhn7AeBkb38lymBtWBQdA==",
 | 
					      "integrity": "sha512-GUE3gqcDCaMltj2++g6bRQ5rBJWtkWTmqmD0fo1RnnMuUqHNCt2oTPeDnS9n6fKYvlhn7AeBkb38lymBtWBQdA==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ee-first": {
 | 
					 | 
				
			||||||
      "version": "1.1.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "encodeurl": {
 | 
					 | 
				
			||||||
      "version": "1.0.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "escape-html": {
 | 
					 | 
				
			||||||
      "version": "1.0.3",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "etag": {
 | 
					 | 
				
			||||||
      "version": "1.8.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "exit": {
 | 
					    "exit": {
 | 
				
			||||||
      "version": "0.1.2",
 | 
					      "version": "0.1.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
 | 
				
			||||||
      "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
 | 
					      "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "express": {
 | 
					 | 
				
			||||||
      "version": "4.16.4",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "accepts": "~1.3.5",
 | 
					 | 
				
			||||||
        "array-flatten": "1.1.1",
 | 
					 | 
				
			||||||
        "body-parser": "1.18.3",
 | 
					 | 
				
			||||||
        "content-disposition": "0.5.2",
 | 
					 | 
				
			||||||
        "content-type": "~1.0.4",
 | 
					 | 
				
			||||||
        "cookie": "0.3.1",
 | 
					 | 
				
			||||||
        "cookie-signature": "1.0.6",
 | 
					 | 
				
			||||||
        "debug": "2.6.9",
 | 
					 | 
				
			||||||
        "depd": "~1.1.2",
 | 
					 | 
				
			||||||
        "encodeurl": "~1.0.2",
 | 
					 | 
				
			||||||
        "escape-html": "~1.0.3",
 | 
					 | 
				
			||||||
        "etag": "~1.8.1",
 | 
					 | 
				
			||||||
        "finalhandler": "1.1.1",
 | 
					 | 
				
			||||||
        "fresh": "0.5.2",
 | 
					 | 
				
			||||||
        "merge-descriptors": "1.0.1",
 | 
					 | 
				
			||||||
        "methods": "~1.1.2",
 | 
					 | 
				
			||||||
        "on-finished": "~2.3.0",
 | 
					 | 
				
			||||||
        "parseurl": "~1.3.2",
 | 
					 | 
				
			||||||
        "path-to-regexp": "0.1.7",
 | 
					 | 
				
			||||||
        "proxy-addr": "~2.0.4",
 | 
					 | 
				
			||||||
        "qs": "6.5.2",
 | 
					 | 
				
			||||||
        "range-parser": "~1.2.0",
 | 
					 | 
				
			||||||
        "safe-buffer": "5.1.2",
 | 
					 | 
				
			||||||
        "send": "0.16.2",
 | 
					 | 
				
			||||||
        "serve-static": "1.13.2",
 | 
					 | 
				
			||||||
        "setprototypeof": "1.1.0",
 | 
					 | 
				
			||||||
        "statuses": "~1.4.0",
 | 
					 | 
				
			||||||
        "type-is": "~1.6.16",
 | 
					 | 
				
			||||||
        "utils-merge": "1.0.1",
 | 
					 | 
				
			||||||
        "vary": "~1.1.2"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "finalhandler": {
 | 
					 | 
				
			||||||
      "version": "1.1.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "debug": "2.6.9",
 | 
					 | 
				
			||||||
        "encodeurl": "~1.0.2",
 | 
					 | 
				
			||||||
        "escape-html": "~1.0.3",
 | 
					 | 
				
			||||||
        "on-finished": "~2.3.0",
 | 
					 | 
				
			||||||
        "parseurl": "~1.3.2",
 | 
					 | 
				
			||||||
        "statuses": "~1.4.0",
 | 
					 | 
				
			||||||
        "unpipe": "~1.0.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "forwarded": {
 | 
					 | 
				
			||||||
      "version": "0.1.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "fresh": {
 | 
					 | 
				
			||||||
      "version": "0.5.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "fs.realpath": {
 | 
					    "fs.realpath": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 | 
				
			||||||
@ -297,27 +122,6 @@
 | 
				
			|||||||
      "from": "git+https://git.coolaj86.com/coolaj86/hexdump.js#v1.0.4",
 | 
					      "from": "git+https://git.coolaj86.com/coolaj86/hexdump.js#v1.0.4",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "http-errors": {
 | 
					 | 
				
			||||||
      "version": "1.6.3",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "depd": "~1.1.2",
 | 
					 | 
				
			||||||
        "inherits": "2.0.3",
 | 
					 | 
				
			||||||
        "setprototypeof": "1.1.0",
 | 
					 | 
				
			||||||
        "statuses": ">= 1.4.0 < 2"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "iconv-lite": {
 | 
					 | 
				
			||||||
      "version": "0.4.23",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "safer-buffer": ">= 2.1.2 < 3"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "inflight": {
 | 
					    "inflight": {
 | 
				
			||||||
      "version": "1.0.6",
 | 
					      "version": "1.0.6",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
 | 
				
			||||||
@ -334,51 +138,6 @@
 | 
				
			|||||||
      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
 | 
					      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ipaddr.js": {
 | 
					 | 
				
			||||||
      "version": "1.9.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "media-typer": {
 | 
					 | 
				
			||||||
      "version": "0.3.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "merge-descriptors": {
 | 
					 | 
				
			||||||
      "version": "1.0.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "methods": {
 | 
					 | 
				
			||||||
      "version": "1.1.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "mime": {
 | 
					 | 
				
			||||||
      "version": "1.4.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "mime-db": {
 | 
					 | 
				
			||||||
      "version": "1.40.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "mime-types": {
 | 
					 | 
				
			||||||
      "version": "2.1.24",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "mime-db": "1.40.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "minimatch": {
 | 
					    "minimatch": {
 | 
				
			||||||
      "version": "3.0.4",
 | 
					      "version": "3.0.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
 | 
				
			||||||
@ -388,27 +147,6 @@
 | 
				
			|||||||
        "brace-expansion": "^1.1.7"
 | 
					        "brace-expansion": "^1.1.7"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ms": {
 | 
					 | 
				
			||||||
      "version": "2.0.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "negotiator": {
 | 
					 | 
				
			||||||
      "version": "0.6.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "on-finished": {
 | 
					 | 
				
			||||||
      "version": "2.3.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "ee-first": "1.1.1"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "once": {
 | 
					    "once": {
 | 
				
			||||||
      "version": "1.4.0",
 | 
					      "version": "1.4.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
 | 
				
			||||||
@ -418,157 +156,16 @@
 | 
				
			|||||||
        "wrappy": "1"
 | 
					        "wrappy": "1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "parseurl": {
 | 
					 | 
				
			||||||
      "version": "1.3.3",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "path-is-absolute": {
 | 
					    "path-is-absolute": {
 | 
				
			||||||
      "version": "1.0.1",
 | 
					      "version": "1.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
 | 
					      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "path-to-regexp": {
 | 
					    "punycode": {
 | 
				
			||||||
      "version": "0.1.7",
 | 
					      "version": "1.4.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
 | 
					      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "proxy-addr": {
 | 
					 | 
				
			||||||
      "version": "2.0.5",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "forwarded": "~0.1.2",
 | 
					 | 
				
			||||||
        "ipaddr.js": "1.9.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "qs": {
 | 
					 | 
				
			||||||
      "version": "6.5.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "range-parser": {
 | 
					 | 
				
			||||||
      "version": "1.2.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "raw-body": {
 | 
					 | 
				
			||||||
      "version": "2.3.3",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "bytes": "3.0.0",
 | 
					 | 
				
			||||||
        "http-errors": "1.6.3",
 | 
					 | 
				
			||||||
        "iconv-lite": "0.4.23",
 | 
					 | 
				
			||||||
        "unpipe": "1.0.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "safe-buffer": {
 | 
					 | 
				
			||||||
      "version": "5.1.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "safer-buffer": {
 | 
					 | 
				
			||||||
      "version": "2.1.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "send": {
 | 
					 | 
				
			||||||
      "version": "0.16.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "debug": "2.6.9",
 | 
					 | 
				
			||||||
        "depd": "~1.1.2",
 | 
					 | 
				
			||||||
        "destroy": "~1.0.4",
 | 
					 | 
				
			||||||
        "encodeurl": "~1.0.2",
 | 
					 | 
				
			||||||
        "escape-html": "~1.0.3",
 | 
					 | 
				
			||||||
        "etag": "~1.8.1",
 | 
					 | 
				
			||||||
        "fresh": "0.5.2",
 | 
					 | 
				
			||||||
        "http-errors": "~1.6.2",
 | 
					 | 
				
			||||||
        "mime": "1.4.1",
 | 
					 | 
				
			||||||
        "ms": "2.0.0",
 | 
					 | 
				
			||||||
        "on-finished": "~2.3.0",
 | 
					 | 
				
			||||||
        "range-parser": "~1.2.0",
 | 
					 | 
				
			||||||
        "statuses": "~1.4.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "serve-static": {
 | 
					 | 
				
			||||||
      "version": "1.13.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "encodeurl": "~1.0.2",
 | 
					 | 
				
			||||||
        "escape-html": "~1.0.3",
 | 
					 | 
				
			||||||
        "parseurl": "~1.3.2",
 | 
					 | 
				
			||||||
        "send": "0.16.2"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "setprototypeof": {
 | 
					 | 
				
			||||||
      "version": "1.1.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "source-map": {
 | 
					 | 
				
			||||||
      "version": "0.6.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "statuses": {
 | 
					 | 
				
			||||||
      "version": "1.4.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "type-is": {
 | 
					 | 
				
			||||||
      "version": "1.6.18",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "media-typer": "0.3.0",
 | 
					 | 
				
			||||||
        "mime-types": "~2.1.24"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "uglify-js": {
 | 
					 | 
				
			||||||
      "version": "3.6.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "commander": "~2.20.0",
 | 
					 | 
				
			||||||
        "source-map": "~0.6.1"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "unpipe": {
 | 
					 | 
				
			||||||
      "version": "1.0.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "utils-merge": {
 | 
					 | 
				
			||||||
      "version": "1.0.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "vary": {
 | 
					 | 
				
			||||||
      "version": "1.1.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "wrappy": {
 | 
					    "wrappy": {
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@
 | 
				
			|||||||
		"dist"
 | 
							"dist"
 | 
				
			||||||
	],
 | 
						],
 | 
				
			||||||
	"scripts": {
 | 
						"scripts": {
 | 
				
			||||||
		"build": "node bin/bundle.js",
 | 
							"build": "nodex bin/bundle.js",
 | 
				
			||||||
		"lint": "jshint lib bin",
 | 
							"lint": "jshint lib bin",
 | 
				
			||||||
		"test": "node server.js",
 | 
							"test": "node server.js",
 | 
				
			||||||
		"start": "node server.js"
 | 
							"start": "node server.js"
 | 
				
			||||||
@ -41,12 +41,14 @@
 | 
				
			|||||||
	],
 | 
						],
 | 
				
			||||||
	"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
 | 
						"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
 | 
				
			||||||
	"license": "MPL-2.0",
 | 
						"license": "MPL-2.0",
 | 
				
			||||||
 | 
						"dependencies": {
 | 
				
			||||||
 | 
							"@root/encoding": "^1.0.1"
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	"devDependencies": {
 | 
						"devDependencies": {
 | 
				
			||||||
		"@root/request": "^1.3.10",
 | 
							"@root/request": "^1.3.10",
 | 
				
			||||||
		"dig.js": "^1.3.9",
 | 
							"dig.js": "^1.3.9",
 | 
				
			||||||
		"dns-suite": "^1.2.12",
 | 
							"dns-suite": "^1.2.12",
 | 
				
			||||||
		"dotenv": "^8.1.0",
 | 
							"dotenv": "^8.1.0",
 | 
				
			||||||
		"express": "^4.16.4",
 | 
							"punycode": "^1.4.1"
 | 
				
			||||||
		"uglify-js": "^3.6.0"
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										139
									
								
								server.js
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								server.js
									
									
									
									
									
								
							@ -1,139 +0,0 @@
 | 
				
			|||||||
'use strict';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var crypto = require('crypto');
 | 
					 | 
				
			||||||
//var dnsjs = require('dns-suite');
 | 
					 | 
				
			||||||
var dig = require('dig.js/dns-request');
 | 
					 | 
				
			||||||
var request = require('util').promisify(require('@root/request'));
 | 
					 | 
				
			||||||
var express = require('express');
 | 
					 | 
				
			||||||
var app = express();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var nameservers = require('dns').getServers();
 | 
					 | 
				
			||||||
var index = crypto.randomBytes(2).readUInt16BE(0) % nameservers.length;
 | 
					 | 
				
			||||||
var nameserver = nameservers[index];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.use('/', express.static(__dirname));
 | 
					 | 
				
			||||||
app.use('/api', express.json());
 | 
					 | 
				
			||||||
app.get('/api/dns/:domain', function (req, res, next) {
 | 
					 | 
				
			||||||
  var domain = req.params.domain;
 | 
					 | 
				
			||||||
  var casedDomain = domain.toLowerCase().split('').map(function (ch) {
 | 
					 | 
				
			||||||
    // dns0x20 takes advantage of the fact that the binary operation for toUpperCase is
 | 
					 | 
				
			||||||
    // ch = ch | 0x20;
 | 
					 | 
				
			||||||
    return Math.round(Math.random()) % 2 ? ch : ch.toUpperCase();
 | 
					 | 
				
			||||||
  }).join('');
 | 
					 | 
				
			||||||
  var typ = req.query.type;
 | 
					 | 
				
			||||||
  var query = {
 | 
					 | 
				
			||||||
    header: {
 | 
					 | 
				
			||||||
      id: crypto.randomBytes(2).readUInt16BE(0)
 | 
					 | 
				
			||||||
    , qr: 0
 | 
					 | 
				
			||||||
    , opcode: 0
 | 
					 | 
				
			||||||
    , aa: 0 // Authoritative-Only
 | 
					 | 
				
			||||||
    , tc: 0                   // NA
 | 
					 | 
				
			||||||
    , rd: 1 // Recurse
 | 
					 | 
				
			||||||
    , ra: 0                   // NA
 | 
					 | 
				
			||||||
    , rcode: 0                // NA
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  , question: [
 | 
					 | 
				
			||||||
      { name: casedDomain
 | 
					 | 
				
			||||||
      //, type: typ || 'A'
 | 
					 | 
				
			||||||
      , typeName: typ || 'A'
 | 
					 | 
				
			||||||
      , className: 'IN'
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  var opts = {
 | 
					 | 
				
			||||||
    onError: function (err) {
 | 
					 | 
				
			||||||
      next(err);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  , onMessage: function (packet) {
 | 
					 | 
				
			||||||
      var fail0x20;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (packet.id !== query.id) {
 | 
					 | 
				
			||||||
        console.error('[SECURITY] ignoring packet for \'' + packet.question[0].name + '\' due to mismatched id');
 | 
					 | 
				
			||||||
        console.error(packet);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      packet.question.forEach(function (q) {
 | 
					 | 
				
			||||||
        // if (-1 === q.name.lastIndexOf(cli.casedQuery))
 | 
					 | 
				
			||||||
        if (q.name !== casedDomain) {
 | 
					 | 
				
			||||||
          fail0x20 = q.name;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      [ 'question', 'answer', 'authority', 'additional' ].forEach(function (group) {
 | 
					 | 
				
			||||||
        (packet[group]||[]).forEach(function (a) {
 | 
					 | 
				
			||||||
          var an = a.name;
 | 
					 | 
				
			||||||
          var i = domain.toLowerCase().lastIndexOf(a.name.toLowerCase());  // answer is something like ExAMPle.cOM and query was wWw.ExAMPle.cOM
 | 
					 | 
				
			||||||
          var j = a.name.toLowerCase().lastIndexOf(domain.toLowerCase());  // answer is something like www.ExAMPle.cOM and query was ExAMPle.cOM
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          // it's important to note that these should only relpace changes in casing that we expected
 | 
					 | 
				
			||||||
          // any abnormalities should be left intact to go "huh?" about
 | 
					 | 
				
			||||||
          // TODO detect abnormalities?
 | 
					 | 
				
			||||||
          if (-1 !== i) {
 | 
					 | 
				
			||||||
            // "EXamPLE.cOm".replace("wWw.EXamPLE.cOm".substr(4), "www.example.com".substr(4))
 | 
					 | 
				
			||||||
            a.name = a.name.replace(casedDomain.substr(i), domain.substr(i));
 | 
					 | 
				
			||||||
          } else if (-1 !== j) {
 | 
					 | 
				
			||||||
            // "www.example.com".replace("EXamPLE.cOm", "example.com")
 | 
					 | 
				
			||||||
            a.name = a.name.substr(0, j) + a.name.substr(j).replace(casedDomain, domain);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          // NOTE: right now this assumes that anything matching the query matches all the way to the end
 | 
					 | 
				
			||||||
          // it does not handle the case of a record for example.com.uk being returned in response to a query for www.example.com correctly
 | 
					 | 
				
			||||||
          // (but I don't think it should need to)
 | 
					 | 
				
			||||||
          if (a.name.length !== an.length) {
 | 
					 | 
				
			||||||
            console.error("[ERROR] question / answer mismatch: '" + an + "' != '" + a.length + "'");
 | 
					 | 
				
			||||||
            console.error(a);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (fail0x20) {
 | 
					 | 
				
			||||||
        console.warn(";; Warning: DNS 0x20 security not implemented (or packet spoofed). Queried '"
 | 
					 | 
				
			||||||
          + casedDomain + "' but got response for '" + fail0x20 + "'.");
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      res.send({
 | 
					 | 
				
			||||||
        header: packet.header
 | 
					 | 
				
			||||||
      , question: packet.question
 | 
					 | 
				
			||||||
      , answer: packet.answer
 | 
					 | 
				
			||||||
      , authority: packet.authority
 | 
					 | 
				
			||||||
      , additional: packet.additional
 | 
					 | 
				
			||||||
      , edns_options: packet.edns_options
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  , onListening: function () {}
 | 
					 | 
				
			||||||
  , onSent: function (/*res*/) { }
 | 
					 | 
				
			||||||
  , onTimeout: function (res) {
 | 
					 | 
				
			||||||
      console.error('dns timeout:', res);
 | 
					 | 
				
			||||||
      next(new Error("DNS timeout - no response"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  , onClose: function () { }
 | 
					 | 
				
			||||||
  //, mdns: cli.mdns
 | 
					 | 
				
			||||||
  , nameserver: nameserver
 | 
					 | 
				
			||||||
  , port: 53
 | 
					 | 
				
			||||||
  , timeout: 2000
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  dig.resolveJson(query, opts);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
app.get('/api/http', function (req, res) {
 | 
					 | 
				
			||||||
  var url = req.query.url;
 | 
					 | 
				
			||||||
  return request({ method: 'GET', url: url }).then(function (resp) {
 | 
					 | 
				
			||||||
    res.send(resp.body);
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
app.get('/api/_acme_api_', function (req, res) {
 | 
					 | 
				
			||||||
  res.send({ success: true });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = app;
 | 
					 | 
				
			||||||
if (require.main === module) {
 | 
					 | 
				
			||||||
  // curl -L http://localhost:3000/api/dns/example.com?type=A
 | 
					 | 
				
			||||||
  console.info("Listening on localhost:3000");
 | 
					 | 
				
			||||||
  app.listen(3000);
 | 
					 | 
				
			||||||
  console.info("Try this:");
 | 
					 | 
				
			||||||
  console.info("\tcurl -L 'http://localhost:3000/api/_acme_api_/'");
 | 
					 | 
				
			||||||
  console.info("\tcurl -L 'http://localhost:3000/api/dns/example.com?type=A'");
 | 
					 | 
				
			||||||
  console.info("\tcurl -L 'http://localhost:3000/api/http/?url=https://example.com'");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
require('dotenv').config();
 | 
					require('dotenv').config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var punycode = require('punycode');
 | 
				
			||||||
var ACME = require('../');
 | 
					var ACME = require('../');
 | 
				
			||||||
var Keypairs = require('../lib/keypairs.js');
 | 
					var Keypairs = require('../lib/keypairs.js');
 | 
				
			||||||
var acme = ACME.create({
 | 
					var acme = ACME.create({
 | 
				
			||||||
@ -73,7 +74,7 @@ async function happyPath(accKty, srvKty, rnd) {
 | 
				
			|||||||
	if (config.debug) {
 | 
						if (config.debug) {
 | 
				
			||||||
		console.info('ACME.js initialized');
 | 
							console.info('ACME.js initialized');
 | 
				
			||||||
		console.info(metadata);
 | 
							console.info(metadata);
 | 
				
			||||||
		console.info('');
 | 
							console.info();
 | 
				
			||||||
		console.info();
 | 
							console.info();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -81,7 +82,7 @@ async function happyPath(accKty, srvKty, rnd) {
 | 
				
			|||||||
	if (config.debug) {
 | 
						if (config.debug) {
 | 
				
			||||||
		console.info('Account Key Created');
 | 
							console.info('Account Key Created');
 | 
				
			||||||
		console.info(JSON.stringify(accountKeypair, null, 2));
 | 
							console.info(JSON.stringify(accountKeypair, null, 2));
 | 
				
			||||||
		console.info('');
 | 
							console.info();
 | 
				
			||||||
		console.info();
 | 
							console.info();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -96,7 +97,7 @@ async function happyPath(accKty, srvKty, rnd) {
 | 
				
			|||||||
		if (config.debug) {
 | 
							if (config.debug) {
 | 
				
			||||||
			console.info('Agreeing to Terms of Service:');
 | 
								console.info('Agreeing to Terms of Service:');
 | 
				
			||||||
			console.info(tos);
 | 
								console.info(tos);
 | 
				
			||||||
			console.info('');
 | 
								console.info();
 | 
				
			||||||
			console.info();
 | 
								console.info();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		agreed = true;
 | 
							agreed = true;
 | 
				
			||||||
@ -123,7 +124,18 @@ async function happyPath(accKty, srvKty, rnd) {
 | 
				
			|||||||
	var domains = randomDomains(rnd);
 | 
						var domains = randomDomains(rnd);
 | 
				
			||||||
	if (config.debug) {
 | 
						if (config.debug) {
 | 
				
			||||||
		console.info('Get certificates for random domains:');
 | 
							console.info('Get certificates for random domains:');
 | 
				
			||||||
		console.info(domains);
 | 
							console.info(
 | 
				
			||||||
 | 
								domains
 | 
				
			||||||
 | 
									.map(function(puny) {
 | 
				
			||||||
 | 
										var uni = punycode.toUnicode(puny);
 | 
				
			||||||
 | 
										if (puny !== uni) {
 | 
				
			||||||
 | 
											return puny + ' (' + uni + ')';
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										return puny;
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									.join('\n')
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
							console.info();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var results = await acme.certificates.create({
 | 
						var results = await acme.certificates.create({
 | 
				
			||||||
		account: account,
 | 
							account: account,
 | 
				
			||||||
@ -140,8 +152,8 @@ async function happyPath(accKty, srvKty, rnd) {
 | 
				
			|||||||
		console.info(results.expires);
 | 
							console.info(results.expires);
 | 
				
			||||||
		console.info(results.cert);
 | 
							console.info(results.cert);
 | 
				
			||||||
		console.info(results.chain);
 | 
							console.info(results.chain);
 | 
				
			||||||
		console.info('');
 | 
							console.info();
 | 
				
			||||||
		console.info('');
 | 
							console.info();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -163,18 +175,20 @@ happyPath('EC', 'RSA', rnd)
 | 
				
			|||||||
function randomDomains(rnd) {
 | 
					function randomDomains(rnd) {
 | 
				
			||||||
	return ['foo-acmejs', 'bar-acmejs', '*.baz-acmejs', 'baz-acmejs'].map(
 | 
						return ['foo-acmejs', 'bar-acmejs', '*.baz-acmejs', 'baz-acmejs'].map(
 | 
				
			||||||
		function(pre) {
 | 
							function(pre) {
 | 
				
			||||||
			return pre + '-' + rnd + '.' + config.domain;
 | 
								return punycode.toASCII(pre + '-' + rnd + '.' + config.domain);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function random() {
 | 
					function random() {
 | 
				
			||||||
	return parseInt(
 | 
						return (
 | 
				
			||||||
		Math.random()
 | 
							parseInt(
 | 
				
			||||||
			.toString()
 | 
								Math.random()
 | 
				
			||||||
			.slice(2, 99),
 | 
									.toString()
 | 
				
			||||||
		10
 | 
									.slice(2, 99),
 | 
				
			||||||
	)
 | 
								10
 | 
				
			||||||
		.toString(16)
 | 
							)
 | 
				
			||||||
		.slice(0, 4);
 | 
								.toString(16)
 | 
				
			||||||
 | 
								.slice(0, 4) + '例'
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										18
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var path = require('path');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						entry: './lib/acme.js',
 | 
				
			||||||
 | 
						output: {
 | 
				
			||||||
 | 
							path: path.resolve(__dirname, 'dist'),
 | 
				
			||||||
 | 
							filename: 'acme.js',
 | 
				
			||||||
 | 
							library: 'acme',
 | 
				
			||||||
 | 
							libraryTarget: 'umd',
 | 
				
			||||||
 | 
							globalObject: "typeof self !== 'undefined' ? self : this"
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						resolve: {
 | 
				
			||||||
 | 
							aliasFields: ['webpack', 'browser'],
 | 
				
			||||||
 | 
					    mainFields: ['browser']
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user