mirror of
				https://github.com/therootcompany/acme.js.git
				synced 2024-11-16 17:29:00 +00:00 
			
		
		
		
	Compare commits
	
		
			20 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 45fd6962f2 | ||
|  | 829d34f60a | ||
|  | 0aa939a227 | ||
| bef931f28f | |||
| eb432571ca | |||
| 29a47e8fa4 | |||
| 87e3555a5a | |||
| 569c922eb0 | |||
| d10482697b | |||
| aa324e2a29 | |||
| e8c46db062 | |||
|  | 6352961fea | ||
| 333605d9b8 | |||
| 86068fe015 | |||
| cf0ee1c064 | |||
| 606dcf3c4f | |||
| 0803517711 | |||
| 0b91d9a26d | |||
| 0743aa5280 | |||
| e388bc31bc | 
							
								
								
									
										14
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								README.md
									
									
									
									
									
								
							| @ -2,10 +2,16 @@ | ||||
| 
 | ||||
| | Built by [Root](https://therootcompany.com) for [Hub](https://rootprojects.org/hub) | ||||
| 
 | ||||
| ACME.js is a _low-level_ client for Let's Encrypt. | ||||
| ## Automated Certificate Management Environment | ||||
| 
 | ||||
| ACME ([RFC 8555](https://tools.ietf.org/html/rfc8555)) is the protocol that powers **Let's Encrypt**. | ||||
| 
 | ||||
| ACME.js is a _low-level_ client that speaks RFC 8555 to get Free SSL certificates through Let's Encrypt. | ||||
| 
 | ||||
| Looking for an **easy**, _high-level_ client? Check out [Greenlock.js](https://git.rootprojects.org/root/greenlock.js). | ||||
| 
 | ||||
| # Quick Start | ||||
| 
 | ||||
| ```js | ||||
| var acme = ACME.create({ maintainerEmail, packageAgent, notify }); | ||||
| await acme.init(directoryUrl); | ||||
| @ -97,7 +103,7 @@ The public API encapsulates the three high-level steps of the ACME protocol: | ||||
|     - Challenge Presentation | ||||
|     - Certificate Redemption | ||||
| 
 | ||||
| ## Overview | ||||
| ## API Overview | ||||
| 
 | ||||
| The core API can be show in just four functions: | ||||
| 
 | ||||
| @ -177,7 +183,7 @@ These `notify` events are intended for _logging_ and debugging, NOT as a data AP | ||||
| Note: DO NOT rely on **undocumented properties**. They are experimental and **will break**. | ||||
| If you have a use case for a particular property **open an issue** - we can lock it down and document it. | ||||
| 
 | ||||
| # Example | ||||
| # Example (Full Walkthrough) | ||||
| 
 | ||||
| ### See [examples/README.md](https://git.rootprojects.org/root/acme.js/src/branch/master/examples/README.md) | ||||
| 
 | ||||
| @ -416,7 +422,7 @@ We also offer consulting for all-things-ACME and Let's Encrypt. | ||||
| 
 | ||||
| # Legal & Rules of the Road | ||||
| 
 | ||||
| ACME.jsk™ is a [trademark](https://rootprojects.org/legal/#trademark) of AJ ONeal | ||||
| ACME.js™ is a [trademark](https://rootprojects.org/legal/#trademark) of AJ ONeal | ||||
| 
 | ||||
| The rule of thumb is "attribute, but don't confuse". For example: | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										21
									
								
								account.js
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								account.js
									
									
									
									
									
								
							| @ -5,12 +5,13 @@ var U = require('./utils.js'); | ||||
| 
 | ||||
| var Keypairs = require('@root/keypairs'); | ||||
| var Enc = require('@root/encoding/bytes'); | ||||
| var agreers = {}; | ||||
| 
 | ||||
| A._getAccountKid = function (me, options) { | ||||
| 	// It's just fine if there's no account, we'll go get the key id we need via the existing key
 | ||||
| 	var kid = | ||||
| 		options.kid || | ||||
| 		(options.account && (options.account.key && options.account.key.kid)); | ||||
| 		(options.account && options.account.key && options.account.key.kid); | ||||
| 
 | ||||
| 	if (kid) { | ||||
| 		return Promise.resolve(kid); | ||||
| @ -138,8 +139,15 @@ A._registerAccount = function(me, options) { | ||||
| 			var agreeToTerms = options.agreeToTerms; | ||||
| 			if (!agreeToTerms) { | ||||
| 				agreeToTerms = function (terms) { | ||||
| 					console.log( | ||||
| 						'By using this software you accept this Subscriber Agreement and Terms of Service:' | ||||
| 					if (agreers[options.subscriberEmail]) { | ||||
| 						return true; | ||||
| 					} | ||||
| 					agreers[options.subscriberEmail] = true; | ||||
| 					console.info(); | ||||
| 					console.info( | ||||
| 						'By using this software you (' + | ||||
| 							options.subscriberEmail + | ||||
| 							') are agreeing to the following:' | ||||
| 					); | ||||
| 					console.info( | ||||
| 						'ACME Subscriber Agreement:', | ||||
| @ -147,8 +155,9 @@ A._registerAccount = function(me, options) { | ||||
| 					); | ||||
| 					console.info( | ||||
| 						'Greenlock/ACME.js Terms of Use:', | ||||
| 						terms.terms.acmeJsTermsUrl | ||||
| 						terms.acmeJsTermsUrl | ||||
| 					); | ||||
| 					console.info(); | ||||
| 					return true; | ||||
| 				}; | ||||
| 			} else if (true === agreeToTerms) { | ||||
| @ -157,8 +166,8 @@ A._registerAccount = function(me, options) { | ||||
| 				}; | ||||
| 			} | ||||
| 			return agreeToTerms({ | ||||
| 				acmeSubscriberTosUrl: me._tos, | ||||
| 				acmeJsTosUrl: 'https://rootprojects.org/legal/#terms' | ||||
| 				acmeSubscriberTermsUrl: me._tos, | ||||
| 				acmeJsTermsUrl: 'https://rootprojects.org/legal/#terms' | ||||
| 			}); | ||||
| 		}) | ||||
| 		.then(agree) | ||||
|  | ||||
							
								
								
									
										88
									
								
								acme.js
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								acme.js
									
									
									
									
									
								
							| @ -474,7 +474,7 @@ ACME._dryRun = function(me, realOptions, zonenames) { | ||||
| 		var selected = []; | ||||
| 		noopts.order._claims = claims.slice(0); | ||||
| 		noopts.notify = function (ev, params) { | ||||
| 			if ('challenge_select' === ev) { | ||||
| 			if ('_challenge_select' === ev) { | ||||
| 				selected.push(params.challenge); | ||||
| 			} | ||||
| 		}; | ||||
| @ -486,6 +486,7 @@ ACME._dryRun = function(me, realOptions, zonenames) { | ||||
| 					type: ch.type | ||||
| 					//challenge: ch
 | ||||
| 				}); | ||||
| 				// ignore promise return
 | ||||
| 				noopts.challenges[ch.type] | ||||
| 					.remove({ challenge: ch }) | ||||
| 					.catch(function (err) { | ||||
| @ -755,12 +756,8 @@ ACME._postChallenge = function(me, options, kid, auth) { | ||||
| 			altname: altname | ||||
| 		}); | ||||
| 
 | ||||
| 		if ('processing' === resp.body.status) { | ||||
| 			//#console.debug('poll: again', auth.url);
 | ||||
| 			return ACME._wait(RETRY_INTERVAL).then(pollStatus); | ||||
| 		} | ||||
| 
 | ||||
| 		// This state should never occur
 | ||||
| 		// State can be pending while waiting ACME server to transition to
 | ||||
| 		// processing
 | ||||
| 		if ('pending' === resp.body.status) { | ||||
| 			if (count >= MAX_PEND) { | ||||
| 				return ACME._wait(RETRY_INTERVAL) | ||||
| @ -768,13 +765,25 @@ ACME._postChallenge = function(me, options, kid, auth) { | ||||
| 					.then(respondToChallenge); | ||||
| 			} | ||||
| 			//#console.debug('poll: again', auth.url);
 | ||||
| 			return ACME._wait(RETRY_INTERVAL).then(respondToChallenge); | ||||
| 			return ACME._wait(RETRY_INTERVAL).then(pollStatus); | ||||
| 		} | ||||
| 
 | ||||
| 		if ('processing' === resp.body.status) { | ||||
| 			//#console.debug('poll: again', auth.url);
 | ||||
| 			return ACME._wait(RETRY_INTERVAL).then(pollStatus); | ||||
| 		} | ||||
| 
 | ||||
| 		// REMOVE DNS records as soon as the state is non-processing
 | ||||
| 		// (valid or invalid or other)
 | ||||
| 		try { | ||||
| 			options.challenges[auth.type].remove({ challenge: auth }); | ||||
| 			options.challenges[auth.type] | ||||
| 				.remove({ challenge: auth }) | ||||
| 				.catch(function (err) { | ||||
| 					err.action = 'challenge_remove'; | ||||
| 					err.altname = auth.altname; | ||||
| 					err.type = auth.type; | ||||
| 					ACME._notify(me, options, 'error', err); | ||||
| 				}); | ||||
| 		} catch (e) {} | ||||
| 
 | ||||
| 		if ('valid' === resp.body.status) { | ||||
| @ -893,6 +902,15 @@ ACME._setChallenges = function(me, options, order) { | ||||
| 				placed.push(selected); | ||||
| 				ACME._notify(me, options, 'challenge_select', { | ||||
| 					// API-locked
 | ||||
| 					altname: ACME._untame( | ||||
| 						claim.identifier.value, | ||||
| 						claim.wildcard | ||||
| 					), | ||||
| 					type: selected.type, | ||||
| 					dnsHost: selected.dnsHost, | ||||
| 					keyAuthorization: selected.keyAuthorization | ||||
| 				}); | ||||
| 				ACME._notify(me, options, '_challenge_select', { | ||||
| 					altname: ACME._untame( | ||||
| 						claim.identifier.value, | ||||
| 						claim.wildcard | ||||
| @ -995,14 +1013,7 @@ ACME._pollOrderStatus = function(me, options, kid, order, verifieds) { | ||||
| 	var body = { csr: csr64 }; | ||||
| 	var payload = JSON.stringify(body); | ||||
| 
 | ||||
| 	function pollCert() { | ||||
| 		//#console.debug('[ACME.js] pollCert:', order._finalizeUrl);
 | ||||
| 		return U._jwsRequest(me, { | ||||
| 			accountKey: options.accountKey, | ||||
| 			url: order._finalizeUrl, | ||||
| 			protected: { kid: kid }, | ||||
| 			payload: Enc.strToBuf(payload) | ||||
| 		}).then(function(resp) { | ||||
| 	function processResponse(resp) { | ||||
| 		ACME._notify(me, options, 'certificate_status', { | ||||
| 			subject: options.domains[0], | ||||
| 			status: resp.body.status | ||||
| @ -1018,7 +1029,7 @@ ACME._pollOrderStatus = function(me, options, kid, order, verifieds) { | ||||
| 		} | ||||
| 
 | ||||
| 		if ('processing' === resp.body.status) { | ||||
| 				return ACME._wait().then(pollCert); | ||||
| 			return ACME._wait().then(pollStatus); | ||||
| 		} | ||||
| 
 | ||||
| 		if (me.debug) { | ||||
| @ -1058,10 +1069,28 @@ ACME._pollOrderStatus = function(me, options, kid, order, verifieds) { | ||||
| 		return Promise.reject( | ||||
| 			E.UNHANDLED_ORDER_STATUS(options, verifieds, resp) | ||||
| 		); | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	return pollCert(); | ||||
| 	function pollStatus() { | ||||
| 		return U._jwsRequest(me, { | ||||
| 			accountKey: options.accountKey, | ||||
| 			url: order._orderUrl, | ||||
| 			protected: { kid: kid }, | ||||
| 			payload: Enc.binToBuf('') | ||||
| 		}).then(processResponse); | ||||
| 	} | ||||
| 
 | ||||
| 	function finalizeOrder() { | ||||
| 		//#console.debug('[ACME.js] pollCert:', order._finalizeUrl);
 | ||||
| 		return U._jwsRequest(me, { | ||||
| 			accountKey: options.accountKey, | ||||
| 			url: order._finalizeUrl, | ||||
| 			protected: { kid: kid }, | ||||
| 			payload: Enc.strToBuf(payload) | ||||
| 		}).then(processResponse); | ||||
| 	} | ||||
| 
 | ||||
| 	return finalizeOrder(); | ||||
| }; | ||||
| 
 | ||||
| ACME._redeemCert = function (me, options, kid, voucher) { | ||||
| @ -1219,14 +1248,8 @@ ACME._prepRequest = function(me, options) { | ||||
| 		options.domains = options.domains || _csr.altnames; | ||||
| 		_csr.altnames = _csr.altnames || []; | ||||
| 		if ( | ||||
| 			options.domains | ||||
| 				.slice(0) | ||||
| 				.sort() | ||||
| 				.join(' ') !== | ||||
| 			_csr.altnames | ||||
| 				.slice(0) | ||||
| 				.sort() | ||||
| 				.join(' ') | ||||
| 			options.domains.slice(0).sort().join(' ') !== | ||||
| 			_csr.altnames.slice(0).sort().join(' ') | ||||
| 		) { | ||||
| 			return Promise.reject( | ||||
| 				new Error('certificate altnames do not match requested domains') | ||||
| @ -1330,10 +1353,7 @@ ACME._csrToUrlBase64 = function(csr) { | ||||
| 	// TODO use PEM.parseBlock()
 | ||||
| 	// nix PEM headers, if any
 | ||||
| 	if ('-' === csr[0]) { | ||||
| 		csr = csr | ||||
| 			.split(/\n+/) | ||||
| 			.slice(1, -1) | ||||
| 			.join(''); | ||||
| 		csr = csr.split(/\n+/).slice(1, -1).join(''); | ||||
| 	} | ||||
| 	return Enc.base64ToUrlBase64(csr.trim().replace(/\s+/g, '')); | ||||
| }; | ||||
| @ -1342,9 +1362,7 @@ ACME._csrToUrlBase64 = function(csr) { | ||||
| ACME._prnd = function (n) { | ||||
| 	var rnd = ''; | ||||
| 	while (rnd.length / 2 < n) { | ||||
| 		var i = Math.random() | ||||
| 			.toString() | ||||
| 			.substr(2); | ||||
| 		var i = Math.random().toString().substr(2); | ||||
| 		var h = parseInt(i, 10).toString(16); | ||||
| 		if (h.length % 2) { | ||||
| 			h = '0' + h; | ||||
|  | ||||
							
								
								
									
										21
									
								
								examples/https-sni-server.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								examples/https-sni-server.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| var https = require('http2'); | ||||
| var tls = require('tls'); | ||||
| var fs = require('fs'); | ||||
| 
 | ||||
| var key = fs.readFileSync('./privkey.pem'); | ||||
| var cert = fs.readFileSync('./fullchain.pem'); | ||||
| 
 | ||||
| function SNICallback(servername, cb) { | ||||
| 	console.log('sni:', servername); | ||||
| 	cb(null, tls.createSecureContext({ key, cert })); | ||||
| } | ||||
| 
 | ||||
| var server = https | ||||
| 	.createSecureServer({ SNICallback: SNICallback }, function (req, res) { | ||||
| 		res.end('Hello, Encrypted World!'); | ||||
| 	}) | ||||
| 	.listen(443, function () { | ||||
| 		console.info('Listening on', server.address()); | ||||
| 	}); | ||||
| @ -9,9 +9,6 @@ sha2.sum = function(alg, str) { | ||||
| 		var sha = 'sha' + String(alg).replace(/^sha-?/i, ''); | ||||
| 		// utf8 is the default for strings
 | ||||
| 		var buf = Buffer.from(str); | ||||
| 		return crypto | ||||
| 			.createHash(sha) | ||||
| 			.update(buf) | ||||
| 			.digest(); | ||||
| 		return crypto.createHash(sha).update(buf).digest(); | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
| @ -33,9 +33,10 @@ M.init = function(me) { | ||||
| }; | ||||
| 
 | ||||
| M._init = function (me, tz, locale) { | ||||
| 	// prevent a stampede from misconfigured clients in an eternal loop
 | ||||
| 	setTimeout(function () { | ||||
| 		// prevent a stampede from misconfigured clients in an eternal loop
 | ||||
| 		me.request({ | ||||
| 			timeout: 3000, | ||||
| 			method: 'GET', | ||||
| 			url: 'https://api.rootprojects.org/api/nonce', | ||||
| 			json: true | ||||
| @ -47,6 +48,7 @@ M._init = function(me, tz, locale) { | ||||
| 			}) | ||||
| 			.then(function (hashcash) { | ||||
| 				var req = { | ||||
| 					timeout: 3000, | ||||
| 					headers: { | ||||
| 						'x-root-nonce-v1': hashcash | ||||
| 					}, | ||||
| @ -60,10 +62,13 @@ M._init = function(me, tz, locale) { | ||||
| 						locale: locale | ||||
| 					} | ||||
| 				}; | ||||
| 				return me | ||||
| 					.request(req) | ||||
| 				return me.request(req); | ||||
| 			}) | ||||
| 			.catch(function (err) { | ||||
| 						if (true || me.debug) { | ||||
| 				if (me.debug) { | ||||
| 					console.error( | ||||
| 						'error adding maintainer to support notices:' | ||||
| 					); | ||||
| 					console.error(err); | ||||
| 				} | ||||
| 			}) | ||||
| @ -71,7 +76,6 @@ M._init = function(me, tz, locale) { | ||||
| 				oldCollegeTries[me.maintainerEmail] = true; | ||||
| 				//console.log(resp);
 | ||||
| 			}); | ||||
| 			}); | ||||
| 	}, me.__timeout || 3000); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										21
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										21
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| { | ||||
| 	"name": "@root/acme", | ||||
| 	"version": "3.0.1", | ||||
| 	"version": "3.1.1", | ||||
| 	"lockfileVersion": 1, | ||||
| 	"requires": true, | ||||
| 	"dependencies": { | ||||
| @ -16,7 +16,6 @@ | ||||
| 			"version": "0.8.1", | ||||
| 			"resolved": "https://registry.npmjs.org/@root/csr/-/csr-0.8.1.tgz", | ||||
| 			"integrity": "sha512-hKl0VuE549TK6SnS2Yn9nRvKbFZXn/oAg+dZJU/tlKl/f/0yRXeuUzf8akg3JjtJq+9E592zDqeXZ7yyrg8fSQ==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"@root/asn1": "^1.0.0", | ||||
| 				"@root/pem": "^1.0.4", | ||||
| @ -29,9 +28,9 @@ | ||||
| 			"integrity": "sha512-OaEub02ufoU038gy6bsNHQOjIn8nUjGiLcaRmJ40IUykneJkIW5fxDqKxQx48cszuNflYldsJLPPXCrGfHs8yQ==" | ||||
| 		}, | ||||
| 		"@root/keypairs": { | ||||
| 			"version": "0.9.0", | ||||
| 			"resolved": "https://registry.npmjs.org/@root/keypairs/-/keypairs-0.9.0.tgz", | ||||
| 			"integrity": "sha512-NXE2L9Gv7r3iC4kB/gTPZE1vO9Ox/p14zDzAJ5cGpTpytbWOlWF7QoHSJbtVX4H7mRG/Hp7HR3jWdWdb2xaaXg==", | ||||
| 			"version": "0.10.0", | ||||
| 			"resolved": "https://registry.npmjs.org/@root/keypairs/-/keypairs-0.10.0.tgz", | ||||
| 			"integrity": "sha512-t8VocY46Mtb0NTsxzyLLf5tsgfw0BXLYVADAyiRdEdqHcvPFGJdjkXNtHVQuSV/FMaC65iTOHVP4E6X8iT3Ikg==", | ||||
| 			"requires": { | ||||
| 				"@root/encoding": "^1.0.1", | ||||
| 				"@root/pem": "^1.0.4", | ||||
| @ -44,9 +43,9 @@ | ||||
| 			"integrity": "sha512-rEUDiUsHtild8GfIjFE9wXtcVxeS+ehCJQBwbQQ3IVfORKHK93CFnRtkr69R75lZFjcmKYVc+AXDB+AeRFOULA==" | ||||
| 		}, | ||||
| 		"@root/request": { | ||||
| 			"version": "1.3.11", | ||||
| 			"resolved": "https://registry.npmjs.org/@root/request/-/request-1.3.11.tgz", | ||||
| 			"integrity": "sha512-3a4Eeghcjsfe6zh7EJ+ni1l8OK9Fz2wL1OjP4UCa0YdvtH39kdXB9RGWuzyNv7dZi0+Ffkc83KfH0WbPMiuJFw==" | ||||
| 			"version": "1.6.1", | ||||
| 			"resolved": "https://registry.npmjs.org/@root/request/-/request-1.6.1.tgz", | ||||
| 			"integrity": "sha512-8wrWyeBLRp7T8J36GkT3RODJ6zYmL0/maWlAUD5LOXT28D3TDquUepyYDKYANNA3Gc8R5ZCgf+AXvSTYpJEWwQ==" | ||||
| 		}, | ||||
| 		"@root/x509": { | ||||
| 			"version": "0.7.2", | ||||
| @ -153,9 +152,9 @@ | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"glob": { | ||||
| 			"version": "7.1.5", | ||||
| 			"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", | ||||
| 			"integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", | ||||
| 			"version": "7.1.6", | ||||
| 			"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", | ||||
| 			"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"fs.realpath": "^1.0.0", | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
| 	"name": "@root/acme", | ||||
| 	"version": "3.0.4", | ||||
| 	"version": "3.1.1", | ||||
| 	"description": "Free SSL certificates for Node.js and Browsers. Issued via Let's Encrypt", | ||||
| 	"homepage": "https://rootprojects.org/acme/", | ||||
| 	"main": "acme.js", | ||||
| @ -42,14 +42,14 @@ | ||||
| 	"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", | ||||
| 	"license": "MPL-2.0", | ||||
| 	"dependencies": { | ||||
| 		"@root/csr": "^0.8.1", | ||||
| 		"@root/encoding": "^1.0.1", | ||||
| 		"@root/keypairs": "^0.9.0", | ||||
| 		"@root/keypairs": "^0.10.0", | ||||
| 		"@root/pem": "^1.0.4", | ||||
| 		"@root/request": "^1.3.11", | ||||
| 		"@root/request": "^1.6.1", | ||||
| 		"@root/x509": "^0.7.2" | ||||
| 	}, | ||||
| 	"devDependencies": { | ||||
| 		"@root/csr": "^0.8.1", | ||||
| 		"dig.js": "^1.3.9", | ||||
| 		"dns-suite": "^1.2.13", | ||||
| 		"dotenv": "^8.1.0", | ||||
|  | ||||
| @ -247,12 +247,7 @@ module.exports = function() { | ||||
| 
 | ||||
| 	function random() { | ||||
| 		return ( | ||||
| 			parseInt( | ||||
| 				Math.random() | ||||
| 					.toString() | ||||
| 					.slice(2, 99), | ||||
| 				10 | ||||
| 			) | ||||
| 			parseInt(Math.random().toString().slice(2, 99), 10) | ||||
| 				.toString(16) | ||||
| 				.slice(0, 4) + '例' | ||||
| 		); | ||||
|  | ||||
| @ -33,10 +33,7 @@ native | ||||
| 
 | ||||
| 				var now = Date.now(); | ||||
| 				var nonce = '20'; | ||||
| 				var needle = crypto | ||||
| 					.randomBytes(3) | ||||
| 					.toString('hex') | ||||
| 					.slice(0, 5); | ||||
| 				var needle = crypto.randomBytes(3).toString('hex').slice(0, 5); | ||||
| 				native | ||||
| 					._hashcash({ | ||||
| 						alg: 'SHA-256', | ||||
|  | ||||
							
								
								
									
										9
									
								
								utils.js
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								utils.js
									
									
									
									
									
								
							| @ -11,12 +11,13 @@ U._jwsRequest = function(me, bigopts) { | ||||
| 		bigopts.protected.nonce = nonce; | ||||
| 		bigopts.protected.url = bigopts.url; | ||||
| 		// protected.alg: added by Keypairs.signJws
 | ||||
| 		if (!bigopts.protected.jwk) { | ||||
| 			// protected.kid must be overwritten due to ACME's interpretation of the spec
 | ||||
| 			if (!('kid' in bigopts.protected)) { | ||||
| 		if (bigopts.protected.jwk) { | ||||
| 			bigopts.protected.kid = false; | ||||
| 		} else if (!('kid' in bigopts.protected)) { | ||||
| 			// protected.kid must be provided according to ACME's interpretation of the spec
 | ||||
| 			// (using the provided URL rather than the Key's Thumbprint as Key ID)
 | ||||
| 			bigopts.protected.kid = bigopts.kid; | ||||
| 		} | ||||
| 		} | ||||
| 
 | ||||
| 		// this will shasum the thumbprint the 2nd time
 | ||||
| 		return Keypairs.signJws({ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user