create acocunt and order, and view challenges
Šī revīzija ir iekļauta:
		
							vecāks
							
								
									5d4f71ba8e
								
							
						
					
					
						revīzija
						ec9a2606f6
					
				
							
								
								
									
										110
									
								
								js/app.js
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								js/app.js
									
									
									
									
									
								
							| @ -5,6 +5,8 @@ | ||||
|   var $qsa = function (s) { return window.document.querySelectorAll(s); }; | ||||
|   var info = {}; | ||||
|   var steps = {}; | ||||
|   var nonce; | ||||
|   var kid; | ||||
|   var i = 1; | ||||
| 
 | ||||
|   //$qs('.js-acme-directory-url').value = 'https://acme-v02.api.letsencrypt.org/directory';
 | ||||
| @ -16,10 +18,12 @@ | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   $qs('.js-acme-form-domains').addEventListener('submit', function (ev) { | ||||
|     ev.preventDefault(); | ||||
|     steps[i].submit(ev); | ||||
|     i += 1; | ||||
|   $qsa('.js-acme-form').forEach(function ($el) { | ||||
|     $el.addEventListener('submit', function (ev) { | ||||
|       ev.preventDefault(); | ||||
|       steps[i].submit(ev); | ||||
|       i += 1; | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   steps[1] = function () { | ||||
| @ -33,7 +37,11 @@ | ||||
| 
 | ||||
|     return BACME.directory($qs('.js-acme-directory-url').value).then(function (directory) { | ||||
|       $qs('.js-acme-tos-url').href = directory.meta.termsOfService; | ||||
|       steps[i](); | ||||
|       return BACME.nonce().then(function (_nonce) { | ||||
|         nonce = _nonce; | ||||
| 
 | ||||
|         steps[i](); | ||||
|       }); | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
| @ -42,16 +50,94 @@ | ||||
|     $qs('.js-acme-form-account').hidden = false; | ||||
|   }; | ||||
|   steps[2].submit = function () { | ||||
|     info.contact = [ 'mailto:' + $qs('.js-acme-account-email').value ]; | ||||
|     var email = $qs('.js-acme-account-email').value.toLowerCase().trim(); | ||||
| 
 | ||||
|     info.contact = [ 'mailto:' + email ]; | ||||
|     info.agree = $qs('.js-acme-account-tos').checked; | ||||
|     info.greenlockAgree = $qs('.js-gl-tos').checked; | ||||
|     // TODO
 | ||||
|     // create account key
 | ||||
|     // create account
 | ||||
|     // capture email
 | ||||
|     // submit challenges
 | ||||
|     // populate challenges in table
 | ||||
|     steps[i](); | ||||
|     // options for
 | ||||
|     // * regenerate key
 | ||||
|     // * ECDSA / RSA / bitlength
 | ||||
| 
 | ||||
|     // TODO ping with version and account creation
 | ||||
| 
 | ||||
|     var jwk = JSON.parse(localStorage.getItem('account:' + email) || 'null'); | ||||
|     var p; | ||||
| 
 | ||||
|     function createKeypair() { | ||||
|       return BACME.accounts.generateKeypair({ | ||||
|         type: 'ECDSA' | ||||
|       , bitlength: '256' | ||||
|       }).then(function (jwk) { | ||||
|         localStorage.setItem('account:' + email, JSON.stringify(jwk)); | ||||
|         return jwk; | ||||
|       }) | ||||
|     } | ||||
| 
 | ||||
|     if (jwk) { | ||||
|       p = Promise.resolve(jwk); | ||||
|     } else { | ||||
|       p = createKeypair(); | ||||
|     } | ||||
| 
 | ||||
|     function createAccount(jwk) { | ||||
|       console.log('account jwk:'); | ||||
|       console.log(jwk); | ||||
|       delete jwk.key_ops; | ||||
|       return BACME.accounts.sign({ | ||||
|         jwk: jwk | ||||
|       , contacts: [ 'mailto:' + email ] | ||||
|       , agree: info.agree | ||||
|       , nonce: nonce | ||||
|       , kid: kid | ||||
|       }).then(function (signedAccount) { | ||||
|         return BACME.accounts.set({ | ||||
|           signedAccount: signedAccount | ||||
|         }).then(function (account) { | ||||
|           console.log('account:'); | ||||
|           console.log(account); | ||||
|           kid = account.kid; | ||||
|           return kid; | ||||
|         }); | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     return p.then(function (_jwk) { | ||||
|       jwk = _jwk; | ||||
|       kid = JSON.parse(localStorage.getItem('account-kid:' + email) || 'null'); | ||||
|       var p2 | ||||
| 
 | ||||
|       // TODO save account id rather than always retrieving it
 | ||||
|       if (kid) { | ||||
|         p2 = Promise.resolve(kid); | ||||
|       } else { | ||||
|         p2 = createAccount(jwk); | ||||
|       } | ||||
| 
 | ||||
|       return p2.then(function (_kid) { | ||||
|         kid = _kid; | ||||
|         return BACME.orders.sign({ | ||||
|           jwk: jwk | ||||
|         , identifiers: info.identifiers | ||||
|         , kid: kid | ||||
|         }).then(function (signedOrder) { | ||||
|           return BACME.orders.create({ | ||||
|             signedOrder: signedOrder | ||||
|           }).then(function (/*challengeIndexes*/) { | ||||
|             return BACME.challenges.all().then(function (challenges) { | ||||
|               console.log('challenges:'); | ||||
|               console.log(challenges); | ||||
|               // TODO populate challenges in table
 | ||||
|               steps[i](); | ||||
|             }); | ||||
|           }); | ||||
|         }); | ||||
|       }); | ||||
|     }).catch(function (err) { | ||||
|       console.error('Step \'' + i + '\' Error:'); | ||||
|       console.error(err); | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   steps[3] = function () { | ||||
|  | ||||
							
								
								
									
										306
									
								
								js/bacme.js
									
									
									
									
									
								
							
							
						
						
									
										306
									
								
								js/bacme.js
									
									
									
									
									
								
							| @ -58,11 +58,36 @@ BACME.nonce = function () { | ||||
| }; | ||||
| 
 | ||||
| BACME.accounts = {}; | ||||
| BACME.accounts.generateKeypair = function () { | ||||
| 
 | ||||
| // type = ECDSA
 | ||||
| // bitlength = 256
 | ||||
| BACME.accounts.generateKeypair = function (opts) { | ||||
|   var wcOpts = {}; | ||||
| 
 | ||||
|   // ECDSA has only the P curves and an associated bitlength
 | ||||
|   if (/^EC/i.test(opts.type)) { | ||||
|     wcOpts.name = 'ECDSA'; | ||||
|     if (/256/.test(opts.bitlength)) { | ||||
|       wcOpts.namedCurve = 'P-256'; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // RSA-PSS is another option, but I don't think it's used for Let's Encrypt
 | ||||
|   // I think the hash is only necessary for signing, not generation or import
 | ||||
|   if (/^RS/i.test(opts.type)) { | ||||
|     wcOpts.name = 'RSASSA-PKCS1-v1_5'; | ||||
|     wcOpts.modulusLength = opts.bitlength; | ||||
|     if (opts.bitlength < 2048) { | ||||
|       wcOpts.modulusLength = opts.bitlength * 8; | ||||
|     } | ||||
|     wcOpts.publicExponent = new Uint8Array([0x01, 0x00, 0x01]); | ||||
|     wcOpts.hash = { name: "SHA-256" }; | ||||
|   } | ||||
| 
 | ||||
| 	// https://github.com/diafygi/webcrypto-examples#ecdsa---generatekey
 | ||||
| 	var extractable = true; | ||||
| 	return webCrypto.subtle.generateKey( | ||||
| 		{ name: "ECDSA", namedCurve: "P-256" } | ||||
| 		wcOpts | ||||
| 	, extractable | ||||
| 	, [ 'sign', 'verify' ] | ||||
| 	).then(function (result) { | ||||
| @ -71,11 +96,11 @@ BACME.accounts.generateKeypair = function () { | ||||
| 		return webCrypto.subtle.exportKey( | ||||
| 			"jwk" | ||||
| 		, result.privateKey | ||||
| 		).then(function (jwk) { | ||||
| 		).then(function (privJwk) { | ||||
| 
 | ||||
| 			accountJwk = jwk; | ||||
| 			accountJwk = privJwk; | ||||
| 			console.log('private jwk:'); | ||||
| 			console.log(JSON.stringify(jwk, null, 2)); | ||||
| 			console.log(JSON.stringify(privJwk, null, 2)); | ||||
| 
 | ||||
| 			return webCrypto.subtle.exportKey( | ||||
| 				"pkcs8" | ||||
| @ -84,7 +109,8 @@ BACME.accounts.generateKeypair = function () { | ||||
| 				console.log('pkcs8:'); | ||||
| 				console.log(Array.from(new Uint8Array(keydata))); | ||||
| 
 | ||||
|         return accountKeypair; | ||||
|         return privJwk; | ||||
|         //return accountKeypair;
 | ||||
| 			}); | ||||
| 		}) | ||||
| 	}); | ||||
| @ -97,63 +123,137 @@ BACME._jsto64 = function (json) { | ||||
| 
 | ||||
| var textEncoder = new TextEncoder(); | ||||
| 
 | ||||
| BACME._importKey = function (jwk) { | ||||
|   var alg; // I think the 256 refers to the hash
 | ||||
|   var wcOpts = {}; | ||||
|   var extractable = false; | ||||
| 
 | ||||
|   // ECDSA
 | ||||
|   if (/^EC/i.test(jwk.kty)) { | ||||
|     wcOpts.name = 'ECDSA'; | ||||
|     wcOpts.namedCurve = jwk.crv; | ||||
|     alg = 'ES256'; | ||||
|   } | ||||
| 
 | ||||
|   // RSA
 | ||||
|   if (/^RS/i.test(jwk.kty)) { | ||||
|     wcOpts.name = 'RSASSA-PKCS1-v1_5'; | ||||
|     wcOpts.hash = { name: "SHA-256" }; | ||||
|     alg = 'RS256'; | ||||
|   } | ||||
| 
 | ||||
|   return window.crypto.subtle.importKey( | ||||
|     "jwk" | ||||
|   , jwk | ||||
| 	, wcOpts | ||||
|   , extractable | ||||
|   , [ "sign"/*, "verify"*/ ] | ||||
|   ).then(function (keypair) { | ||||
|     return { | ||||
|       wcKey: keypair | ||||
|     , meta: { | ||||
|         alg: alg | ||||
|       , name: wcOpts.name | ||||
|       , hash: wcOpts.hash | ||||
|       } | ||||
|     , jwk: jwk | ||||
|     }; | ||||
|   }); | ||||
| }; | ||||
| BACME._sign = function (opts) { | ||||
|   var wcPrivKey = opts.abstractKey.wcKey; | ||||
|   var wcOpts = opts.abstractKey.meta; | ||||
|   var alg = opts.abstractKey.meta.alg; // I think the 256 refers to the hash
 | ||||
|   var signHash; | ||||
| 
 | ||||
|   console.log('kty', opts.abstractKey.jwk.kty); | ||||
|   signHash = { name: "SHA-" + alg.replace(/[a-z]+/ig, '') }; | ||||
| 
 | ||||
|   var msg = textEncoder.encode(opts.protected64 + '.' + opts.payload64); | ||||
|   console.log('msg:', msg); | ||||
|   return window.crypto.subtle.sign( | ||||
|     { name: wcOpts.name, hash: signHash } | ||||
|   , wcPrivKey | ||||
|   , msg | ||||
|   ).then(function (signature) { | ||||
|     //console.log('sig1:', signature);
 | ||||
|     //console.log('sig2:', new Uint8Array(signature));
 | ||||
|     //console.log('sig3:', Array.prototype.slice.call(new Uint8Array(signature)));
 | ||||
|     // convert buffer to urlsafe base64
 | ||||
|     var sig64 = btoa(Array.prototype.map.call(new Uint8Array(signature), function (ch) { | ||||
|       return String.fromCharCode(ch); | ||||
|     }).join('')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); | ||||
| 
 | ||||
|     console.log('[1] URL-safe Base64 Signature:'); | ||||
|     console.log(sig64); | ||||
| 
 | ||||
|     var signedMsg = { | ||||
|       protected: opts.protected64 | ||||
|     , payload: opts.payload64 | ||||
|     , signature: sig64 | ||||
|     }; | ||||
| 
 | ||||
|     console.log('Signed Base64 Msg:'); | ||||
|     console.log(JSON.stringify(signedMsg, null, 2)); | ||||
| 
 | ||||
|     return signedMsg; | ||||
|   }); | ||||
| }; | ||||
| // email = john.doe@gmail.com
 | ||||
| BACME.accounts.sign = function (email) { | ||||
| 	var payload64 = BACME._jsto64( | ||||
| 		{ termsOfServiceAgreed: true | ||||
| 		, onlyReturnExisting: false | ||||
| 		, contact: [ 'mailto:' + email ] | ||||
| 		} | ||||
| 	); | ||||
| // jwk = { ... }
 | ||||
| // agree = true
 | ||||
| BACME.accounts.sign = function (opts) { | ||||
| 
 | ||||
| 	var protected64 = BACME._jsto64( | ||||
| 		{ nonce: nonce | ||||
| 		, url: accountUrl | ||||
| 		, alg: 'ES256' | ||||
| 		, jwk: { | ||||
| 				kty: accountJwk.kty | ||||
| 			, crv: accountJwk.crv | ||||
| 			, x: accountJwk.x | ||||
| 			, y: accountJwk.y | ||||
| 			} | ||||
| 		} | ||||
| 	); | ||||
|   return BACME._importKey(opts.jwk).then(function (abstractKey) { | ||||
| 
 | ||||
| 	// Note: this function hashes before signing so send data, not the hash
 | ||||
| 	return window.crypto.subtle.sign( | ||||
| 		{ name: "ECDSA", hash: { name: "SHA-256" } } | ||||
| 	, accountKeypair.privateKey | ||||
| 	, textEncoder.encode(protected64 + '.' + payload64) | ||||
| 	).then(function (signature) { | ||||
|     var payloadJson = | ||||
|       { termsOfServiceAgreed: opts.agree | ||||
|       , onlyReturnExisting: false | ||||
|       , contact: opts.contacts || [ 'mailto:' + opts.email ] | ||||
|       }; | ||||
|     console.log('payload:'); | ||||
|     console.log(payloadJson); | ||||
|     var payload64 = BACME._jsto64( | ||||
|       payloadJson | ||||
|     ); | ||||
| 
 | ||||
| 		// convert buffer to urlsafe base64
 | ||||
| 		var sig64 = btoa(Array.prototype.map.call(new Uint8Array(signature), function (ch) { | ||||
| 			return String.fromCharCode(ch); | ||||
| 		}).join('')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); | ||||
|     // TODO RSA
 | ||||
|     var protectedJson = | ||||
|       { nonce: opts.nonce | ||||
|       , url: accountUrl | ||||
|       , alg: abstractKey.meta.alg | ||||
|       , jwk: { | ||||
|           kty: opts.jwk.kty | ||||
|         , crv: opts.jwk.crv | ||||
|         , x: opts.jwk.x | ||||
|         , y: opts.jwk.y | ||||
|         } | ||||
|       }; | ||||
|     console.log('protected:'); | ||||
|     console.log(protectedJson); | ||||
|     var protected64 = BACME._jsto64( | ||||
|       protectedJson | ||||
|     ); | ||||
| 
 | ||||
| 		console.log('URL-safe Base64 Signature:'); | ||||
| 		console.log(sig64); | ||||
| 
 | ||||
| 		signedAccount = { | ||||
| 			protected: protected64 | ||||
| 		, payload: payload64 | ||||
| 		, signature: sig64 | ||||
| 		}; | ||||
| 		console.log('Signed Base64 Account:'); | ||||
| 		console.log(JSON.stringify(signedAccount, null, 2)); | ||||
| 	}); | ||||
| 		// Note: this function hashes before signing so send data, not the hash
 | ||||
| 		return BACME._sign({ | ||||
|       abstractKey: abstractKey | ||||
|     , payload64: payload64 | ||||
|     , protected64: protected64 | ||||
|     }); | ||||
|   }); | ||||
| }; | ||||
| 
 | ||||
| var account; | ||||
| var accountId; | ||||
| 
 | ||||
| BACME.accounts.set = function () { | ||||
| BACME.accounts.set = function (opts) { | ||||
| 	nonce = null; | ||||
| 	return window.fetch(accountUrl, { | ||||
| 		mode: 'cors' | ||||
| 	, method: 'POST' | ||||
| 	, headers: { 'Content-Type': 'application/jose+json' } | ||||
| 	, body: JSON.stringify(signedAccount) | ||||
| 	, body: JSON.stringify(opts.signedAccount) | ||||
| 	}).then(function (resp) { | ||||
| 		BACME._logHeaders(resp); | ||||
| 		nonce = resp.headers.get('replay-nonce'); | ||||
| @ -163,11 +263,18 @@ BACME.accounts.set = function () { | ||||
| 
 | ||||
| 		if (!resp.headers.get('content-type')) { | ||||
| 		 console.log('Body: <none>'); | ||||
| 		 return; | ||||
| 
 | ||||
| 		 return { kid: accountId }; | ||||
| 		} | ||||
| 
 | ||||
| 		return resp.json().then(function (result) { | ||||
|       if (/^Error/i.test(result.detail)) { | ||||
|         return Promise.reject(new Error(result.detail)); | ||||
|       } | ||||
|       result.kid = accountId; | ||||
|       BACME._logBody(result); | ||||
| 
 | ||||
|       return result; | ||||
| 		}); | ||||
| 	}); | ||||
| }; | ||||
| @ -178,37 +285,29 @@ var signedOrder; | ||||
| BACME.orders = {}; | ||||
| 
 | ||||
| // identifiers = [ { type: 'dns', value: 'example.com' }, { type: 'dns', value: '*.example.com' } ]
 | ||||
| BACME.orders.sign = function (identifiers) { | ||||
| 	var payload64 = jsto64({ identifiers: identifiers }); | ||||
| // signedAccount
 | ||||
| BACME.orders.sign = function (opts) { | ||||
| 	var payload64 = BACME._jsto64({ identifiers: opts.identifiers }); | ||||
| 
 | ||||
| 	var protected64 = jsto64( | ||||
| 		{ nonce: nonce, alg: 'ES256', url: orderUrl, kid: accountId } | ||||
| 	var protected64 = BACME._jsto64( | ||||
| 		{ nonce: nonce, alg: 'ES256', url: orderUrl, kid: opts.kid } | ||||
| 	); | ||||
| 
 | ||||
| 	return window.crypto.subtle.sign( | ||||
| 		{ name: "ECDSA", hash: { name: "SHA-256" } } | ||||
| 	, accountKeypair.privateKey | ||||
| 	, textEncoder.encode(protected64 + '.' + payload64) | ||||
| 	).then(function (signature) { | ||||
| 
 | ||||
| 		// convert buffer to urlsafe base64
 | ||||
| 		var sig64 = btoa(Array.prototype.map.call(new Uint8Array(signature), function (ch) { | ||||
| 			return String.fromCharCode(ch); | ||||
| 		}).join('')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); | ||||
| 
 | ||||
| 		console.log('URL-safe Base64 Signature:'); | ||||
| 		console.log(sig64); | ||||
| 
 | ||||
| 		signedOrder = { | ||||
| 			protected: protected64 | ||||
| 		, payload: payload64 | ||||
| 		, signature: sig64 | ||||
| 		}; | ||||
| 		console.log('Signed Base64 Order:'); | ||||
| 		console.log(JSON.stringify(signedAccount, null, 2)); | ||||
| 
 | ||||
|     return signedOrder; | ||||
| 	}); | ||||
| 	return BACME._importKey(opts.jwk).then(function (abstractKey) { | ||||
|     console.log('abstractKey:'); | ||||
|     console.log(abstractKey); | ||||
|     return BACME._sign({ | ||||
|       abstractKey: abstractKey | ||||
|     , payload64: payload64 | ||||
|     , protected64: protected64 | ||||
|     }).then(function (sig) { | ||||
|       if (!sig) { | ||||
|         throw new Error('sig is undefined... nonsense!'); | ||||
|       } | ||||
|       console.log('newsig', sig); | ||||
|       return sig; | ||||
|     }); | ||||
|   }); | ||||
| }; | ||||
| 
 | ||||
| var order; | ||||
| @ -216,25 +315,26 @@ var currentOrderUrl; | ||||
| var authorizationUrls; | ||||
| var finalizeUrl; | ||||
| 
 | ||||
| BACME.orders.create = function () { | ||||
| BACME.orders.create = function (opts) { | ||||
| 	nonce = null; | ||||
| 	return window.fetch(orderUrl, { | ||||
| 		mode: 'cors' | ||||
| 	, method: 'POST' | ||||
| 	, headers: { 'Content-Type': 'application/jose+json' } | ||||
| 	, body: JSON.stringify(signedOrder) | ||||
| 	, body: JSON.stringify(opts.signedOrder) | ||||
| 	}).then(function (resp) { | ||||
| 		console.log('Headers:'); | ||||
| 		Array.from(resp.headers.entries()).forEach(function (h) { console.log(h[0] + ': ' + h[1]); }); | ||||
|     BACME._logHeaders(resp); | ||||
| 		currentOrderUrl = resp.headers.get('location'); | ||||
| 		nonce = resp.headers.get('replay-nonce'); | ||||
| 		console.log('Next nonce:', nonce); | ||||
| 
 | ||||
| 		return resp.json().then(function (result) { | ||||
|       if (/^Error/i.test(result.detail)) { | ||||
|         return Promise.reject(new Error(result.detail)); | ||||
|       } | ||||
| 			authorizationUrls = result.authorizations; | ||||
| 			finalizeUrl = result.finalize; | ||||
| 			console.log('Body:'); | ||||
| 			console.log(JSON.stringify(result, null, 2)); | ||||
|       BACME._logBody(result); | ||||
| 
 | ||||
|       return result; | ||||
| 		}); | ||||
| @ -242,6 +342,22 @@ BACME.orders.create = function () { | ||||
| }; | ||||
| 
 | ||||
| BACME.challenges = {}; | ||||
| BACME.challenges.all = function () { | ||||
|   var challenges = []; | ||||
| 
 | ||||
|   function next() { | ||||
|     if (!authorizationUrls.length) { | ||||
|       return challenges; | ||||
|     } | ||||
| 
 | ||||
|     return BACME.challenges.view().then(function (challenge) { | ||||
|       challenges.push(challenge); | ||||
|       return next(); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   return next(); | ||||
| }; | ||||
| BACME.challenges.view = function () { | ||||
| 	var authzUrl = authorizationUrls.pop(); | ||||
| 	var token; | ||||
| @ -273,10 +389,19 @@ var httpPath; | ||||
| var dnsAuth; | ||||
| var dnsRecord; | ||||
| 
 | ||||
| BACME.thumbprint = function () { | ||||
| BACME.thumbprint = function (opts) { | ||||
| 	// https://stackoverflow.com/questions/42588786/how-to-fingerprint-a-jwk
 | ||||
| 
 | ||||
| 	var accountPublicStr = '{' + ['crv', 'kty', 'x', 'y'].map(function (key) { | ||||
|   var accountJwk = opts.jwk; | ||||
|   var keys; | ||||
| 
 | ||||
|   if (/^EC/i.test(opts.jwk.kty)) { | ||||
|     keys = [ 'e', 'kty', 'n' ]; | ||||
|   } else if (/^RS/i.test(opts.jwk.kty)) { | ||||
|     keys = [ 'crv', 'kty', 'x', 'y' ]; | ||||
|   } | ||||
| 
 | ||||
| 	var accountPublicStr = '{' + keys.map(function (key) { | ||||
| 		return '"' + key + '":"' + accountJwk[key] + '"'; | ||||
| 	}).join(',') + '}'; | ||||
| 
 | ||||
| @ -338,11 +463,11 @@ BACME.challenges['dns-01'] = function () { | ||||
| var challengePollUrl; | ||||
| 
 | ||||
| BACME.challenges.accept = function () { | ||||
|   var payload64 = jsto64( | ||||
|   var payload64 = BACME._jsto64( | ||||
| 		{} | ||||
| 	); | ||||
| 
 | ||||
| 	var protected64 = jsto64( | ||||
| 	var protected64 = BACME._jsto64( | ||||
| 		{ nonce: nonce, alg: 'ES256', url: challengeUrl, kid: accountId } | ||||
| 	); | ||||
| 
 | ||||
| @ -371,8 +496,7 @@ BACME.challenges.accept = function () { | ||||
| 			, body: JSON.stringify(body) | ||||
| 			} | ||||
| 		).then(function (resp) { | ||||
| 			console.log('Headers:'); | ||||
| 			Array.from(resp.headers.entries()).forEach(function (h) { console.log(h[0] + ': ' + h[1]); }); | ||||
|       BACME._logHeaders(resp); | ||||
| 			nonce = resp.headers.get('replay-nonce'); | ||||
| 
 | ||||
| 			return resp.json().then(function (reply) { | ||||
| @ -435,11 +559,11 @@ BACME.orders.generateCsr = function (keypair, domains) { | ||||
| var certificateUrl; | ||||
| 
 | ||||
| BACME.orders.finalize = function () { | ||||
| 	var payload64 = jsto64( | ||||
| 	var payload64 = BACME._jsto64( | ||||
| 		{ csr: csr } | ||||
| 	); | ||||
| 
 | ||||
| 	var protected64 = jsto64( | ||||
| 	var protected64 = BACME._jsto64( | ||||
| 		{ nonce: nonce, alg: 'ES256', url: finalizeUrl, kid: accountId } | ||||
| 	); | ||||
| 
 | ||||
|  | ||||
		Notiek ielāde…
	
	
			
			x
			
			
		
	
		Atsaukties uz šo jaunā problēmā
	
	Block a user