advance to CSR
This commit is contained in:
		
							parent
							
								
									d646edf045
								
							
						
					
					
						commit
						6c0aed0491
					
				
							
								
								
									
										108
									
								
								js/app.js
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								js/app.js
									
									
									
									
									
								
							| @ -19,8 +19,9 @@ | ||||
|   } | ||||
| 
 | ||||
|   function submitForm(ev) { | ||||
|     steps[i].submit(ev); | ||||
|     var j = i; | ||||
|     i += 1; | ||||
|     steps[j].submit(ev); | ||||
|   } | ||||
|   $qsa('.js-acme-form').forEach(function ($el) { | ||||
|     $el.addEventListener('submit', function (ev) { | ||||
| @ -51,7 +52,12 @@ | ||||
|   }; | ||||
|   steps[1].submit = function () { | ||||
|     info.identifiers = $qs('.js-acme-domains').value.split(/\s*,\s*/g).map(function (hostname) { | ||||
|       return { type: 'dns', value: hostname.trim() }; | ||||
|       return { type: 'dns', value: hostname.toLowerCase().trim() }; | ||||
|     }); | ||||
|     info.identifiers.sort(function (a, b) { | ||||
|       if (a === b) { return 0; } | ||||
|       if (a < b) { return 1; } | ||||
|       if (a > b) { return -1; } | ||||
|     }); | ||||
| 
 | ||||
|     return BACME.directory($qs('.js-acme-directory-url').value).then(function (directory) { | ||||
| @ -59,6 +65,7 @@ | ||||
|       return BACME.nonce().then(function (_nonce) { | ||||
|         nonce = _nonce; | ||||
| 
 | ||||
|         console.log("MAGIC STEP NUMBER in 1 is:", i); | ||||
|         steps[i](); | ||||
|       }); | ||||
|     }); | ||||
| @ -147,6 +154,7 @@ | ||||
|             signedOrder: signedOrder | ||||
|           }).then(function (order) { | ||||
|             info.finalizeUrl = order.finalize; | ||||
|             info.orderUrl = order.url; // from header Location ???
 | ||||
|             return BACME.thumbprint({ jwk: jwk }).then(function (thumbprint) { | ||||
|               return BACME.challenges.all().then(function (claims) { | ||||
|                 console.log('claims:'); | ||||
| @ -176,7 +184,7 @@ | ||||
|                     , challengeDomain: hostname | ||||
|                     }); | ||||
|                     return BACME.challenges['dns-01']({ | ||||
|                       keyAuth: keyAuth | ||||
|                       keyAuth: keyAuth.value | ||||
|                     , challengeDomain: hostname | ||||
|                     }).then(function (dnsAuth) { | ||||
|                       var data = { | ||||
| @ -230,6 +238,7 @@ | ||||
| 
 | ||||
|                   updateChallengeType(); | ||||
| 
 | ||||
|                   console.log("MAGIC STEP NUMBER in 2 is:", i); | ||||
|                   steps[i](); | ||||
|                 }); | ||||
| 
 | ||||
| @ -249,23 +258,44 @@ | ||||
|     $qs('.js-acme-form-challenges').hidden = false; | ||||
|   }; | ||||
|   steps[3].submit = function () { | ||||
|     var chType = $qs('.js-acme-challenge-type').value; | ||||
|     var ps = []; | ||||
|     // for now just show the next page immediately (its a spinner)
 | ||||
|     console.log("MAGIC STEP NUMBER is:", i); | ||||
| 
 | ||||
|     var chType; | ||||
|     Array.prototype.some.call($qsa('.js-acme-challenge-type'), function ($el) { | ||||
|       if ($el.checked) { | ||||
|         chType = $el.value; | ||||
|         return true; | ||||
|       } | ||||
|     }); | ||||
|     console.log('chType is:', chType); | ||||
|     var chs = []; | ||||
| 
 | ||||
|     // do each wildcard, if any
 | ||||
|     // do each challenge, by selected type only
 | ||||
|     [ 'wildcard', chType].forEach(function (typ) { | ||||
|       info.challenges[typ].forEach(function (ch) { | ||||
|         // { jwk, challengeUrl, accountId (kid) }
 | ||||
|         ps.push(BACME.challenges.accept({ | ||||
|         chs.push({ | ||||
|           jwk: info.jwk | ||||
|         , challengeUrl: ch.url | ||||
|         , accountId: info.kid | ||||
|         })); | ||||
|         }); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     return Promise.all(ps).then(function (results) { | ||||
|     var results = []; | ||||
|     function nextChallenge() { | ||||
|       var ch = chs.pop(); | ||||
|       if (!ch) { return results; } | ||||
|       return BACME.challenges.accept(ch).then(function (result) { | ||||
|         results.push(result); | ||||
|         return nextChallenge(); | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     steps[i](); | ||||
|     return nextChallenge().then(function (results) { | ||||
|       console.log('challenge status:', results); | ||||
|       var polls = results.slice(0); | ||||
|       var allsWell = true; | ||||
| @ -276,7 +306,9 @@ | ||||
|         }).then(function () { | ||||
|           return Promise.all(polls.map(function (poll) { | ||||
|             return BACME.challenges.check({ challengePollUrl: poll.url }); | ||||
|           })).then(function () { | ||||
|           })).then(function (polls) { | ||||
|             console.log(polls); | ||||
| 
 | ||||
|             polls = polls.filter(function (poll) { | ||||
|               //return 'valid' !== poll.status && 'invalid' !== poll.status;
 | ||||
|               if ('pending' === poll.status) { | ||||
| @ -312,7 +344,63 @@ | ||||
|   } | ||||
|   steps[4].submit = function () { | ||||
|     console.log('Congrats! Auto advancing...'); | ||||
|     return BACME.order | ||||
|     var key = info.identifiers.map(function (ident) { return ident.value; }).join(','); | ||||
|     var serverJwk = JSON.parse(localStorage.getItem('server:' + key) || 'null'); | ||||
|     var p; | ||||
| 
 | ||||
|     function createKeypair() { | ||||
|       return BACME.accounts.generateKeypair({ | ||||
|         type: 'ECDSA' | ||||
|       , bitlength: '256' | ||||
|       }).then(function (serverJwk) { | ||||
|         localStorage.setItem('server:' + key, JSON.stringify(serverJwk)); | ||||
|         return serverJwk; | ||||
|       }) | ||||
|     } | ||||
| 
 | ||||
|     if (serverJwk) { | ||||
|       p = Promise.resolve(serverJwk); | ||||
|     } else { | ||||
|       p = createKeypair(); | ||||
|     } | ||||
| 
 | ||||
|     return p.then(function (_serverJwk) { | ||||
|       serverJwk = _serverJwk; | ||||
|       // { serverJwk, domains }
 | ||||
|       return BACME.orders.generateCsr({ | ||||
|         serverJwk: serverJwk | ||||
|       , domains: info.identifiers.map(function (ident) { | ||||
|           return ident.value; | ||||
|         }) | ||||
|       }).then(function (csrweb64) { | ||||
|         return BACME.order.finalize({ | ||||
|           csr: csrweb64 | ||||
|         , jwk: info.jwk | ||||
|         , finalizeUrl: info.finalizeUrl | ||||
|         , accountId: info.kid | ||||
|         }); | ||||
|       }).then(function () { | ||||
|         function checkCert() { | ||||
|           return new Promise(function (resolve) { | ||||
|             setTimeout(resolve, 1000); | ||||
|           }).then(function () { | ||||
|             return BACME.order.check({ orderUrl: info.orderUrl }); | ||||
|           }).then(function (reply) { | ||||
|             if ('processing' === reply) { | ||||
|               return checkCert(); | ||||
|             } | ||||
|             return reply; | ||||
|           }); | ||||
|         } | ||||
| 
 | ||||
|         return checkCert(); | ||||
|       }).then(function (reply) { | ||||
|         return BACME.order.receive({ certificateUrl: reply.certificate }); | ||||
|       }).then(function (certs) { | ||||
|         console.log('WINNING!'); | ||||
|         console.log(certs); | ||||
|       }); | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   steps[5] = function () { | ||||
|  | ||||
							
								
								
									
										68
									
								
								js/bacme.js
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								js/bacme.js
									
									
									
									
									
								
							| @ -102,6 +102,8 @@ BACME.accounts.generateKeypair = function (opts) { | ||||
| 			console.log('private jwk:'); | ||||
| 			console.log(JSON.stringify(privJwk, null, 2)); | ||||
| 
 | ||||
|       return privJwk; | ||||
|       /* | ||||
| 			return webCrypto.subtle.exportKey( | ||||
| 				"pkcs8" | ||||
| 			, result.privateKey | ||||
| @ -112,6 +114,7 @@ BACME.accounts.generateKeypair = function (opts) { | ||||
|         return privJwk; | ||||
|         //return accountKeypair;
 | ||||
| 			}); | ||||
|       */ | ||||
| 		}) | ||||
| 	}); | ||||
| }; | ||||
| @ -335,6 +338,7 @@ BACME.orders.create = function (opts) { | ||||
| 			finalizeUrl = result.finalize; | ||||
|       BACME._logBody(result); | ||||
| 
 | ||||
|       result.url = currentOrderUrl; | ||||
|       return result; | ||||
| 		}); | ||||
| 	}); | ||||
| @ -404,9 +408,9 @@ BACME.thumbprint = function (opts) { | ||||
|   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' ]; | ||||
|   } else if (/^RS/i.test(opts.jwk.kty)) { | ||||
|     keys = [ 'e', 'kty', 'n' ]; | ||||
|   } | ||||
| 
 | ||||
| 	var accountPublicStr = '{' + keys.map(function (key) { | ||||
| @ -416,12 +420,14 @@ BACME.thumbprint = function (opts) { | ||||
| 	return window.crypto.subtle.digest( | ||||
| 		{ name: "SHA-256" } // SHA-256 is spec'd, non-optional
 | ||||
| 	, textEncoder.encode(accountPublicStr) | ||||
| 	).then(function(hash){ | ||||
| 	).then(function (hash) { | ||||
| 		thumbprint = btoa(Array.prototype.map.call(new Uint8Array(hash), function (ch) { | ||||
| 			return String.fromCharCode(ch); | ||||
| 		}).join('')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); | ||||
| 
 | ||||
| 		console.log('Thumbprint:'); | ||||
| 		console.log(opts); | ||||
| 		console.log(accountPublicStr); | ||||
| 		console.log(thumbprint); | ||||
| 
 | ||||
|     return thumbprint; | ||||
| @ -446,10 +452,12 @@ BACME.challenges['http-01'] = function (opts) { | ||||
| 
 | ||||
| // { keyAuth }
 | ||||
| BACME.challenges['dns-01'] = function (opts) { | ||||
|   console.log('opts.keyAuth for DNS:'); | ||||
|   console.log(opts.keyAuth); | ||||
| 	return window.crypto.subtle.digest( | ||||
| 		{ name: "SHA-256", } | ||||
| 	, textEncoder.encode(opts.keyAuth) | ||||
| 	).then(function(hash){ | ||||
| 	).then(function (hash) { | ||||
| 		dnsAuth = btoa(Array.prototype.map.call(new Uint8Array(hash), function (ch) { | ||||
| 			return String.fromCharCode(ch); | ||||
| 		}).join('')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); | ||||
| @ -478,8 +486,7 @@ BACME.challenges.accept = function (opts) { | ||||
| 		{} | ||||
| 	); | ||||
| 
 | ||||
| 	nonce = null; | ||||
|   return BACME._import(opts.jwk).then(function (abstractKey) { | ||||
|   return BACME._importKey(opts.jwk).then(function (abstractKey) { | ||||
|     var protected64 = BACME._jsto64( | ||||
|       { nonce: nonce, alg: abstractKey.meta.alg/*'ES256'*/, url: opts.challengeUrl, kid: opts.accountId } | ||||
|     ); | ||||
| @ -490,6 +497,7 @@ BACME.challenges.accept = function (opts) { | ||||
|     }); | ||||
|   }).then(function (signedAccept) { | ||||
| 
 | ||||
| 	  nonce = null; | ||||
| 		return window.fetch( | ||||
| 			opts.challengeUrl | ||||
| 		, { mode: 'cors' | ||||
| @ -555,8 +563,11 @@ BACME.domains.generateKeypair = function () { | ||||
| 	}); | ||||
| }; | ||||
| 
 | ||||
| BACME.orders.generateCsr = function (keypair, domains) { | ||||
|   return Promise.resolve(CSR.generate(keypair, domains)); | ||||
| // { serverJwk, domains }
 | ||||
| BACME.orders.generateCsr = function (opts) { | ||||
|   return BACME._importKey(opts.serverJwk).then(function (abstractKey) { | ||||
|     return Promise.resolve(CSR.generate({ keypair: abstractKey.wcKey, domains: opts.domains })); | ||||
|   }); | ||||
| }; | ||||
| 
 | ||||
| var certificateUrl; | ||||
| @ -567,8 +578,7 @@ BACME.orders.finalize = function (opts) { | ||||
| 		{ csr: opts.csr } | ||||
| 	); | ||||
| 
 | ||||
| 	nonce = null; | ||||
|   return BACME._import(opts.jwk).then(function (abstractKey) { | ||||
|   return BACME._importKey(opts.jwk).then(function (abstractKey) { | ||||
|     var protected64 = BACME._jsto64( | ||||
|       { nonce: nonce, alg: abstractKey.meta.alg/*'ES256'*/, url: opts.finalizeUrl, kid: opts.accountId } | ||||
|     ); | ||||
| @ -579,8 +589,9 @@ BACME.orders.finalize = function (opts) { | ||||
|     }); | ||||
|   }).then(function (signedFinal) { | ||||
| 
 | ||||
| 	  nonce = null; | ||||
| 		return window.fetch( | ||||
| 			finalizeUrl | ||||
| 			opts.finalizeUrl | ||||
| 		, { mode: 'cors' | ||||
| 			, method: 'POST' | ||||
| 			, headers: { 'Content-Type': 'application/jose+json' } | ||||
| @ -600,4 +611,39 @@ BACME.orders.finalize = function (opts) { | ||||
| 	}); | ||||
| }; | ||||
| 
 | ||||
| BACME.orders.receive = function (opts) { | ||||
|   return window.fetch( | ||||
|     opts.certificateUrl | ||||
|   , { mode: 'cors' | ||||
|     , method: 'GET' | ||||
|     } | ||||
|   ).then(function (resp) { | ||||
|     BACME._logHeaders(resp); | ||||
|     nonce = resp.headers.get('replay-nonce'); | ||||
| 
 | ||||
|     return resp.json().then(function (reply) { | ||||
|       BACME._logBody(reply); | ||||
| 
 | ||||
|       return reply; | ||||
|     }); | ||||
|   }); | ||||
| }; | ||||
| 
 | ||||
| BACME.orders.check = function (opts) { | ||||
|   return window.fetch( | ||||
|     opts.orderUrl | ||||
|   , { mode: 'cors' | ||||
|     , method: 'GET' | ||||
|     } | ||||
|   ).then(function (resp) { | ||||
|     BACME._logHeaders(resp); | ||||
| 
 | ||||
|     return resp.json().then(function (reply) { | ||||
|       BACME._logBody(reply); | ||||
| 
 | ||||
|       return reply; | ||||
|     }); | ||||
|   }); | ||||
| }; | ||||
| 
 | ||||
| }(window)); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user