create acocunt and order, and view challenges
Tento commit je obsažen v:
		
							rodič
							
								
									5d4f71ba8e
								
							
						
					
					
						revize
						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 }
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Načítá se…
	
	
			
			x
			
			
		
	
		Odkázat v novém úkolu
	
	Zablokovat Uživatele