| 
									
										
										
										
											2018-03-15 00:41:00 -06:00
										 |  |  | /*! | 
					
						
							|  |  |  |  * acme-v2.js | 
					
						
							|  |  |  |  * Copyright(c) 2018 AJ ONeal <aj@ppl.family> https://ppl.family
 | 
					
						
							|  |  |  |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var defaults = { | 
					
						
							|  |  |  |   productionServerUrl:    'https://acme-v02.api.letsencrypt.org/directory' | 
					
						
							|  |  |  | , stagingServerUrl:       'https://acme-staging-v02.api.letsencrypt.org/directory' | 
					
						
							|  |  |  | , acmeChallengePrefix:    '/.well-known/acme-challenge/' | 
					
						
							|  |  |  | , knownEndpoints:         [ 'keyChange', 'meta', 'newAccount', 'newNonce', 'newOrder', 'revokeCert' ] | 
					
						
							|  |  |  | , challengeType:          'http-01' // dns-01
 | 
					
						
							|  |  |  | , keyType:                'rsa' // ecdsa
 | 
					
						
							|  |  |  | , keySize:                2048 // 256
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function create(deps) { | 
					
						
							|  |  |  |   if (!deps) { deps = {}; } | 
					
						
							|  |  |  |   deps.LeCore = {}; | 
					
						
							|  |  |  |   deps.pkg = deps.pkg || require('./package.json'); | 
					
						
							|  |  |  |   deps.os = deps.os || require('os'); | 
					
						
							|  |  |  |   deps.process = deps.process || require('process'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var uaDefaults = { | 
					
						
							|  |  |  |       pkg: "Greenlock/" + deps.pkg.version | 
					
						
							|  |  |  |     , os: " (" + deps.os.type() + "; " + deps.process.arch + " " + deps.os.platform() + " " + deps.os.release() + ")" | 
					
						
							|  |  |  |     , node: " Node.js/" + deps.process.version | 
					
						
							|  |  |  |     , user: '' | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   //var currentUAProps;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function getUaString() { | 
					
						
							|  |  |  |     var userAgent = ''; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //Object.keys(currentUAProps)
 | 
					
						
							|  |  |  |     Object.keys(uaDefaults).forEach(function (key) { | 
					
						
							|  |  |  |       userAgent += uaDefaults[key]; | 
					
						
							|  |  |  |       //userAgent += currentUAProps[key];
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return userAgent.trim(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function getRequest(opts) { | 
					
						
							|  |  |  |     if (!opts) { opts = {}; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return deps.request.defaults({ | 
					
						
							|  |  |  |       headers: { | 
					
						
							|  |  |  |         'User-Agent': opts.userAgent || getUaString() | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   deps.request = deps.request || require('request'); | 
					
						
							|  |  |  |   deps.promisify = deps.promisify || require('util').promisify; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var directoryUrl = deps.directoryUrl || defaults.stagingServerUrl; | 
					
						
							|  |  |  |   var request = deps.promisify(getRequest({})); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var crypto = require('crypto'); | 
					
						
							|  |  |  | 			RSA.signJws = RSA.generateJws = RSA.generateSignatureJws = RSA.generateSignatureJwk = | 
					
						
							|  |  |  | 			function (keypair, payload, nonce) { | 
					
						
							|  |  |  |         var prot = {}; | 
					
						
							|  |  |  |         if (nonce) { | 
					
						
							|  |  |  |           if ('string' === typeof nonce) { | 
					
						
							|  |  |  |             prot.nonce = nonce; | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             prot = nonce; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 				keypair = RSA._internal.import(keypair); | 
					
						
							|  |  |  | 				keypair = RSA._internal.importForge(keypair); | 
					
						
							|  |  |  | 				keypair.publicKeyJwk = RSA.exportPublicJwk(keypair); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Compute JWS signature
 | 
					
						
							|  |  |  | 				var protectedHeader = ""; | 
					
						
							|  |  |  | 				if (Object.keys(prot).length) { | 
					
						
							|  |  |  | 					protectedHeader = JSON.stringify(prot); // { alg: prot.alg, nonce: prot.nonce, url: prot.url });
 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				var protected64 = RSA.utils.toWebsafeBase64(new Buffer(protectedHeader).toString('base64')); | 
					
						
							|  |  |  | 				var payload64 = RSA.utils.toWebsafeBase64(payload.toString('base64')); | 
					
						
							|  |  |  | 				var raw = protected64 + "." + payload64; | 
					
						
							|  |  |  | 				var sha256Buf = crypto.createHash('sha256').update(raw).digest(); | 
					
						
							|  |  |  | 				var sig64; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (RSA._URSA) { | 
					
						
							|  |  |  | 					sig64 = RSA._ursaGenerateSig(keypair, sha256Buf); | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					sig64 = RSA._forgeGenerateSig(keypair, sha256Buf); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return { | 
					
						
							|  |  |  |           /* | 
					
						
							|  |  |  | 					header: { | 
					
						
							|  |  |  | 						alg: "RS256" | 
					
						
							|  |  |  | 					, jwk: keypair.publicKeyJwk | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  |           */ | 
					
						
							|  |  |  | 				  protected: protected64 | 
					
						
							|  |  |  | 				, payload: payload64 | 
					
						
							|  |  |  | 				, signature: sig64 | 
					
						
							|  |  |  | 				}; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  |   var acme2 = { | 
					
						
							|  |  |  |     getAcmeUrls: function () { | 
					
						
							|  |  |  |       var me = this; | 
					
						
							|  |  |  |       return request({ url: directoryUrl }).then(function (resp) { | 
					
						
							|  |  |  |         me._directoryUrls = JSON.parse(resp.body); | 
					
						
							|  |  |  |         me._tos = me._directoryUrls.meta.termsOfService; | 
					
						
							|  |  |  |         return me._directoryUrls; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   , getNonce: function () { | 
					
						
							|  |  |  |       var me = this; | 
					
						
							|  |  |  |       return request({ method: 'HEAD', url: me._directoryUrls.newNonce }).then(function (resp) { | 
					
						
							|  |  |  |         me._nonce = resp.toJSON().headers['replay-nonce']; | 
					
						
							|  |  |  |         return me._nonce; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 		// ACME RFC Section 7.3 Account Creation
 | 
					
						
							|  |  |  | 		/* | 
					
						
							|  |  |  | 		 { | 
					
						
							|  |  |  | 			 "protected": base64url({ | 
					
						
							|  |  |  | 				 "alg": "ES256", | 
					
						
							|  |  |  | 				 "jwk": {...}, | 
					
						
							|  |  |  | 				 "nonce": "6S8IqOGY7eL2lsGoTZYifg", | 
					
						
							|  |  |  | 				 "url": "https://example.com/acme/new-account" | 
					
						
							|  |  |  | 			 }), | 
					
						
							|  |  |  | 			 "payload": base64url({ | 
					
						
							|  |  |  | 				 "termsOfServiceAgreed": true, | 
					
						
							|  |  |  | 				 "onlyReturnExisting": false, | 
					
						
							|  |  |  | 				 "contact": [ | 
					
						
							|  |  |  | 					 "mailto:cert-admin@example.com", | 
					
						
							|  |  |  | 					 "mailto:admin@example.com" | 
					
						
							|  |  |  | 				 ] | 
					
						
							|  |  |  | 			 }), | 
					
						
							|  |  |  | 			 "signature": "RZPOnYoPs1PhjszF...-nh6X1qtOFPB519I" | 
					
						
							|  |  |  | 		 } | 
					
						
							|  |  |  | 		*/ | 
					
						
							|  |  |  |   , registerNewAccount: function (options) { | 
					
						
							|  |  |  |       var me = this; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-15 00:41:00 -06:00
										 |  |  |       var body = { | 
					
						
							|  |  |  |         termsOfServiceAgreed: true | 
					
						
							|  |  |  |       , onlyReturnExisting: false | 
					
						
							|  |  |  |       , contact: [ 'mailto:' + options.email ] | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  |       /* | 
					
						
							|  |  |  |        "externalAccountBinding": { | 
					
						
							|  |  |  |          "protected": base64url({ | 
					
						
							|  |  |  |            "alg": "HS256", | 
					
						
							|  |  |  |            "kid": /* key identifier from CA *//*, | 
					
						
							|  |  |  |            "url": "https://example.com/acme/new-account" | 
					
						
							|  |  |  |          }), | 
					
						
							|  |  |  |          "payload": base64url(/* same as in "jwk" above *//*), | 
					
						
							|  |  |  |          "signature": /* MAC using MAC key from CA *//* | 
					
						
							|  |  |  |        } | 
					
						
							|  |  |  |       */ | 
					
						
							| 
									
										
										
										
											2018-03-15 00:41:00 -06:00
										 |  |  |       }; | 
					
						
							|  |  |  | 			var payload = JSON.stringify(body, null, 2); | 
					
						
							|  |  |  | 			var jws = RSA.signJws( | 
					
						
							|  |  |  |         options.keypair | 
					
						
							|  |  |  |       , new Buffer(payload) | 
					
						
							|  |  |  |       , { nonce: me._nonce, alg: 'RS256', url: me._directoryUrls.newAccount, jwk: RSA.exportPublicJwk(options.keypair) } | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       console.log('jws:'); | 
					
						
							|  |  |  |       console.log(jws); | 
					
						
							|  |  |  |       return request({ | 
					
						
							|  |  |  |         method: 'POST' | 
					
						
							|  |  |  |       , url: me._directoryUrls.newAccount | 
					
						
							|  |  |  |       , headers: { 'Content-Type': 'application/jose+json' } | 
					
						
							|  |  |  |       , json: jws | 
					
						
							|  |  |  |       }).then(function (resp) { | 
					
						
							|  |  |  |         me._nonce = resp.toJSON().headers['replay-nonce']; | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  |         var location = resp.toJSON().headers['location']; | 
					
						
							|  |  |  |         console.log(location); // the account id url
 | 
					
						
							| 
									
										
										
										
											2018-03-15 00:41:00 -06:00
										 |  |  |         console.log(resp.toJSON()); | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  | 				me._kid = location; | 
					
						
							| 
									
										
										
										
											2018-03-15 00:41:00 -06:00
										 |  |  |         return resp.body; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  | 		/* | 
					
						
							|  |  |  | 		 POST /acme/new-order HTTP/1.1 | 
					
						
							|  |  |  | 		 Host: example.com | 
					
						
							|  |  |  | 		 Content-Type: application/jose+json | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 { | 
					
						
							|  |  |  | 			 "protected": base64url({ | 
					
						
							|  |  |  | 				 "alg": "ES256", | 
					
						
							|  |  |  | 				 "kid": "https://example.com/acme/acct/1", | 
					
						
							|  |  |  | 				 "nonce": "5XJ1L3lEkMG7tR6pA00clA", | 
					
						
							|  |  |  | 				 "url": "https://example.com/acme/new-order" | 
					
						
							|  |  |  | 			 }), | 
					
						
							|  |  |  | 			 "payload": base64url({ | 
					
						
							|  |  |  | 				 "identifiers": [{"type:"dns","value":"example.com"}], | 
					
						
							|  |  |  | 				 "notBefore": "2016-01-01T00:00:00Z", | 
					
						
							|  |  |  | 				 "notAfter": "2016-01-08T00:00:00Z" | 
					
						
							|  |  |  | 			 }), | 
					
						
							|  |  |  | 			 "signature": "H6ZXtGjTZyUnPeKn...wEA4TklBdh3e454g" | 
					
						
							|  |  |  | 		 } | 
					
						
							|  |  |  | 		*/ | 
					
						
							| 
									
										
										
										
											2018-03-20 01:24:36 -06:00
										 |  |  |   , _getChallenges: function (options, auth) { | 
					
						
							|  |  |  |       console.log('\n[DEBUG] getChallenges\n'); | 
					
						
							|  |  |  |       return request({ method: 'GET', url: auth, json: true }).then(function (resp) { | 
					
						
							|  |  |  |         console.log('Authorization:'); | 
					
						
							|  |  |  |         console.log(resp.body.challenges); | 
					
						
							|  |  |  |         return resp.body.challenges; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // https://tools.ietf.org/html/draft-ietf-acme-acme-10#section-7.5.1
 | 
					
						
							|  |  |  |   , _postChallenge: function (options, ch) { | 
					
						
							|  |  |  | 			var me = this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var body = { }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var payload = JSON.stringify(body); | 
					
						
							|  |  |  | 			//var payload = JSON.stringify(body, null, 2);
 | 
					
						
							|  |  |  | 			var jws = RSA.signJws( | 
					
						
							|  |  |  |         options.keypair | 
					
						
							|  |  |  |       , new Buffer(payload) | 
					
						
							|  |  |  |       , { nonce: me._nonce, alg: 'RS256', url: ch.url, kid: me._kid } | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var thumbprint = RSA.thumbprint(options.keypair); | 
					
						
							|  |  |  |       var keyAuthorization = ch.token + '.' + thumbprint; | 
					
						
							|  |  |  |       //   keyAuthorization = token || '.' || base64url(JWK_Thumbprint(accountKey))
 | 
					
						
							|  |  |  |       //   /.well-known/acme-challenge/:token
 | 
					
						
							|  |  |  |       console.log('type:'); | 
					
						
							|  |  |  |       console.log(ch.type); | 
					
						
							|  |  |  |       console.log('ch.token:'); | 
					
						
							|  |  |  |       console.log(ch.token); | 
					
						
							|  |  |  |       console.log('thumbprint:'); | 
					
						
							|  |  |  |       console.log(thumbprint); | 
					
						
							|  |  |  |       console.log('keyAuthorization:'); | 
					
						
							|  |  |  |       console.log(keyAuthorization); | 
					
						
							|  |  |  |       /* | 
					
						
							|  |  |  |       options.setChallenge(ch.token, thumbprint, keyAuthorization, function (err) { | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       */ | 
					
						
							|  |  |  |       function wait(ms) { | 
					
						
							|  |  |  |         return new Promise(function (resolve) { | 
					
						
							|  |  |  |           setTimeout(resolve, (ms || 1100)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       function pollStatus() { | 
					
						
							|  |  |  |         console.log('\n[DEBUG] statusChallenge\n'); | 
					
						
							|  |  |  |         return request({ method: 'GET', url: ch.url, json: true }).then(function (resp) { | 
					
						
							|  |  |  |           console.error('poll: resp.body:'); | 
					
						
							|  |  |  |           console.error(resp.body); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if ('pending' === resp.body.status) { | 
					
						
							|  |  |  |             console.log('poll: again'); | 
					
						
							|  |  |  |             return wait().then(pollStatus); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if ('valid' === resp.body.status) { | 
					
						
							|  |  |  |             console.log('poll: valid'); | 
					
						
							|  |  |  |             return resp.body; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if (!resp.body.status) { | 
					
						
							|  |  |  |             console.error("[acme-v2] (y) bad challenge state:"); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           else if ('invalid' === resp.body.status) { | 
					
						
							|  |  |  |             console.error("[acme-v2] (x) invalid challenge state:"); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           else { | 
					
						
							|  |  |  |             console.error("[acme-v2] (z) bad challenge state:"); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       console.log('\n[DEBUG] postChallenge\n'); | 
					
						
							|  |  |  |       //console.log('\n[DEBUG] stop to fix things\n'); return;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       function post() { | 
					
						
							|  |  |  |         return request({ | 
					
						
							|  |  |  |           method: 'POST' | 
					
						
							|  |  |  |         , url: ch.url | 
					
						
							|  |  |  |         , headers: { 'Content-Type': 'application/jose+json' } | 
					
						
							|  |  |  |         , json: jws | 
					
						
							|  |  |  |         }).then(function (resp) { | 
					
						
							|  |  |  |           me._nonce = resp.toJSON().headers['replay-nonce']; | 
					
						
							|  |  |  |           console.log('respond to challenge: resp.body:'); | 
					
						
							|  |  |  |           console.log(resp.body); | 
					
						
							|  |  |  |           return wait().then(pollStatus); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return wait(20 * 1000).then(post); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   , _finalizeOrder: function (options, validatedDomains) { | 
					
						
							|  |  |  |       console.log('finalizeOrder:'); | 
					
						
							|  |  |  | 			var me = this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var csr = RSA.generateCsrWeb64(options.certificateKeypair, validatedDomains); | 
					
						
							|  |  |  |       var body = { csr: csr }; | 
					
						
							|  |  |  |       var payload = JSON.stringify(body); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       function wait(ms) { | 
					
						
							|  |  |  |         return new Promise(function (resolve) { | 
					
						
							|  |  |  |           setTimeout(resolve, (ms || 1100)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       function pollCert() { | 
					
						
							|  |  |  |         //var payload = JSON.stringify(body, null, 2);
 | 
					
						
							|  |  |  |         var jws = RSA.signJws( | 
					
						
							|  |  |  |           options.keypair | 
					
						
							|  |  |  |         , new Buffer(payload) | 
					
						
							|  |  |  |         , { nonce: me._nonce, alg: 'RS256', url: me._finalize, kid: me._kid } | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         console.log('finalize:', me._finalize); | 
					
						
							|  |  |  |         return request({ | 
					
						
							|  |  |  |           method: 'POST' | 
					
						
							|  |  |  |         , url: me._finalize | 
					
						
							|  |  |  |         , headers: { 'Content-Type': 'application/jose+json' } | 
					
						
							|  |  |  |         , json: jws | 
					
						
							|  |  |  |         }).then(function (resp) { | 
					
						
							|  |  |  |           me._nonce = resp.toJSON().headers['replay-nonce']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           console.log('order finalized: resp.body:'); | 
					
						
							|  |  |  |           console.log(resp.body); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if ('processing' === resp.body.status) { | 
					
						
							|  |  |  |             return wait().then(pollCert); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if ('valid' === resp.body.status) { | 
					
						
							|  |  |  |             me._expires = resp.body.expires; | 
					
						
							|  |  |  |             me._certificate = resp.body.certificate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return resp.body; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if ('invalid' === resp.body.status) { | 
					
						
							|  |  |  |             console.error('cannot finalize: badness'); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           console.error('(x) cannot finalize: badness'); | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return pollCert(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   , _getCertificate: function (auth) { | 
					
						
							|  |  |  |       var me = this; | 
					
						
							|  |  |  |       return request({ method: 'GET', url: me._certificate, json: true }).then(function (resp) { | 
					
						
							|  |  |  |         console.log('Certificate:'); | 
					
						
							|  |  |  |         console.log(resp.body); | 
					
						
							|  |  |  |         return resp.body; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  |   , getCertificate: function (options, cb) { | 
					
						
							|  |  |  | 			var me = this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var body = { | 
					
						
							|  |  |  | 				identifiers: [ | 
					
						
							| 
									
										
										
										
											2018-03-20 01:24:36 -06:00
										 |  |  |           { type: "dns" , value: "test.ppl.family" } | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  | 				/* | 
					
						
							|  |  |  |         , {	type: "dns" , value: "example.net" } | 
					
						
							|  |  |  | 				*/ | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         //, "notBefore": "2016-01-01T00:00:00Z"
 | 
					
						
							|  |  |  |        //, "notAfter": "2016-01-08T00:00:00Z"
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var payload = JSON.stringify(body); | 
					
						
							|  |  |  | 			//var payload = JSON.stringify(body, null, 2);
 | 
					
						
							|  |  |  | 			var jws = RSA.signJws( | 
					
						
							|  |  |  |         options.keypair | 
					
						
							|  |  |  |       , new Buffer(payload) | 
					
						
							|  |  |  |       , { nonce: me._nonce, alg: 'RS256', url: me._directoryUrls.newOrder, kid: me._kid } | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-20 01:24:36 -06:00
										 |  |  |       console.log('\n[DEBUG] newOrder\n'); | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  |       return request({ | 
					
						
							|  |  |  |         method: 'POST' | 
					
						
							|  |  |  |       , url: me._directoryUrls.newOrder | 
					
						
							|  |  |  |       , headers: { 'Content-Type': 'application/jose+json' } | 
					
						
							|  |  |  |       , json: jws | 
					
						
							|  |  |  |       }).then(function (resp) { | 
					
						
							|  |  |  |         me._nonce = resp.toJSON().headers['replay-nonce']; | 
					
						
							|  |  |  |         var location = resp.toJSON().headers['location']; | 
					
						
							|  |  |  |         console.log(location); // the account id url
 | 
					
						
							|  |  |  |         console.log(resp.toJSON()); | 
					
						
							|  |  |  |         //var body = JSON.parse(resp.body);
 | 
					
						
							|  |  |  |         me._authorizations = resp.body.authorizations; | 
					
						
							|  |  |  |         me._order = location; | 
					
						
							|  |  |  |         me._finalize = resp.body.finalize; | 
					
						
							| 
									
										
										
										
											2018-03-20 01:24:36 -06:00
										 |  |  |         //console.log('[DEBUG] finalize:', me._finalize); return;
 | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |         //return resp.body;
 | 
					
						
							|  |  |  |         return Promise.all(me._authorizations.map(function (auth) { | 
					
						
							| 
									
										
										
										
											2018-03-20 01:24:36 -06:00
										 |  |  |           console.log('authz', auth); | 
					
						
							|  |  |  |           return me._getChallenges(options, auth).then(function (challenges) { | 
					
						
							|  |  |  |             var chp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             challenges.forEach(function (ch) { | 
					
						
							|  |  |  |               if ('http-01' !== ch.type) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               chp = me._postChallenge(options, ch); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return chp; | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         })).then(function () { | 
					
						
							|  |  |  |           var validatedDomains = body.identifiers.map(function (ident) { | 
					
						
							|  |  |  |             return ident.value; | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2018-03-20 01:24:36 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |           return me._finalizeOrder(options, validatedDomains); | 
					
						
							|  |  |  |         }).then(function () { | 
					
						
							|  |  |  |           return me._getCertificate(); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  |       }); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-15 00:41:00 -06:00
										 |  |  |   }; | 
					
						
							|  |  |  |   return acme2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  | var RSA = require('rsa-compat').RSA; | 
					
						
							| 
									
										
										
										
											2018-03-15 00:41:00 -06:00
										 |  |  | var acme2 = create(); | 
					
						
							|  |  |  | acme2.getAcmeUrls().then(function (body) { | 
					
						
							|  |  |  |   console.log(body); | 
					
						
							|  |  |  |   acme2.getNonce().then(function (nonce) { | 
					
						
							|  |  |  |     console.log(nonce); | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		var options = { | 
					
						
							|  |  |  | 			email: 'coolaj86@gmail.com' | 
					
						
							| 
									
										
										
										
											2018-03-20 01:24:36 -06:00
										 |  |  | 		, keypair: RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/account.privkey.pem') }) | 
					
						
							|  |  |  | 		, certificateKeypair: RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/privkey.pem') }) | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  | 		}; | 
					
						
							|  |  |  |     acme2.registerNewAccount(options).then(function (account) { | 
					
						
							| 
									
										
										
										
											2018-03-15 00:41:00 -06:00
										 |  |  |       console.log(account); | 
					
						
							| 
									
										
										
										
											2018-03-16 00:59:40 -06:00
										 |  |  |     	acme2.getCertificate(options, function () { | 
					
						
							|  |  |  | 				console.log('got cert'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-03-15 00:41:00 -06:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); |