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>
 | 
			
		||||
    </form>
 | 
			
		||||
 | 
			
		||||
    <!-- Step 4 Process Challanges -->
 | 
			
		||||
    <!-- Step 5 Get Certs -->
 | 
			
		||||
    <form class="js-acme-form js-acme-form-download">
 | 
			
		||||
      <label>privkey.pem</label>
 | 
			
		||||
      <textarea>-</textarea>
 | 
			
		||||
      <textarea class="js-privkey">-</textarea>
 | 
			
		||||
 | 
			
		||||
      <label>fullchain.pem</label>
 | 
			
		||||
      <textarea>-</textarea>
 | 
			
		||||
      <textarea class="js-fullchain">-</textarea>
 | 
			
		||||
 | 
			
		||||
      <!--
 | 
			
		||||
        TODO
 | 
			
		||||
      <label>cert.pem</label>
 | 
			
		||||
      <textarea>-</textarea>
 | 
			
		||||
      <textarea class="js-cert">-</textarea>
 | 
			
		||||
 | 
			
		||||
      <label>chain.pem</label>
 | 
			
		||||
      <textarea>-</textarea>
 | 
			
		||||
      <textarea class="js-chain">-</textarea>
 | 
			
		||||
      -->
 | 
			
		||||
 | 
			
		||||
      <button type="button">Download SSL Certificates</button>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -10,5 +10,5 @@ popd
 | 
			
		||||
 | 
			
		||||
mkdir -p 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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										81
									
								
								js/app.js
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								js/app.js
									
									
									
									
									
								
							@ -30,7 +30,9 @@
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
  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);
 | 
			
		||||
    $qs('.js-acme-table-wildcard').hidden = true;
 | 
			
		||||
    $qs('.js-acme-table-http-01').hidden = true;
 | 
			
		||||
@ -200,7 +202,6 @@
 | 
			
		||||
                      , dnsAnswer: dnsAuth.answer
 | 
			
		||||
                      };
 | 
			
		||||
 | 
			
		||||
                      obj[c.type].push(data);
 | 
			
		||||
                      console.log('');
 | 
			
		||||
                      console.log('CHALLENGE');
 | 
			
		||||
                      console.log(claim);
 | 
			
		||||
@ -258,9 +259,6 @@
 | 
			
		||||
    $qs('.js-acme-form-challenges').hidden = false;
 | 
			
		||||
  };
 | 
			
		||||
  steps[3].submit = function () {
 | 
			
		||||
    // 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) {
 | 
			
		||||
@ -283,6 +281,7 @@
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
    console.log("INFO.challenges !!!!!", info.challenges);
 | 
			
		||||
 | 
			
		||||
    var results = [];
 | 
			
		||||
    function nextChallenge() {
 | 
			
		||||
@ -294,6 +293,7 @@
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // for now just show the next page immediately (its a spinner)
 | 
			
		||||
    steps[i]();
 | 
			
		||||
    return nextChallenge().then(function (results) {
 | 
			
		||||
      console.log('challenge status:', results);
 | 
			
		||||
@ -366,6 +366,7 @@
 | 
			
		||||
 | 
			
		||||
    return p.then(function (_serverJwk) {
 | 
			
		||||
      serverJwk = _serverJwk;
 | 
			
		||||
      info.serverJwk = serverJwk;
 | 
			
		||||
      // { serverJwk, domains }
 | 
			
		||||
      return BACME.orders.generateCsr({
 | 
			
		||||
        serverJwk: serverJwk
 | 
			
		||||
@ -373,7 +374,7 @@
 | 
			
		||||
          return ident.value;
 | 
			
		||||
        })
 | 
			
		||||
      }).then(function (csrweb64) {
 | 
			
		||||
        return BACME.order.finalize({
 | 
			
		||||
        return BACME.orders.finalize({
 | 
			
		||||
          csr: csrweb64
 | 
			
		||||
        , jwk: info.jwk
 | 
			
		||||
        , finalizeUrl: info.finalizeUrl
 | 
			
		||||
@ -384,7 +385,7 @@
 | 
			
		||||
          return new Promise(function (resolve) {
 | 
			
		||||
            setTimeout(resolve, 1000);
 | 
			
		||||
          }).then(function () {
 | 
			
		||||
            return BACME.order.check({ orderUrl: info.orderUrl });
 | 
			
		||||
            return BACME.orders.check({ orderUrl: info.orderUrl });
 | 
			
		||||
          }).then(function (reply) {
 | 
			
		||||
            if ('processing' === reply) {
 | 
			
		||||
              return checkCert();
 | 
			
		||||
@ -395,10 +396,74 @@
 | 
			
		||||
 | 
			
		||||
        return checkCert();
 | 
			
		||||
      }).then(function (reply) {
 | 
			
		||||
        return BACME.order.receive({ certificateUrl: reply.certificate });
 | 
			
		||||
        return BACME.orders.receive({ certificateUrl: reply.certificate });
 | 
			
		||||
      }).then(function (certs) {
 | 
			
		||||
        console.log('WINNING!');
 | 
			
		||||
        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);
 | 
			
		||||
				});
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										67
									
								
								js/bacme.js
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								js/bacme.js
									
									
									
									
									
								
							@ -129,13 +129,24 @@ var textEncoder = new TextEncoder();
 | 
			
		||||
BACME._importKey = function (jwk) {
 | 
			
		||||
  var alg; // I think the 256 refers to the hash
 | 
			
		||||
  var wcOpts = {};
 | 
			
		||||
  var extractable = false;
 | 
			
		||||
  var extractable = true; // TODO make optionally false?
 | 
			
		||||
  var priv = jwk;
 | 
			
		||||
  var pub;
 | 
			
		||||
 | 
			
		||||
  // ECDSA
 | 
			
		||||
  if (/^EC/i.test(jwk.kty)) {
 | 
			
		||||
    wcOpts.name = 'ECDSA';
 | 
			
		||||
    wcOpts.namedCurve = jwk.crv;
 | 
			
		||||
    alg = 'ES256';
 | 
			
		||||
    pub = {
 | 
			
		||||
      crv: priv.crv
 | 
			
		||||
    , kty: priv.kty
 | 
			
		||||
    , x: priv.x
 | 
			
		||||
    , y: priv.y
 | 
			
		||||
    };
 | 
			
		||||
    if (!priv.d) {
 | 
			
		||||
      priv = null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // RSA
 | 
			
		||||
@ -143,28 +154,50 @@ BACME._importKey = function (jwk) {
 | 
			
		||||
    wcOpts.name = 'RSASSA-PKCS1-v1_5';
 | 
			
		||||
    wcOpts.hash = { name: "SHA-256" };
 | 
			
		||||
    alg = 'RS256';
 | 
			
		||||
    pub = {
 | 
			
		||||
      e: priv.e
 | 
			
		||||
    , kty: priv.kty
 | 
			
		||||
    , n: priv.n
 | 
			
		||||
    }
 | 
			
		||||
    if (!priv.p) {
 | 
			
		||||
      priv = null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return window.crypto.subtle.importKey(
 | 
			
		||||
    "jwk"
 | 
			
		||||
  , jwk
 | 
			
		||||
  , pub
 | 
			
		||||
	, wcOpts
 | 
			
		||||
  , extractable
 | 
			
		||||
  , [ "sign"/*, "verify"*/ ]
 | 
			
		||||
  ).then(function (keypair) {
 | 
			
		||||
    return {
 | 
			
		||||
      wcKey: keypair
 | 
			
		||||
    , meta: {
 | 
			
		||||
        alg: alg
 | 
			
		||||
      , name: wcOpts.name
 | 
			
		||||
      , hash: wcOpts.hash
 | 
			
		||||
      }
 | 
			
		||||
    , jwk: jwk
 | 
			
		||||
    };
 | 
			
		||||
  , [ "verify" ]
 | 
			
		||||
  ).then(function (publicKey) {
 | 
			
		||||
    function give(privateKey) {
 | 
			
		||||
      return {
 | 
			
		||||
        wcPub: publicKey
 | 
			
		||||
      , wcKey: privateKey
 | 
			
		||||
      , wcKeypair: { publicKey: publicKey, privateKey: privateKey }
 | 
			
		||||
      , meta: {
 | 
			
		||||
          alg: alg
 | 
			
		||||
        , name: wcOpts.name
 | 
			
		||||
        , hash: wcOpts.hash
 | 
			
		||||
        }
 | 
			
		||||
      , jwk: jwk
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    if (!priv) {
 | 
			
		||||
      return give();
 | 
			
		||||
    }
 | 
			
		||||
    return window.crypto.subtle.importKey(
 | 
			
		||||
      "jwk"
 | 
			
		||||
    , priv
 | 
			
		||||
    , wcOpts
 | 
			
		||||
    , extractable
 | 
			
		||||
    , [ "sign"/*, "verify"*/ ]
 | 
			
		||||
    ).then(give);
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
BACME._sign = function (opts) {
 | 
			
		||||
  var wcPrivKey = opts.abstractKey.wcKey;
 | 
			
		||||
  var wcPrivKey = opts.abstractKey.wcKeypair.privateKey;
 | 
			
		||||
  var wcOpts = opts.abstractKey.meta;
 | 
			
		||||
  var alg = opts.abstractKey.meta.alg; // I think the 256 refers to the hash
 | 
			
		||||
  var signHash;
 | 
			
		||||
@ -508,6 +541,7 @@ BACME.challenges.accept = function (opts) {
 | 
			
		||||
		).then(function (resp) {
 | 
			
		||||
      BACME._logHeaders(resp);
 | 
			
		||||
			nonce = resp.headers.get('replay-nonce');
 | 
			
		||||
      console.log("ACCEPT NONCE:", nonce);
 | 
			
		||||
 | 
			
		||||
			return resp.json().then(function (reply) {
 | 
			
		||||
        challengePollUrl = reply.url;
 | 
			
		||||
@ -523,7 +557,6 @@ BACME.challenges.accept = function (opts) {
 | 
			
		||||
BACME.challenges.check = function (opts) {
 | 
			
		||||
	return window.fetch(opts.challengePollUrl, { mode: 'cors' }).then(function (resp) {
 | 
			
		||||
    BACME._logHeaders(resp);
 | 
			
		||||
		nonce = resp.headers.get('replay-nonce');
 | 
			
		||||
 | 
			
		||||
		return resp.json().then(function (reply) {
 | 
			
		||||
			challengePollUrl = reply.url;
 | 
			
		||||
@ -566,7 +599,7 @@ BACME.domains.generateKeypair = function () {
 | 
			
		||||
// { 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 }));
 | 
			
		||||
    return Promise.resolve(CSR.generate({ keypair: abstractKey.wcKeypair, domains: opts.domains }));
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -621,7 +654,7 @@ BACME.orders.receive = function (opts) {
 | 
			
		||||
    BACME._logHeaders(resp);
 | 
			
		||||
    nonce = resp.headers.get('replay-nonce');
 | 
			
		||||
 | 
			
		||||
    return resp.json().then(function (reply) {
 | 
			
		||||
    return resp.text().then(function (reply) {
 | 
			
		||||
      BACME._logBody(reply);
 | 
			
		||||
 | 
			
		||||
      return reply;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user