forked from root/acme.js
		
	semi-merge more-acme updates
This commit is contained in:
		
							parent
							
								
									f1e11f1be7
								
							
						
					
					
						commit
						b902907a7c
					
				
							
								
								
									
										18
									
								
								app.js
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								app.js
									
									
									
									
									
								
							@ -1,3 +1,4 @@
 | 
			
		||||
/*global Promise*/
 | 
			
		||||
(function () {
 | 
			
		||||
  'use strict';
 | 
			
		||||
 | 
			
		||||
@ -5,6 +6,9 @@
 | 
			
		||||
  var Rasha = window.Rasha;
 | 
			
		||||
  var Eckles = window.Eckles;
 | 
			
		||||
  var x509 = window.x509;
 | 
			
		||||
  var CSR = window.CSR;
 | 
			
		||||
  var ACME = window.ACME;
 | 
			
		||||
  var accountStuff = {};
 | 
			
		||||
 | 
			
		||||
  function $(sel) {
 | 
			
		||||
    return document.querySelector(sel);
 | 
			
		||||
@ -13,6 +17,11 @@
 | 
			
		||||
    return Array.prototype.slice.call(document.querySelectorAll(sel));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function checkTos(tos) {
 | 
			
		||||
    console.log("TODO checkbox for agree to terms");
 | 
			
		||||
    return tos;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function run() {
 | 
			
		||||
    console.log('hello');
 | 
			
		||||
 | 
			
		||||
@ -49,8 +58,10 @@
 | 
			
		||||
      , namedCurve: $('input[name="ec-crv"]:checked').value
 | 
			
		||||
      , modulusLength: $('input[name="rsa-len"]:checked').value
 | 
			
		||||
      };
 | 
			
		||||
      var then = Date.now();
 | 
			
		||||
      console.log('opts', opts);
 | 
			
		||||
      Keypairs.generate(opts).then(function (results) {
 | 
			
		||||
        console.log("Key generation time:", (Date.now() - then) + "ms");
 | 
			
		||||
        var pubDer;
 | 
			
		||||
        var privDer;
 | 
			
		||||
        if (/EC/i.test(opts.kty)) {
 | 
			
		||||
@ -99,12 +110,13 @@
 | 
			
		||||
        $$('input').map(function ($el) { $el.disabled = false; });
 | 
			
		||||
        $$('button').map(function ($el) { $el.disabled = false; });
 | 
			
		||||
        $('.js-toc-jwk').hidden = false;
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
        $('.js-create-account').hidden = false;
 | 
			
		||||
        $('.js-create-csr').hidden = false;
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('.js-generate').hidden = false;
 | 
			
		||||
    $('.js-create-account').hidden = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  window.addEventListener('load', run);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								index.html
									
									
									
									
									
								
							@ -34,27 +34,21 @@
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="js-ec-opts">
 | 
			
		||||
        <p>EC Options:</p>
 | 
			
		||||
        <input type="radio" id="-crv2"
 | 
			
		||||
         name="ec-crv" value="P-256" checked>
 | 
			
		||||
        <label for="-crv2">P-256</label>
 | 
			
		||||
        <input type="radio" id="-crv3"
 | 
			
		||||
         name="ec-crv" value="P-384">
 | 
			
		||||
        <label for="-crv3">P-384</label>
 | 
			
		||||
        <!-- input type="radio" id="-crv5"
 | 
			
		||||
         name="ec-crv" value="P-521">
 | 
			
		||||
        <label for="-crv5">P-521</label -->
 | 
			
		||||
        <label for="-crv2"><input type="radio" id="-crv2"
 | 
			
		||||
         name="ec-crv" value="P-256" checked>P-256</label>
 | 
			
		||||
        <label for="-crv3"><input type="radio" id="-crv3"
 | 
			
		||||
         name="ec-crv" value="P-384">P-384</label>
 | 
			
		||||
        <!-- label for="-crv5"><input type="radio" id="-crv5"
 | 
			
		||||
         name="ec-crv" value="P-521">P-521</label -->
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="js-rsa-opts" hidden>
 | 
			
		||||
        <p>RSA Options:</p>
 | 
			
		||||
        <input type="radio" id="-modlen2"
 | 
			
		||||
         name="rsa-len" value="2048" checked>
 | 
			
		||||
        <label for="-modlen2">2048</label>
 | 
			
		||||
        <input type="radio" id="-modlen3"
 | 
			
		||||
         name="rsa-len" value="3072">
 | 
			
		||||
        <label for="-modlen3">3072</label>
 | 
			
		||||
        <input type="radio" id="-modlen5"
 | 
			
		||||
         name="rsa-len" value="4096">
 | 
			
		||||
        <label for="-modlen5">4096</label>
 | 
			
		||||
        <label for="-modlen2"><input type="radio" id="-modlen2"
 | 
			
		||||
         name="rsa-len" value="2048" checked>2048</label>
 | 
			
		||||
        <label for="-modlen3"><input type="radio" id="-modlen3"
 | 
			
		||||
         name="rsa-len" value="3072">3072</label>
 | 
			
		||||
        <label for="-modlen5"><input type="radio" id="-modlen5"
 | 
			
		||||
         name="rsa-len" value="4096">4096</label>
 | 
			
		||||
      </div>
 | 
			
		||||
      <button class="js-generate" hidden>Generate</button>
 | 
			
		||||
    </form>
 | 
			
		||||
@ -100,7 +94,6 @@
 | 
			
		||||
    <script src="./lib/ecdsa.js"></script>
 | 
			
		||||
    <script src="./lib/rsa.js"></script>
 | 
			
		||||
    <script src="./lib/keypairs.js"></script>
 | 
			
		||||
    <script src="./lib/acme.js"></script>
 | 
			
		||||
    <script src="./app.js"></script>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
@ -110,6 +110,8 @@ Enc.binToHex = function (bin) {
 | 
			
		||||
    return h;
 | 
			
		||||
  }).join('');
 | 
			
		||||
};
 | 
			
		||||
// TODO are there any nuance differences here?
 | 
			
		||||
Enc.utf8ToHex = Enc.binToHex;
 | 
			
		||||
 | 
			
		||||
Enc.hexToBase64 = function (hex) {
 | 
			
		||||
  return btoa(Enc.hexToBin(hex));
 | 
			
		||||
 | 
			
		||||
@ -180,14 +180,6 @@ Keypairs.signJws = function (opts) {
 | 
			
		||||
      var msg = protected64 + '.' + payload64;
 | 
			
		||||
 | 
			
		||||
      return Keypairs._sign(opts, msg).then(function (buf) {
 | 
			
		||||
        /*
 | 
			
		||||
         * This will come back into play for CSRs, but not for JOSE
 | 
			
		||||
        if ('EC' === opts.jwk.kty) {
 | 
			
		||||
          // ECDSA JWT signatures differ from "normal" ECDSA signatures
 | 
			
		||||
          // https://tools.ietf.org/html/rfc7518#section-3.4
 | 
			
		||||
          binsig = convertIfEcdsa(binsig);
 | 
			
		||||
        }
 | 
			
		||||
        */
 | 
			
		||||
        var signedMsg = {
 | 
			
		||||
          protected: protected64
 | 
			
		||||
        , payload: payload64
 | 
			
		||||
@ -212,40 +204,6 @@ Keypairs.signJws = function (opts) {
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
Keypairs._convertIfEcdsa = function (binsig) {
 | 
			
		||||
  // should have asn1 sequence header of 0x30
 | 
			
		||||
  if (0x30 !== binsig[0]) { throw new Error("Impossible EC SHA head marker"); }
 | 
			
		||||
  var index = 2; // first ecdsa "R" header byte
 | 
			
		||||
  var len = binsig[1];
 | 
			
		||||
  var lenlen = 0;
 | 
			
		||||
  // Seek length of length if length is greater than 127 (i.e. two 512-bit / 64-byte R and S values)
 | 
			
		||||
  if (0x80 & len) {
 | 
			
		||||
    lenlen = len - 0x80; // should be exactly 1
 | 
			
		||||
    len = binsig[2]; // should be <= 130 (two 64-bit SHA-512s, plus padding)
 | 
			
		||||
    index += lenlen;
 | 
			
		||||
  }
 | 
			
		||||
  // should be of BigInt type
 | 
			
		||||
  if (0x02 !== binsig[index]) { throw new Error("Impossible EC SHA R marker"); }
 | 
			
		||||
  index += 1;
 | 
			
		||||
 | 
			
		||||
  var rlen = binsig[index];
 | 
			
		||||
  var bits = 32;
 | 
			
		||||
  if (rlen > 49) {
 | 
			
		||||
    bits = 64;
 | 
			
		||||
  } else if (rlen > 33) {
 | 
			
		||||
    bits = 48;
 | 
			
		||||
  }
 | 
			
		||||
  var r = binsig.slice(index + 1, index + 1 + rlen).toString('hex');
 | 
			
		||||
  var slen = binsig[index + 1 + rlen + 1]; // skip header and read length
 | 
			
		||||
  var s = binsig.slice(index + 1 + rlen + 1 + 1).toString('hex');
 | 
			
		||||
  if (2 *slen !== s.length) { throw new Error("Impossible EC SHA S length"); }
 | 
			
		||||
  // There may be one byte of padding on either
 | 
			
		||||
  while (r.length < 2*bits) { r = '00' + r; }
 | 
			
		||||
  while (s.length < 2*bits) { s = '00' + s; }
 | 
			
		||||
  if (2*(bits+1) === r.length) { r = r.slice(2); }
 | 
			
		||||
  if (2*(bits+1) === s.length) { s = s.slice(2); }
 | 
			
		||||
  return Enc.hexToBuf(r + s);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Keypairs._sign = function (opts, payload) {
 | 
			
		||||
  return Keypairs._import(opts).then(function (privkey) {
 | 
			
		||||
@ -259,9 +217,12 @@ Keypairs._sign = function (opts, payload) {
 | 
			
		||||
    , privkey
 | 
			
		||||
    , payload
 | 
			
		||||
    ).then(function (signature) {
 | 
			
		||||
      // convert buffer to urlsafe base64
 | 
			
		||||
      //return Enc.bufToUrlBase64(new Uint8Array(signature));
 | 
			
		||||
      return new Uint8Array(signature);
 | 
			
		||||
      signature = new Uint8Array(signature); // ArrayBuffer -> u8
 | 
			
		||||
      // This will come back into play for CSRs, but not for JOSE
 | 
			
		||||
      if ('EC' === opts.jwk.kty && /x509/i.test(opts.format)) {
 | 
			
		||||
        signature = Keypairs._ecdsaJoseSigToAsn1Sig(signature);
 | 
			
		||||
      }
 | 
			
		||||
      return signature;
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
@ -287,7 +248,6 @@ Keypairs._getName = function (opts) {
 | 
			
		||||
    return 'RSASSA-PKCS1-v1_5';
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Keypairs._import = function (opts) {
 | 
			
		||||
  return Promise.resolve().then(function () {
 | 
			
		||||
    var ops;
 | 
			
		||||
@ -316,6 +276,30 @@ Keypairs._import = function (opts) {
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
// ECDSA JOSE / JWS / JWT signatures differ from "normal" ASN1/X509 ECDSA signatures
 | 
			
		||||
// https://tools.ietf.org/html/rfc7518#section-3.4
 | 
			
		||||
Keypairs._ecdsaJoseSigToAsn1Sig = function (bufsig) {
 | 
			
		||||
  // it's easier to do the manipulation in the browser with an array
 | 
			
		||||
  bufsig = Array.from(bufsig);
 | 
			
		||||
  var hlen = bufsig.length / 2; // should be even
 | 
			
		||||
  var r = bufsig.slice(0, hlen);
 | 
			
		||||
  var s = bufsig.slice(hlen);
 | 
			
		||||
  // unpad positive ints less than 32 bytes wide
 | 
			
		||||
  while (!r[0]) { r = r.slice(1); }
 | 
			
		||||
  while (!s[0]) { s = s.slice(1); }
 | 
			
		||||
  // pad (or re-pad) ambiguously non-negative BigInts, up to 33 bytes wide
 | 
			
		||||
  if (0x80 & r[0]) { r.unshift(0); }
 | 
			
		||||
  if (0x80 & s[0]) { s.unshift(0); }
 | 
			
		||||
 | 
			
		||||
  var len = 2 + r.length + 2 + s.length;
 | 
			
		||||
  var head = [0x30];
 | 
			
		||||
  // hard code 0x80 + 1 because it won't be longer than
 | 
			
		||||
  // two SHA512 plus two pad bytes (130 bytes <= 256)
 | 
			
		||||
  if (len >= 0x80) { head.push(0x81); }
 | 
			
		||||
  head.push(len);
 | 
			
		||||
 | 
			
		||||
  return Uint8Array.from(head.concat([0x02, r.length], r, [0x02, s.byteLength], s));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function setTime(time) {
 | 
			
		||||
  if ('number' === typeof time) { return time; }
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
(function (exports) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
 | 
			
		||||
  var x509 = exports.x509 = {};
 | 
			
		||||
  var ASN1 = exports.ASN1;
 | 
			
		||||
  var Enc = exports.Enc;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user