2014-05-15 14:20:00 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
var util = {
|
2014-07-25 21:18:58 +04:00
|
|
|
// Compare the contents of two ArrayBuffer(View)s
|
2014-05-15 14:20:00 +04:00
|
|
|
memcmp: function util_memcmp(x, y) {
|
|
|
|
if (!x || !y) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-07-25 21:18:58 +04:00
|
|
|
var xb = new Uint8Array(x);
|
|
|
|
var yb = new Uint8Array(y);
|
2014-05-15 14:20:00 +04:00
|
|
|
if (x.byteLength !== y.byteLength) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-12-14 03:44:52 +03:00
|
|
|
for (var i = 0; i < xb.byteLength; ++i) {
|
2014-05-15 14:20:00 +04:00
|
|
|
if (xb[i] !== yb[i]) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
// Convert an ArrayBufferView to a hex string
|
|
|
|
abv2hex: function util_abv2hex(abv) {
|
2016-01-26 16:57:52 +03:00
|
|
|
var b = new Uint8Array(abv);
|
2014-05-15 14:20:00 +04:00
|
|
|
var hex = "";
|
2018-12-14 03:44:52 +03:00
|
|
|
for (var i = 0; i < b.length; ++i) {
|
2014-05-15 14:20:00 +04:00
|
|
|
var zeropad = b[i] < 0x10 ? "0" : "";
|
|
|
|
hex += zeropad + b[i].toString(16);
|
|
|
|
}
|
|
|
|
return hex;
|
|
|
|
},
|
|
|
|
|
|
|
|
// Convert a hex string to an ArrayBufferView
|
|
|
|
hex2abv: function util_hex2abv(hex) {
|
|
|
|
if (hex.length % 2 !== 0) {
|
|
|
|
hex = "0" + hex;
|
|
|
|
}
|
|
|
|
|
|
|
|
var abv = new Uint8Array(hex.length / 2);
|
2018-12-14 03:44:52 +03:00
|
|
|
for (var i = 0; i < abv.length; ++i) {
|
|
|
|
abv[i] = parseInt(hex.substr(2 * i, 2), 16);
|
2014-05-15 14:20:00 +04:00
|
|
|
}
|
|
|
|
return abv;
|
|
|
|
},
|
2016-03-09 23:18:38 +03:00
|
|
|
|
2018-12-14 03:44:52 +03:00
|
|
|
clone(obj) {
|
2016-03-09 23:18:38 +03:00
|
|
|
return new Promise(resolve => {
|
|
|
|
let { port1, port2 } = new MessageChannel();
|
|
|
|
|
|
|
|
// Wait for the cloned object to arrive.
|
|
|
|
port1.onmessage = msg => resolve(msg.data);
|
|
|
|
|
|
|
|
// Clone the object.
|
|
|
|
port2.postMessage(obj);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2018-12-14 03:44:52 +03:00
|
|
|
cloneExportCompareKeys(key) {
|
2016-03-09 23:18:38 +03:00
|
|
|
return util.clone(key).then(clone => {
|
|
|
|
var exports = [];
|
|
|
|
|
|
|
|
if (key instanceof CryptoKey) {
|
|
|
|
exports.push(crypto.subtle.exportKey("raw", key));
|
|
|
|
exports.push(crypto.subtle.exportKey("raw", clone));
|
|
|
|
} else {
|
|
|
|
exports.push(crypto.subtle.exportKey("spki", key.publicKey));
|
|
|
|
exports.push(crypto.subtle.exportKey("spki", clone.publicKey));
|
|
|
|
exports.push(crypto.subtle.exportKey("pkcs8", key.privateKey));
|
|
|
|
exports.push(crypto.subtle.exportKey("pkcs8", clone.privateKey));
|
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.all(exports).then(pairs => {
|
|
|
|
for (var i = 0; i < pairs.length; i += 2) {
|
|
|
|
if (!util.memcmp(pairs[i], pairs[i + 1])) {
|
|
|
|
throw new Error("keys don't match");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return clone;
|
|
|
|
});
|
|
|
|
});
|
2018-12-14 03:44:52 +03:00
|
|
|
},
|
2014-05-15 14:20:00 +04:00
|
|
|
};
|
2014-08-08 00:24:52 +04:00
|
|
|
|
|
|
|
function exists(x) {
|
|
|
|
return x !== undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
function hasFields(object, fields) {
|
|
|
|
return fields.map(x => exists(object[x])).reduce((x, y) => x && y);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hasKeyFields(x) {
|
|
|
|
return hasFields(x, ["algorithm", "extractable", "type", "usages"]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hasBaseJwkFields(x) {
|
|
|
|
return hasFields(x, ["kty", "alg", "ext", "key_ops"]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function shallowArrayEquals(x, y) {
|
|
|
|
if (x.length != y.length) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-12-15 01:54:56 +03:00
|
|
|
for (let i in x) {
|
2014-08-08 00:24:52 +04:00
|
|
|
if (x[i] != y[i]) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|