tested working in firefox
Este commit está contenido en:
		
							padre
							
								
									136c9c06fe
								
							
						
					
					
						commit
						df964d76c6
					
				@ -40,7 +40,7 @@
 | 
			
		||||
    <link rel="preload" href="./js/pkijs.org/v1.3.33/x509_schema.js" as="script">
 | 
			
		||||
    <link rel="preload" href="./js/pkijs.org/v1.3.33/x509_simpl.js" as="script">
 | 
			
		||||
    <link rel="preload" href="./js/browser-csr/v1.0.0-alpha/csr.js" as="script">
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
  </head>
 | 
			
		||||
  <body hidden>
 | 
			
		||||
    <!-- let's define our SVG that we will reuse -->
 | 
			
		||||
@ -207,6 +207,7 @@
 | 
			
		||||
              <div id="js-acme-ver-uri" class="acme-ver-uri">..loading</div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="js-acme-verification-dns-01">
 | 
			
		||||
              <h3>Set this DNS Record</h3>
 | 
			
		||||
              <div class="acme-ver-dns-label">Hostname</div>
 | 
			
		||||
              <div id="js-acme-ver-hostname">loading...</div>
 | 
			
		||||
              <div class="acme-ver-dns-label">TXT Host</div>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										156
									
								
								app/js/app.js
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								app/js/app.js
									
									
									
									
									
								
							@ -2,7 +2,7 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
  /*global URLSearchParams,Headers*/
 | 
			
		||||
  var BROWSER_SUPPORTS_ECDSA = navigator.userAgent.toLowerCase().indexOf('firefox') === -1;
 | 
			
		||||
  var BROWSER_SUPPORTS_ECDSA;
 | 
			
		||||
  var $qs = function (s) { return window.document.querySelector(s); };
 | 
			
		||||
  var $qsa = function (s) { return window.document.querySelectorAll(s); };
 | 
			
		||||
  var info = {};
 | 
			
		||||
@ -31,16 +31,50 @@
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  function testRsaSupport() {
 | 
			
		||||
    var opts = {
 | 
			
		||||
      type: 'RSA'
 | 
			
		||||
    , bitlength: '2048'
 | 
			
		||||
    };
 | 
			
		||||
    return BACME.accounts.generateKeypair(opts).then(function (jwk) {
 | 
			
		||||
      return crypto.subtle.importKey(
 | 
			
		||||
        "jwk"
 | 
			
		||||
      , jwk
 | 
			
		||||
      , { name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" } }
 | 
			
		||||
      , true
 | 
			
		||||
      , ["sign"]
 | 
			
		||||
      ).then(function (privateKey) {
 | 
			
		||||
        return window.crypto.subtle.exportKey("pkcs8", privateKey);
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  testEcdsaSupport().then(function () {
 | 
			
		||||
    console.log("supports ECDSA");
 | 
			
		||||
    console.info("[crypto] ECDSA is supported");
 | 
			
		||||
    BROWSER_SUPPORTS_ECDSA = true;
 | 
			
		||||
    localStorage.setItem('version', '1');
 | 
			
		||||
    return true;
 | 
			
		||||
  }).catch(function () {
 | 
			
		||||
    console.log("DOES NOT supports ECDSA");
 | 
			
		||||
    console.warn("[crypto] ECDSA is NOT fully supported");
 | 
			
		||||
    BROWSER_SUPPORTS_ECDSA = false;
 | 
			
		||||
 | 
			
		||||
    // fix previous firefox browsers
 | 
			
		||||
    if (!localStorage.getItem('version')) {
 | 
			
		||||
      localStorage.clear();
 | 
			
		||||
      localStorage.getItem('version', '1');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // DO NOT RETURN HERE
 | 
			
		||||
    testRsaSupport().then(function () {
 | 
			
		||||
      console.info('[crypto] RSA is supported');
 | 
			
		||||
    }).catch(function (err) {
 | 
			
		||||
      console.error('[crypto] could not use either EC nor RSA.');
 | 
			
		||||
      console.error(err);
 | 
			
		||||
      window.alert("Your browser is cryptography support (neither RSA or EC is usable). Please use Chrome, Firefox, or Safari.");
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // RETURN HERE
 | 
			
		||||
    return false;
 | 
			
		||||
  });
 | 
			
		||||
  // TODO test RSA support
 | 
			
		||||
 | 
			
		||||
  var apiUrl = 'https://acme-{{env}}.api.letsencrypt.org/directory';
 | 
			
		||||
  function updateApiType() {
 | 
			
		||||
@ -83,7 +117,10 @@
 | 
			
		||||
    var j = i;
 | 
			
		||||
    i += 1;
 | 
			
		||||
 | 
			
		||||
    steps[j].submit(ev);
 | 
			
		||||
    return PromiseA.resolve(steps[j].submit(ev)).catch(function (err) {
 | 
			
		||||
      console.error(err);
 | 
			
		||||
      window.alert.error("Something went wrong. It's our fault not yours. Please email aj@greenlock.domains and let him know that 'step " + j + "' failed.");
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $qsa('.js-acme-form').forEach(function ($el) {
 | 
			
		||||
@ -355,8 +392,9 @@
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    }).catch(function (err) {
 | 
			
		||||
      console.error('Step \'' + i + '\' Error:');
 | 
			
		||||
      console.error('Step \'\' Error:');
 | 
			
		||||
      console.error(err, err.stack);
 | 
			
		||||
      window.alert("An error happened at Step " + i + ", but it's not your fault. Email aj@greenlock.domains and let him know.");
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@ -421,9 +459,22 @@
 | 
			
		||||
              if ('pending' === poll.status) {
 | 
			
		||||
                return true;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              if ('invalid' === poll.status) {
 | 
			
		||||
                allsWell = false;
 | 
			
		||||
                window.alert("verification failed:" + poll.error.detail);
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              if (poll.error) {
 | 
			
		||||
                window.alert("verification failed:" + poll.error.detail);
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              if ('valid' !== poll.status) {
 | 
			
		||||
                allsWell = false;
 | 
			
		||||
                console.warn('BAD POLL STATUS', poll);
 | 
			
		||||
                window.alert("unknown error: " + JSON.stringify(poll, null, 2));
 | 
			
		||||
              }
 | 
			
		||||
              // TODO show status in HTML
 | 
			
		||||
            });
 | 
			
		||||
@ -444,6 +495,38 @@
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // https://stackoverflow.com/questions/40314257/export-webcrypto-key-to-pem-format
 | 
			
		||||
  function spkiToPEM(keydata, pemName){
 | 
			
		||||
      var keydataS = arrayBufferToString(keydata);
 | 
			
		||||
      var keydataB64 = window.btoa(keydataS);
 | 
			
		||||
      var keydataB64Pem = formatAsPem(keydataB64, pemName);
 | 
			
		||||
      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, pemName) {
 | 
			
		||||
      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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // spinner
 | 
			
		||||
  steps[4] = function () {
 | 
			
		||||
    updateProgress(1);
 | 
			
		||||
@ -460,16 +543,10 @@
 | 
			
		||||
    function createKeypair() {
 | 
			
		||||
      var opts;
 | 
			
		||||
 | 
			
		||||
      if(BROWSER_SUPPORTS_ECDSA) {
 | 
			
		||||
        opts = {
 | 
			
		||||
          type: 'ECDSA'
 | 
			
		||||
        , bitlength: '256'
 | 
			
		||||
        };
 | 
			
		||||
      if (BROWSER_SUPPORTS_ECDSA) {
 | 
			
		||||
        opts = { type: 'ECDSA', bitlength: '256' };
 | 
			
		||||
      } else {
 | 
			
		||||
        opts = {
 | 
			
		||||
          type: 'RSA'
 | 
			
		||||
        , bitlength: '2048'
 | 
			
		||||
        };
 | 
			
		||||
        opts = { type: 'RSA', bitlength: '2048' };
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return BACME.domains.generateKeypair(opts).then(function (serverJwk) {
 | 
			
		||||
@ -524,52 +601,14 @@
 | 
			
		||||
        $qs("#js-download-fullchain-link").href =
 | 
			
		||||
          "data:text/octet-stream;base64," + window.btoa(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" }
 | 
			
		||||
          };
 | 
			
		||||
          wcOpts = { name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" } };
 | 
			
		||||
        } else {
 | 
			
		||||
          pemName = 'EC';
 | 
			
		||||
          wcOpts = {
 | 
			
		||||
            name: "ECDSA"
 | 
			
		||||
          , namedCurve: "P-256"
 | 
			
		||||
          };
 | 
			
		||||
          wcOpts = { name: "ECDSA", namedCurve: "P-256" };
 | 
			
		||||
        }
 | 
			
		||||
        return crypto.subtle.importKey(
 | 
			
		||||
          "jwk"
 | 
			
		||||
@ -580,15 +619,16 @@
 | 
			
		||||
        ).then(function (privateKey) {
 | 
			
		||||
          return window.crypto.subtle.exportKey("pkcs8", privateKey);
 | 
			
		||||
        }).then (function (keydata) {
 | 
			
		||||
          var pem = spkiToPEM(keydata);
 | 
			
		||||
          var pem = spkiToPEM(keydata, pemName);
 | 
			
		||||
          $qs('#js-privkey').innerHTML = pem;
 | 
			
		||||
          $qs("#js-download-privkey-link").href =
 | 
			
		||||
            "data:text/octet-stream;base64," + window.btoa(pem);
 | 
			
		||||
          steps[i]();
 | 
			
		||||
        }).catch(function(err){
 | 
			
		||||
          console.error(err.toString());
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    }).catch(function (err) {
 | 
			
		||||
      console.error(err.toString());
 | 
			
		||||
      window.alert("An error happened in the final step, but it's not your fault. Email aj@greenlock.domains and let him know.");
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -38,13 +38,16 @@ BACME._logBody = function (body) {
 | 
			
		||||
BACME.directory = function (opts) {
 | 
			
		||||
  return webFetch(opts.directoryUrl || directoryUrl, { mode: 'cors' }).then(function (resp) {
 | 
			
		||||
    BACME._logHeaders(resp);
 | 
			
		||||
    return resp.json().then(function (body) {
 | 
			
		||||
      directory = body;
 | 
			
		||||
    return resp.json().then(function (reply) {
 | 
			
		||||
      if (/error/.test(reply.type)) {
 | 
			
		||||
        return Promise.reject(new Error(reply.detail || reply.type));
 | 
			
		||||
      }
 | 
			
		||||
      directory = reply;
 | 
			
		||||
      nonceUrl = directory.newNonce || 'https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce';
 | 
			
		||||
      accountUrl = directory.newAccount || 'https://acme-staging-v02.api.letsencrypt.org/acme/new-account';
 | 
			
		||||
      orderUrl = directory.newOrder || "https://acme-staging-v02.api.letsencrypt.org/acme/new-order";
 | 
			
		||||
      BACME._logBody(body);
 | 
			
		||||
      return body;
 | 
			
		||||
      BACME._logBody(reply);
 | 
			
		||||
      return reply;
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
@ -227,18 +230,30 @@ BACME.accounts.sign = function (opts) {
 | 
			
		||||
      payloadJson
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // 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
 | 
			
		||||
        }
 | 
			
		||||
      , jwk: null
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
    if (/EC/i.test(opts.jwk.kty)) {
 | 
			
		||||
      protectedJson.jwk = {
 | 
			
		||||
        crv: opts.jwk.crv
 | 
			
		||||
      , kty: opts.jwk.kty
 | 
			
		||||
      , x: opts.jwk.x
 | 
			
		||||
      , y: opts.jwk.y
 | 
			
		||||
      };
 | 
			
		||||
    } else if (/RS/i.test(opts.jwk.kty)) {
 | 
			
		||||
      protectedJson.jwk = {
 | 
			
		||||
        e: opts.jwk.e
 | 
			
		||||
      , kty: opts.jwk.kty
 | 
			
		||||
      , n: opts.jwk.n
 | 
			
		||||
      };
 | 
			
		||||
    } else {
 | 
			
		||||
      return Promise.reject(new Error("[acme.accounts.sign] unsupported key type '" + opts.jwk.kty + "'"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    console.log('protected:');
 | 
			
		||||
    console.log(protectedJson);
 | 
			
		||||
    var protected64 = BACME._jsto64(
 | 
			
		||||
@ -486,9 +501,7 @@ var challengePollUrl;
 | 
			
		||||
 | 
			
		||||
// { jwk, challengeUrl, accountId (kid) }
 | 
			
		||||
BACME.challenges.accept = function (opts) {
 | 
			
		||||
  var payload64 = BACME._jsto64(
 | 
			
		||||
    {}
 | 
			
		||||
  );
 | 
			
		||||
  var payload64 = BACME._jsto64({});
 | 
			
		||||
 | 
			
		||||
  return BACME._importKey(opts.jwk).then(function (abstractKey) {
 | 
			
		||||
    var protected64 = BACME._jsto64(
 | 
			
		||||
@ -530,6 +543,9 @@ BACME.challenges.check = function (opts) {
 | 
			
		||||
    BACME._logHeaders(resp);
 | 
			
		||||
 | 
			
		||||
    return resp.json().then(function (reply) {
 | 
			
		||||
      if (/error/.test(reply.type)) {
 | 
			
		||||
        return Promise.reject(new Error(reply.detail || reply.type));
 | 
			
		||||
      }
 | 
			
		||||
      challengePollUrl = reply.url;
 | 
			
		||||
 | 
			
		||||
      BACME._logBody(reply);
 | 
			
		||||
@ -630,6 +646,9 @@ BACME.orders.finalize = function (opts) {
 | 
			
		||||
      nonce = resp.headers.get('replay-nonce');
 | 
			
		||||
 | 
			
		||||
      return resp.json().then(function (reply) {
 | 
			
		||||
        if (/error/.test(reply.type)) {
 | 
			
		||||
          return Promise.reject(new Error(reply.detail || reply.type));
 | 
			
		||||
        }
 | 
			
		||||
        certificateUrl = reply.certificate;
 | 
			
		||||
        BACME._logBody(reply);
 | 
			
		||||
 | 
			
		||||
@ -667,6 +686,9 @@ BACME.orders.check = function (opts) {
 | 
			
		||||
    BACME._logHeaders(resp);
 | 
			
		||||
 | 
			
		||||
    return resp.json().then(function (reply) {
 | 
			
		||||
      if (/error/.test(reply.type)) {
 | 
			
		||||
        return Promise.reject(new Error(reply.detail || reply.type));
 | 
			
		||||
      }
 | 
			
		||||
      BACME._logBody(reply);
 | 
			
		||||
 | 
			
		||||
      return reply;
 | 
			
		||||
 | 
			
		||||
		Cargando…
	
	
			
			x
			
			
		
	
		Referencia en una nueva incidencia
	
	Block a user