diff --git a/src/js/crypto.js b/src/js/crypto.js index 171e733..3a40cc9 100644 --- a/src/js/crypto.js +++ b/src/js/crypto.js @@ -249,6 +249,55 @@ function importPrivateKey() { }, ".asc"); } +/** + * Call the native system GPG to "decrypt" a PGP signature. This should work when the hacky "base64 decode and search for strings" method fails. + * @param {String} sigdata + * @param {Function} callback (string) message, (string) fingerprint, (bool) success + * @returns {undefined} + */ +function readSignatureExternally(sigdata, callback) { + const exec = require('child_process').exec; + const os = require('os'); + const process = require('process'); + + const sigfilepath = getNewTempFilePath() + ".asc"; + writeToFile(sigfilepath, sigdata); + + var gpgexecutable = "gpg"; + switch (os.platform()) { + case "win32": + // Most systems will have it here + gpgexecutable = '"C:\\Program Files (x86)\\gnupg\\bin\\gpg.exe"'; + if (!fs.existsSync(gpgexecutable)) { + // Let's hope it's in %PATH% + gpgexecutable = "gpg.exe"; + } + break; + case "linux": + break; + default: + break; + } + + var command = gpgexecutable + " -vv --decrypt " + sigfilepath; + exec(command, function (error, stdout, stderr) { + console.log(stdout); + var msg = null; + if (stdout.length > 50) { + msg = stdout; + } else { + callback(null, null, false); + } + + var keyid = null; + var keyidregex = /(keyid|RSA key) ([A-F0-9]+)/; + if (keyidregex.test(stderr)) { + keyid = stderr.match(keyidregex)[2]; + } + callback(msg, keyid, true); + }); +} + function calculateSHA256HashOfBuffer(buffer) { const hasha = require('hasha'); var hashstr = hasha(Buffer.from(buffer), {algorithm: 'sha256'}); diff --git a/src/js/filesystem.js b/src/js/filesystem.js index 2785305..3e8dfaa 100644 --- a/src/js/filesystem.js +++ b/src/js/filesystem.js @@ -94,6 +94,24 @@ function deleteFile(path) { } function getBasename(fullpath) { - var path = require("path"); + const path = require("path"); return path.basename(fullpath); +} + +/** + * Get the path to a nonexistent, randomly-named temporary file. + * @returns {String} + */ +function getNewTempFilePath() { + const fs = require('fs'); + const path = require("path"); + const crypto = require('crypto'); + const os = require('os'); + + const randomname = crypto.randomBytes(6).readUIntLE(0,6).toString(36); + var temppath = path.join(os.tmpdir(), "nwjs-app-"); + + var folder = fs.mkdtempSync(temppath); + + return path.join(folder, randomname); } \ No newline at end of file diff --git a/src/js/pdf.js b/src/js/pdf.js index c92e7cb..efec750 100644 --- a/src/js/pdf.js +++ b/src/js/pdf.js @@ -83,8 +83,14 @@ function analyzeSignedPDF() { var msg = window.atob(base64).split("START", 2)[1].split("END", 2)[0]; parseAndDisplaySignature(msg, pdfhash, false, null); } catch (ex) { + readSignatureExternally(sigdata, function (msg, keyprint, ok) { + if (!ok) { + showAlert("Error: could not parse signature data."); + return; + } + parseAndDisplaySignature(msg, pdfhash, false, keyprint); + }); console.error(ex); - showAlert("Error: could not parse signature data."); } }); }); @@ -233,9 +239,14 @@ then run the analyze tool again to prove if it was changed since notarization.") } if (typeof fingerprint == "string") { - var fingerprintstart = fingerprint.substr(0, fingerprint.length - 16); - var fingerprintend = fingerprint.substr(-16); - $("#verifyModalDetailedInfoList").append('
  • Signature fingerprint: ' + fingerprintstart + '' + fingerprintend + '
  • '); + if (fingerprint.length > 16) { + var fingerprintstart = fingerprint.substr(0, fingerprint.length - 16); + var fingerprintend = fingerprint.substr(-16); + } else { + var fingerprintstart = ""; + var fingerprintend = fingerprint; + } + $("#verifyModalDetailedInfoList").append('
  • Signature key ID: ' + fingerprintstart + '' + fingerprintend + '
  • '); } new bootstrap.Modal(document.getElementById('verifyModal')).show(); }