forked from coolaj86/bluecrypt-keypairs.js
semi-merge more-acme updates
This commit is contained in:
parent
f1e11f1be7
commit
b902907a7c
16
app.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
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…
Reference in New Issue