Browse Source

semi-merge more-acme updates

browser-v2
AJ ONeal 5 years ago
parent
commit
b902907a7c
  1. 16
      app.js
  2. 31
      index.html
  3. 2
      lib/bluecrypt-encoding.js
  4. 76
      lib/keypairs.js
  5. 2
      lib/x509.js

16
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

@ -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>

2
lib/bluecrypt-encoding.js

@ -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));

76
lib/keypairs.js

@ -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; }

2
lib/x509.js

@ -1,6 +1,6 @@
'use strict';
(function (exports) {
'use strict';
var x509 = exports.x509 = {};
var ASN1 = exports.ASN1;
var Enc = exports.Enc;

Loading…
Cancel
Save