Begin adding support for browser

This commit is contained in:
Skylar Ittner 2021-07-08 23:29:14 -06:00
parent 8e73504214
commit a56ea40640
3 changed files with 128 additions and 61 deletions

View File

@ -274,19 +274,30 @@ function calculateSHA256HashOfString(str) {
}
function openPublicKeyFile() {
openFileDialog(function (path) {
var keyfile = getFileAsString(path);
openFileDialog(function (path, html5file) {
var importpk = function (keyfile) {
kbpgp.KeyManager.import_from_armored_pgp({
armored: keyfile
}, function (err, pubkeymgr) {
if (!err) {
keyring.add_key_manager(pubkeymgr);
alert("Public key file loaded. You can now analyze PDFs signed by the key's owner.");
} else {
alert("Error loading public key: " + err);
}
});
};
kbpgp.KeyManager.import_from_armored_pgp({
armored: keyfile
}, function (err, pubkeymgr) {
if (!err) {
keyring.add_key_manager(pubkeymgr);
alert("Public key file loaded. You can now analyze PDFs signed by the key's owner.");
} else {
alert("Error loading public key: " + err);
if (typeof nw != 'undefined') {
var keyfile = getFileAsString(path);
importpk(keyfile);
} else {
var fileReader = new FileReader();
fileReader.onload = function (e) {
importpk(e.target.result);
}
});
fileReader.readAsText(html5file);
}
}, ".asc");
}

View File

@ -27,7 +27,7 @@ function openFileDialog(callback, accept) {
dialog.setAttribute("accept", accept);
}
dialog.onchange = function () {
callback(dialog.value);
callback(dialog.value, this.files[0]);
}
dialog.dispatchEvent(new MouseEvent("click", {
"view": window,

View File

@ -56,42 +56,84 @@ function analyzeSignedPDF() {
return;
}
closePDF(false);
openFileDialog(function (path) {
var pdf = Buffer.from(getFileAsUint8Array(path).buffer);
openFileDialog(function (path, html5file) {
var analyze = function (pdf) {
var splitindex = pdf.indexOf("-----BEGIN PGP MESSAGE-----");
if (splitindex == -1) {
alert("Selected file does not contain any recognized signature data.");
return;
}
var pdfdata = pdf.slice(0, splitindex);
var sigdata = pdf.slice(splitindex).toString();
var splitindex = pdf.indexOf("-----BEGIN PGP MESSAGE-----");
if (splitindex == -1) {
alert("Selected file does not contain any recognized signature data.");
return;
}
var pdfdata = pdf.slice(0, splitindex);
var sigdata = pdf.slice(splitindex).toString();
var verify = function (pdfhash) {
loadKeyFromLocalStorage(function () {
verifyMessage(sigdata, function (msg, fprint) {
parseAndDisplaySignature(msg, pdfhash, true, fprint);
}, function (err) {
console.error(err);
console.log(sigdata);
var base64 = sigdata.split("\n\n", 2)[1].split("\n-----END PGP MESSAGE-----")[0];
base64 = base64.substring(0, base64.lastIndexOf("\n")).replaceAll("\n", "");
try {
var msg = window.atob(base64).split("START", 2)[1].split("END", 2)[0];
parseAndDisplaySignature(msg, pdfhash, false, null);
} catch (ex) {
console.error(ex);
alert("Error: could not parse signature data.");
}
});
});
var pdfhash = calculateSHA256HashOfString(pdfdata);
if (typeof nw != 'undefined') {
pdfjsLib.getDocument(pdf).promise.then(function (pdfDoc_) {
pdfDoc = pdfDoc_;
loadKeyFromLocalStorage(function () {
verifyMessage(sigdata, function (msg, fprint) {
parseAndDisplaySignature(msg, pdfhash, true, fprint);
}, function (err) {
console.error(err);
var base64 = sigdata.split("\n\n", 2)[1].split("\n-----END PGP MESSAGE-----")[0];
base64 = base64.substring(0, base64.lastIndexOf("\n")).replaceAll("\n", "");
try {
var msg = window.atob(base64).split("START", 2)[1].split("END", 2)[0];
parseAndDisplaySignature(msg, pdfhash, false, null);
} catch (ex) {
console.error(ex);
alert("Error: could not parse signature data.");
renderAllPages(pdfDoc);
pdfZoom("fitheight");
});
} else {
var fileReader = new FileReader();
fileReader.onload = function () {
pdfjsLib.getDocument(new Uint8Array(this.result)).promise.then(function (pdfDoc_) {
pdfDoc = pdfDoc_;
renderAllPages(pdfDoc);
pdfZoom("fitheight");
});
};
fileReader.readAsArrayBuffer(html5file);
}
});
});
};
pdfjsLib.getDocument(pdf).promise.then(function (pdfDoc_) {
pdfDoc = pdfDoc_;
renderAllPages(pdfDoc);
pdfZoom("fitheight");
});
if (typeof nw != 'undefined') {
verify(calculateSHA256HashOfString(pdfdata));
} else {
window.crypto.subtle.digest("SHA-256", (new TextEncoder()).encode(pdfdata))
.then(hash => {
window.hash = hash;
// here hash is an arrayBuffer,
// so we'll connvert it to its hex version
let result = '';
const view = new DataView(hash);
for (let i = 0; i < hash.byteLength; i += 4) {
result += ('00000000' + view.getUint32(i).toString(16)).slice(-8);
}
verify(result);
});
}
};
if (typeof nw != 'undefined') {
// running in NW.js so we have Node
analyze(Buffer.from(getFileAsUint8Array(path).buffer));
} else {
// no Node :(
var fileReader = new FileReader();
fileReader.onload = function (e) {
analyze(e.target.result);
}
fileReader.readAsBinaryString(html5file);
}
}, ".pdf");
}
@ -143,25 +185,33 @@ then run the analyze tool again to prove if it was changed since notarization.")
$("#verifyModalDetailedInfoList").append('<li class="list-group-item"><i class="fas fa-map-marked-alt fa-fw"></i> State: ' + sanitizeHTMLString(msgparts["STATE"]).toUpperCase() + '</li>');
}
if (typeof msgparts["OTS"] == "string") {
var bytearray = [];
var bytestrarray = msgparts["OTS"].match(/.{1,3}/g);
for (var i = 0; i < bytestrarray.length; i++) {
bytearray.push(bytestrarray[i] * 1);
}
const detached = OpenTimestamps.DetachedTimestampFile.fromHash(new OpenTimestamps.Ops.OpSHA256(), Uint8Array.from(Buffer.from(pdfhash, 'hex')));
const detachedOts = OpenTimestamps.DetachedTimestampFile.deserialize(bytearray);
let options = {};
OpenTimestamps.verify(detachedOts, detached, options).then(verifyResult => {
console.log(verifyResult);
if (typeof verifyResult != "undefined") {
if (typeof verifyResult.bitcoin != undefined) {
$("#verifyModalDetailedInfoList").append('<li class="list-group-item"><i class="fas fa-clock fa-fw"></i> Signing time independently verified on the Bitcoin blockchain. Signed at ' + formatTimestamp("F j, Y g:i a", verifyResult.bitcoin.timestamp) + '</li>');
}
if (typeof verifyResult.litecoin != undefined) {
$("#verifyModalDetailedInfoList").append('<li class="list-group-item"><i class="fas fa-clock fa-fw"></i> Signing time independently verified on the Litecoin blockchain. Signed at ' + formatTimestamp("F j, Y g:i a", verifyResult.bitcoin.timestamp) + '</li>');
}
try {
var bytearray = [];
var bytestrarray = msgparts["OTS"].match(/.{1,3}/g);
for (var i = 0; i < bytestrarray.length; i++) {
bytearray.push(bytestrarray[i] * 1);
}
});
const detached = OpenTimestamps.DetachedTimestampFile.fromHash(new OpenTimestamps.Ops.OpSHA256(), Uint8Array.from(Buffer.from(pdfhash, 'hex')));
const detachedOts = OpenTimestamps.DetachedTimestampFile.deserialize(bytearray);
console.log(OpenTimestamps.info(detachedOts));
let options = {
ignoreBitcoinNode: true,
timeout: 5000
};
OpenTimestamps.verify(detachedOts, detached, options).then(verifyResult => {
console.log(verifyResult);
if (typeof verifyResult != "undefined") {
if (typeof verifyResult.bitcoin != undefined) {
$("#verifyModalDetailedInfoList").append('<li class="list-group-item"><i class="fas fa-clock fa-fw"></i> Signing time independently verified on the Bitcoin blockchain. Signed at ' + formatTimestamp("F j, Y g:i a", verifyResult.bitcoin.timestamp) + '</li>');
}
if (typeof verifyResult.litecoin != undefined) {
$("#verifyModalDetailedInfoList").append('<li class="list-group-item"><i class="fas fa-clock fa-fw"></i> Signing time independently verified on the Litecoin blockchain. Signed at ' + formatTimestamp("F j, Y g:i a", verifyResult.bitcoin.timestamp) + '</li>');
}
}
});
} catch (ex) {
console.error(ex);
}
}
$("#verifyModalDetailedInfoList").append('<li class="list-group-item"><i class="far fa-file fa-fw"></i> Actual file hash: ' + pdfhash + '</li>');
@ -287,6 +337,12 @@ function savePDF() {
function pdfZoom(str) {
disableGuideBox();
if ($("#page-canvas-container .page-canvas").length == 0) {
setTimeout(function () {
pdfZoom(str);
}, 100);
return;
}
var widthpx = $("#page-canvas-container .page-canvas").css("width").replace("px", "") * 1;
var zoomstep = 100;
console.log(widthpx);