appears to work
This commit is contained in:
		
							parent
							
								
									6c0aed0491
								
							
						
					
					
						commit
						510a367135
					
				
							
								
								
									
										13
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								index.html
									
									
									
									
									
								
							| @ -120,19 +120,22 @@ | |||||||
|       <button type="submit">Next</button> |       <button type="submit">Next</button> | ||||||
|     </form> |     </form> | ||||||
| 
 | 
 | ||||||
|     <!-- Step 4 Process Challanges --> |     <!-- Step 5 Get Certs --> | ||||||
|     <form class="js-acme-form js-acme-form-download"> |     <form class="js-acme-form js-acme-form-download"> | ||||||
|       <label>privkey.pem</label> |       <label>privkey.pem</label> | ||||||
|       <textarea>-</textarea> |       <textarea class="js-privkey">-</textarea> | ||||||
| 
 | 
 | ||||||
|       <label>fullchain.pem</label> |       <label>fullchain.pem</label> | ||||||
|       <textarea>-</textarea> |       <textarea class="js-fullchain">-</textarea> | ||||||
| 
 | 
 | ||||||
|  |       <!-- | ||||||
|  |         TODO | ||||||
|       <label>cert.pem</label> |       <label>cert.pem</label> | ||||||
|       <textarea>-</textarea> |       <textarea class="js-cert">-</textarea> | ||||||
| 
 | 
 | ||||||
|       <label>chain.pem</label> |       <label>chain.pem</label> | ||||||
|       <textarea>-</textarea> |       <textarea class="js-chain">-</textarea> | ||||||
|  |       --> | ||||||
| 
 | 
 | ||||||
|       <button type="button">Download SSL Certificates</button> |       <button type="button">Download SSL Certificates</button> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -10,5 +10,5 @@ popd | |||||||
| 
 | 
 | ||||||
| mkdir -p js/browser-csr/v1.0.0-alpha/ | mkdir -p js/browser-csr/v1.0.0-alpha/ | ||||||
| pushd js/browser-csr/v1.0.0-alpha/ | pushd js/browser-csr/v1.0.0-alpha/ | ||||||
|   wget -c https://git.coolaj86.com/coolaj86/browser-csr.js/raw/commit/c513a862a4e016794da800f0c2eec858b80837ab/csr.js |   wget -c https://git.coolaj86.com/coolaj86/browser-csr.js/raw/commit/01cdc0e91b5bf03f12e1b25b4129e3cde927987c/csr.js | ||||||
| popd | popd | ||||||
|  | |||||||
							
								
								
									
										81
									
								
								js/app.js
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								js/app.js
									
									
									
									
									
								
							| @ -30,7 +30,9 @@ | |||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|   function updateChallengeType() { |   function updateChallengeType() { | ||||||
|     var input = this || $qs('.js-acme-challenge-type'); |     var input = this || Array.prototype.filter.call( | ||||||
|  |       $qsa('.js-acme-challenge-type'), function ($el) { return $el.checked; } | ||||||
|  |     )[0]; | ||||||
|     console.log('ch type radio:', input.value); |     console.log('ch type radio:', input.value); | ||||||
|     $qs('.js-acme-table-wildcard').hidden = true; |     $qs('.js-acme-table-wildcard').hidden = true; | ||||||
|     $qs('.js-acme-table-http-01').hidden = true; |     $qs('.js-acme-table-http-01').hidden = true; | ||||||
| @ -200,7 +202,6 @@ | |||||||
|                       , dnsAnswer: dnsAuth.answer |                       , dnsAnswer: dnsAuth.answer | ||||||
|                       }; |                       }; | ||||||
| 
 | 
 | ||||||
|                       obj[c.type].push(data); |  | ||||||
|                       console.log(''); |                       console.log(''); | ||||||
|                       console.log('CHALLENGE'); |                       console.log('CHALLENGE'); | ||||||
|                       console.log(claim); |                       console.log(claim); | ||||||
| @ -258,9 +259,6 @@ | |||||||
|     $qs('.js-acme-form-challenges').hidden = false; |     $qs('.js-acme-form-challenges').hidden = false; | ||||||
|   }; |   }; | ||||||
|   steps[3].submit = function () { |   steps[3].submit = function () { | ||||||
|     // for now just show the next page immediately (its a spinner)
 |  | ||||||
|     console.log("MAGIC STEP NUMBER is:", i); |  | ||||||
| 
 |  | ||||||
|     var chType; |     var chType; | ||||||
|     Array.prototype.some.call($qsa('.js-acme-challenge-type'), function ($el) { |     Array.prototype.some.call($qsa('.js-acme-challenge-type'), function ($el) { | ||||||
|       if ($el.checked) { |       if ($el.checked) { | ||||||
| @ -283,6 +281,7 @@ | |||||||
|         }); |         }); | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|  |     console.log("INFO.challenges !!!!!", info.challenges); | ||||||
| 
 | 
 | ||||||
|     var results = []; |     var results = []; | ||||||
|     function nextChallenge() { |     function nextChallenge() { | ||||||
| @ -294,6 +293,7 @@ | |||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // for now just show the next page immediately (its a spinner)
 | ||||||
|     steps[i](); |     steps[i](); | ||||||
|     return nextChallenge().then(function (results) { |     return nextChallenge().then(function (results) { | ||||||
|       console.log('challenge status:', results); |       console.log('challenge status:', results); | ||||||
| @ -366,6 +366,7 @@ | |||||||
| 
 | 
 | ||||||
|     return p.then(function (_serverJwk) { |     return p.then(function (_serverJwk) { | ||||||
|       serverJwk = _serverJwk; |       serverJwk = _serverJwk; | ||||||
|  |       info.serverJwk = serverJwk; | ||||||
|       // { serverJwk, domains }
 |       // { serverJwk, domains }
 | ||||||
|       return BACME.orders.generateCsr({ |       return BACME.orders.generateCsr({ | ||||||
|         serverJwk: serverJwk |         serverJwk: serverJwk | ||||||
| @ -373,7 +374,7 @@ | |||||||
|           return ident.value; |           return ident.value; | ||||||
|         }) |         }) | ||||||
|       }).then(function (csrweb64) { |       }).then(function (csrweb64) { | ||||||
|         return BACME.order.finalize({ |         return BACME.orders.finalize({ | ||||||
|           csr: csrweb64 |           csr: csrweb64 | ||||||
|         , jwk: info.jwk |         , jwk: info.jwk | ||||||
|         , finalizeUrl: info.finalizeUrl |         , finalizeUrl: info.finalizeUrl | ||||||
| @ -384,7 +385,7 @@ | |||||||
|           return new Promise(function (resolve) { |           return new Promise(function (resolve) { | ||||||
|             setTimeout(resolve, 1000); |             setTimeout(resolve, 1000); | ||||||
|           }).then(function () { |           }).then(function () { | ||||||
|             return BACME.order.check({ orderUrl: info.orderUrl }); |             return BACME.orders.check({ orderUrl: info.orderUrl }); | ||||||
|           }).then(function (reply) { |           }).then(function (reply) { | ||||||
|             if ('processing' === reply) { |             if ('processing' === reply) { | ||||||
|               return checkCert(); |               return checkCert(); | ||||||
| @ -395,10 +396,74 @@ | |||||||
| 
 | 
 | ||||||
|         return checkCert(); |         return checkCert(); | ||||||
|       }).then(function (reply) { |       }).then(function (reply) { | ||||||
|         return BACME.order.receive({ certificateUrl: reply.certificate }); |         return BACME.orders.receive({ certificateUrl: reply.certificate }); | ||||||
|       }).then(function (certs) { |       }).then(function (certs) { | ||||||
|         console.log('WINNING!'); |         console.log('WINNING!'); | ||||||
|         console.log(certs); |         console.log(certs); | ||||||
|  |         $qs('.js-fullchain').value = certs; | ||||||
|  | 
 | ||||||
|  |         // https://stackoverflow.com/questions/40314257/export-webcrypto-key-to-pem-format
 | ||||||
|  | 				function spkiToPEM(keydata){ | ||||||
|  | 						var keydataS = arrayBufferToString(keydata); | ||||||
|  | 						var keydataB64 = window.btoa(keydataS); | ||||||
|  | 						var keydataB64Pem = formatAsPem(keydataB64); | ||||||
|  | 						return keydataB64Pem; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				function arrayBufferToString( buffer ) { | ||||||
|  | 						var binary = ''; | ||||||
|  | 						var bytes = new Uint8Array( buffer ); | ||||||
|  | 						var len = bytes.byteLength; | ||||||
|  | 						for (var i = 0; i < len; i++) { | ||||||
|  | 								binary += String.fromCharCode( bytes[ i ] ); | ||||||
|  | 						} | ||||||
|  | 						return binary; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 				function formatAsPem(str) { | ||||||
|  | 						var finalString = '-----BEGIN ' + pemName + ' PRIVATE KEY-----\n'; | ||||||
|  | 
 | ||||||
|  | 						while(str.length > 0) { | ||||||
|  | 								finalString += str.substring(0, 64) + '\n'; | ||||||
|  | 								str = str.substring(64); | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						finalString = finalString + '-----END ' + pemName + ' PRIVATE KEY-----'; | ||||||
|  | 
 | ||||||
|  | 						return finalString; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  |         var wcOpts; | ||||||
|  |         var pemName; | ||||||
|  |         if (/^R/.test(info.serverJwk.kty)) { | ||||||
|  |           pemName = 'RSA'; | ||||||
|  |           wcOpts = { | ||||||
|  |             name: "RSASSA-PKCS1-v1_5" | ||||||
|  |           , hash: { name: "SHA-256" } | ||||||
|  |           }; | ||||||
|  |         } else { | ||||||
|  |           pemName = 'EC'; | ||||||
|  |           wcOpts = { | ||||||
|  |             name: "ECDSA" | ||||||
|  |           , namedCurve: "P-256" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 				return crypto.subtle.importKey( | ||||||
|  |           "jwk" | ||||||
|  |         , info.serverJwk | ||||||
|  |         , wcOpts | ||||||
|  |         , true | ||||||
|  |         , ["sign"] | ||||||
|  | 				).then(function (privateKey) { | ||||||
|  | 				  return window.crypto.subtle.exportKey("pkcs8", privateKey); | ||||||
|  | 				}).then (function (keydata) { | ||||||
|  | 					var pem = spkiToPEM(keydata); | ||||||
|  | 					$qs('.js-privkey').value = pem; | ||||||
|  |           steps[i](); | ||||||
|  | 				}).catch(function(err){ | ||||||
|  | 					console.error(err); | ||||||
|  | 				}); | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
|  | |||||||
							
								
								
									
										51
									
								
								js/bacme.js
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								js/bacme.js
									
									
									
									
									
								
							| @ -129,13 +129,24 @@ var textEncoder = new TextEncoder(); | |||||||
| BACME._importKey = function (jwk) { | BACME._importKey = function (jwk) { | ||||||
|   var alg; // I think the 256 refers to the hash
 |   var alg; // I think the 256 refers to the hash
 | ||||||
|   var wcOpts = {}; |   var wcOpts = {}; | ||||||
|   var extractable = false; |   var extractable = true; // TODO make optionally false?
 | ||||||
|  |   var priv = jwk; | ||||||
|  |   var pub; | ||||||
| 
 | 
 | ||||||
|   // ECDSA
 |   // ECDSA
 | ||||||
|   if (/^EC/i.test(jwk.kty)) { |   if (/^EC/i.test(jwk.kty)) { | ||||||
|     wcOpts.name = 'ECDSA'; |     wcOpts.name = 'ECDSA'; | ||||||
|     wcOpts.namedCurve = jwk.crv; |     wcOpts.namedCurve = jwk.crv; | ||||||
|     alg = 'ES256'; |     alg = 'ES256'; | ||||||
|  |     pub = { | ||||||
|  |       crv: priv.crv | ||||||
|  |     , kty: priv.kty | ||||||
|  |     , x: priv.x | ||||||
|  |     , y: priv.y | ||||||
|  |     }; | ||||||
|  |     if (!priv.d) { | ||||||
|  |       priv = null; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // RSA
 |   // RSA
 | ||||||
| @ -143,17 +154,28 @@ BACME._importKey = function (jwk) { | |||||||
|     wcOpts.name = 'RSASSA-PKCS1-v1_5'; |     wcOpts.name = 'RSASSA-PKCS1-v1_5'; | ||||||
|     wcOpts.hash = { name: "SHA-256" }; |     wcOpts.hash = { name: "SHA-256" }; | ||||||
|     alg = 'RS256'; |     alg = 'RS256'; | ||||||
|  |     pub = { | ||||||
|  |       e: priv.e | ||||||
|  |     , kty: priv.kty | ||||||
|  |     , n: priv.n | ||||||
|  |     } | ||||||
|  |     if (!priv.p) { | ||||||
|  |       priv = null; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return window.crypto.subtle.importKey( |   return window.crypto.subtle.importKey( | ||||||
|     "jwk" |     "jwk" | ||||||
|   , jwk |   , pub | ||||||
| 	, wcOpts | 	, wcOpts | ||||||
|   , extractable |   , extractable | ||||||
|   , [ "sign"/*, "verify"*/ ] |   , [ "verify" ] | ||||||
|   ).then(function (keypair) { |   ).then(function (publicKey) { | ||||||
|  |     function give(privateKey) { | ||||||
|       return { |       return { | ||||||
|       wcKey: keypair |         wcPub: publicKey | ||||||
|  |       , wcKey: privateKey | ||||||
|  |       , wcKeypair: { publicKey: publicKey, privateKey: privateKey } | ||||||
|       , meta: { |       , meta: { | ||||||
|           alg: alg |           alg: alg | ||||||
|         , name: wcOpts.name |         , name: wcOpts.name | ||||||
| @ -161,10 +183,21 @@ BACME._importKey = function (jwk) { | |||||||
|         } |         } | ||||||
|       , jwk: jwk |       , jwk: jwk | ||||||
|       }; |       }; | ||||||
|  |     } | ||||||
|  |     if (!priv) { | ||||||
|  |       return give(); | ||||||
|  |     } | ||||||
|  |     return window.crypto.subtle.importKey( | ||||||
|  |       "jwk" | ||||||
|  |     , priv | ||||||
|  |     , wcOpts | ||||||
|  |     , extractable | ||||||
|  |     , [ "sign"/*, "verify"*/ ] | ||||||
|  |     ).then(give); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| BACME._sign = function (opts) { | BACME._sign = function (opts) { | ||||||
|   var wcPrivKey = opts.abstractKey.wcKey; |   var wcPrivKey = opts.abstractKey.wcKeypair.privateKey; | ||||||
|   var wcOpts = opts.abstractKey.meta; |   var wcOpts = opts.abstractKey.meta; | ||||||
|   var alg = opts.abstractKey.meta.alg; // I think the 256 refers to the hash
 |   var alg = opts.abstractKey.meta.alg; // I think the 256 refers to the hash
 | ||||||
|   var signHash; |   var signHash; | ||||||
| @ -508,6 +541,7 @@ BACME.challenges.accept = function (opts) { | |||||||
| 		).then(function (resp) { | 		).then(function (resp) { | ||||||
|       BACME._logHeaders(resp); |       BACME._logHeaders(resp); | ||||||
| 			nonce = resp.headers.get('replay-nonce'); | 			nonce = resp.headers.get('replay-nonce'); | ||||||
|  |       console.log("ACCEPT NONCE:", nonce); | ||||||
| 
 | 
 | ||||||
| 			return resp.json().then(function (reply) { | 			return resp.json().then(function (reply) { | ||||||
|         challengePollUrl = reply.url; |         challengePollUrl = reply.url; | ||||||
| @ -523,7 +557,6 @@ BACME.challenges.accept = function (opts) { | |||||||
| BACME.challenges.check = function (opts) { | BACME.challenges.check = function (opts) { | ||||||
| 	return window.fetch(opts.challengePollUrl, { mode: 'cors' }).then(function (resp) { | 	return window.fetch(opts.challengePollUrl, { mode: 'cors' }).then(function (resp) { | ||||||
|     BACME._logHeaders(resp); |     BACME._logHeaders(resp); | ||||||
| 		nonce = resp.headers.get('replay-nonce'); |  | ||||||
| 
 | 
 | ||||||
| 		return resp.json().then(function (reply) { | 		return resp.json().then(function (reply) { | ||||||
| 			challengePollUrl = reply.url; | 			challengePollUrl = reply.url; | ||||||
| @ -566,7 +599,7 @@ BACME.domains.generateKeypair = function () { | |||||||
| // { serverJwk, domains }
 | // { serverJwk, domains }
 | ||||||
| BACME.orders.generateCsr = function (opts) { | BACME.orders.generateCsr = function (opts) { | ||||||
|   return BACME._importKey(opts.serverJwk).then(function (abstractKey) { |   return BACME._importKey(opts.serverJwk).then(function (abstractKey) { | ||||||
|     return Promise.resolve(CSR.generate({ keypair: abstractKey.wcKey, domains: opts.domains })); |     return Promise.resolve(CSR.generate({ keypair: abstractKey.wcKeypair, domains: opts.domains })); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -621,7 +654,7 @@ BACME.orders.receive = function (opts) { | |||||||
|     BACME._logHeaders(resp); |     BACME._logHeaders(resp); | ||||||
|     nonce = resp.headers.get('replay-nonce'); |     nonce = resp.headers.get('replay-nonce'); | ||||||
| 
 | 
 | ||||||
|     return resp.json().then(function (reply) { |     return resp.text().then(function (reply) { | ||||||
|       BACME._logBody(reply); |       BACME._logBody(reply); | ||||||
| 
 | 
 | ||||||
|       return reply; |       return reply; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user