semi-merge more-acme updates

This commit is contained in:
AJ ONeal 2019-05-06 03:45:11 -06:00
parent f1e11f1be7
commit b902907a7c
5 changed files with 59 additions and 68 deletions

18
app.js
View File

@ -1,3 +1,4 @@
/*global Promise*/
(function () { (function () {
'use strict'; 'use strict';
@ -5,6 +6,9 @@
var Rasha = window.Rasha; var Rasha = window.Rasha;
var Eckles = window.Eckles; var Eckles = window.Eckles;
var x509 = window.x509; var x509 = window.x509;
var CSR = window.CSR;
var ACME = window.ACME;
var accountStuff = {};
function $(sel) { function $(sel) {
return document.querySelector(sel); return document.querySelector(sel);
@ -13,6 +17,11 @@
return Array.prototype.slice.call(document.querySelectorAll(sel)); return Array.prototype.slice.call(document.querySelectorAll(sel));
} }
function checkTos(tos) {
console.log("TODO checkbox for agree to terms");
return tos;
}
function run() { function run() {
console.log('hello'); console.log('hello');
@ -49,8 +58,10 @@
, namedCurve: $('input[name="ec-crv"]:checked').value , namedCurve: $('input[name="ec-crv"]:checked').value
, modulusLength: $('input[name="rsa-len"]:checked').value , modulusLength: $('input[name="rsa-len"]:checked').value
}; };
var then = Date.now();
console.log('opts', opts); console.log('opts', opts);
Keypairs.generate(opts).then(function (results) { Keypairs.generate(opts).then(function (results) {
console.log("Key generation time:", (Date.now() - then) + "ms");
var pubDer; var pubDer;
var privDer; var privDer;
if (/EC/i.test(opts.kty)) { if (/EC/i.test(opts.kty)) {
@ -99,12 +110,13 @@
$$('input').map(function ($el) { $el.disabled = false; }); $$('input').map(function ($el) { $el.disabled = false; });
$$('button').map(function ($el) { $el.disabled = false; }); $$('button').map(function ($el) { $el.disabled = false; });
$('.js-toc-jwk').hidden = false; $('.js-toc-jwk').hidden = false;
});
});
$('.js-create-account').hidden = false;
$('.js-create-csr').hidden = false;
});
});
$('.js-generate').hidden = false; $('.js-generate').hidden = false;
$('.js-create-account').hidden = false;
} }
window.addEventListener('load', run); window.addEventListener('load', run);

View File

@ -34,27 +34,21 @@
</div> </div>
<div class="js-ec-opts"> <div class="js-ec-opts">
<p>EC Options:</p> <p>EC Options:</p>
<input type="radio" id="-crv2" <label for="-crv2"><input type="radio" id="-crv2"
name="ec-crv" value="P-256" checked> name="ec-crv" value="P-256" checked>P-256</label>
<label for="-crv2">P-256</label> <label for="-crv3"><input type="radio" id="-crv3"
<input type="radio" id="-crv3" name="ec-crv" value="P-384">P-384</label>
name="ec-crv" value="P-384"> <!-- label for="-crv5"><input type="radio" id="-crv5"
<label for="-crv3">P-384</label> name="ec-crv" value="P-521">P-521</label -->
<!-- input type="radio" id="-crv5"
name="ec-crv" value="P-521">
<label for="-crv5">P-521</label -->
</div> </div>
<div class="js-rsa-opts" hidden> <div class="js-rsa-opts" hidden>
<p>RSA Options:</p> <p>RSA Options:</p>
<input type="radio" id="-modlen2" <label for="-modlen2"><input type="radio" id="-modlen2"
name="rsa-len" value="2048" checked> name="rsa-len" value="2048" checked>2048</label>
<label for="-modlen2">2048</label> <label for="-modlen3"><input type="radio" id="-modlen3"
<input type="radio" id="-modlen3" name="rsa-len" value="3072">3072</label>
name="rsa-len" value="3072"> <label for="-modlen5"><input type="radio" id="-modlen5"
<label for="-modlen3">3072</label> name="rsa-len" value="4096">4096</label>
<input type="radio" id="-modlen5"
name="rsa-len" value="4096">
<label for="-modlen5">4096</label>
</div> </div>
<button class="js-generate" hidden>Generate</button> <button class="js-generate" hidden>Generate</button>
</form> </form>
@ -100,7 +94,6 @@
<script src="./lib/ecdsa.js"></script> <script src="./lib/ecdsa.js"></script>
<script src="./lib/rsa.js"></script> <script src="./lib/rsa.js"></script>
<script src="./lib/keypairs.js"></script> <script src="./lib/keypairs.js"></script>
<script src="./lib/acme.js"></script>
<script src="./app.js"></script> <script src="./app.js"></script>
</body> </body>
</html> </html>

View File

@ -110,6 +110,8 @@ Enc.binToHex = function (bin) {
return h; return h;
}).join(''); }).join('');
}; };
// TODO are there any nuance differences here?
Enc.utf8ToHex = Enc.binToHex;
Enc.hexToBase64 = function (hex) { Enc.hexToBase64 = function (hex) {
return btoa(Enc.hexToBin(hex)); return btoa(Enc.hexToBin(hex));

View File

@ -180,14 +180,6 @@ Keypairs.signJws = function (opts) {
var msg = protected64 + '.' + payload64; var msg = protected64 + '.' + payload64;
return Keypairs._sign(opts, msg).then(function (buf) { 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 = { var signedMsg = {
protected: protected64 protected: protected64
, payload: payload64 , 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) { Keypairs._sign = function (opts, payload) {
return Keypairs._import(opts).then(function (privkey) { return Keypairs._import(opts).then(function (privkey) {
@ -259,9 +217,12 @@ Keypairs._sign = function (opts, payload) {
, privkey , privkey
, payload , payload
).then(function (signature) { ).then(function (signature) {
// convert buffer to urlsafe base64 signature = new Uint8Array(signature); // ArrayBuffer -> u8
//return Enc.bufToUrlBase64(new Uint8Array(signature)); // This will come back into play for CSRs, but not for JOSE
return new Uint8Array(signature); 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'; return 'RSASSA-PKCS1-v1_5';
} }
}; };
Keypairs._import = function (opts) { Keypairs._import = function (opts) {
return Promise.resolve().then(function () { return Promise.resolve().then(function () {
var ops; 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) { function setTime(time) {
if ('number' === typeof time) { return time; } if ('number' === typeof time) { return time; }

View File

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