mirror of https://github.com/keeweb/keeweb
validate desktop updates before running
parent
41656b76b6
commit
69257b82ad
|
@ -290,6 +290,11 @@ module.exports = function(grunt) {
|
|||
options: { replacements: [{ pattern: ' manifest="manifest.appcache"', replacement: '' }] },
|
||||
files: { 'tmp/desktop/app/index.html': 'dist/index.html' }
|
||||
},
|
||||
'desktop-public-key': {
|
||||
options: { replacements: [{ pattern: '\'PUBLIC_KEY_CONTENT\'', replacement:
|
||||
'`' + fs.readFileSync('keys/public-key.pem', {encoding: 'utf8'}).trim() + '`' }] },
|
||||
files: { 'tmp/desktop/app/main.js': 'desktop/main.js' }
|
||||
},
|
||||
'cordova-html': {
|
||||
options: { replacements: [{ pattern: '<script', replacement: '<script src="cordova.js"></script><script' }] },
|
||||
files: { 'tmp/cordova/app/index.html': 'dist/index.html' }
|
||||
|
@ -678,6 +683,7 @@ module.exports = function(grunt) {
|
|||
|
||||
grunt.registerTask('build-desktop-app-content', [
|
||||
'copy:desktop-app-content',
|
||||
'string-replace:desktop-public-key',
|
||||
'string-replace:desktop-html'
|
||||
]);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// It checks whether the app is available in userData folder and if its version is higher than local, launches it
|
||||
// This script is the only part which will be updated only with the app itself, auto-update will not change it
|
||||
|
||||
// (C) Antelle 2015, MIT license https://github.com/keeweb/keeweb
|
||||
// (C) Antelle 2017, MIT license https://github.com/keeweb/keeweb
|
||||
|
||||
const app = require('electron').app;
|
||||
const path = require('path');
|
||||
|
@ -23,6 +23,11 @@ if (fs.existsSync(appPathUserData)) {
|
|||
for (let i = 0; i < versionLocal.length; i++) {
|
||||
if (+versionUserData[i] > +versionLocal[i]) {
|
||||
appPath = appPathUserData;
|
||||
try {
|
||||
validateSignature(path);
|
||||
} catch (e) {
|
||||
exitWithError('Error validating signatures: ' + e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (+versionUserData[i] < +versionLocal[i]) {
|
||||
|
@ -34,4 +39,37 @@ if (fs.existsSync(appPathUserData)) {
|
|||
}
|
||||
}
|
||||
|
||||
function validateSignature(appPath) {
|
||||
const signatures = JSON.parse(fs.readFileSync(path.join(appPath, 'signatures.json')));
|
||||
const selfSignature = signatures.self;
|
||||
if (!selfSignature) {
|
||||
exitWithError('No self signature');
|
||||
}
|
||||
delete signatures.self;
|
||||
const data = JSON.stringify(signatures);
|
||||
validateDataSignature(Buffer.from(data), selfSignature, 'self');
|
||||
Object.keys(signatures).forEach(signedFilePath => {
|
||||
const resourcePath = path.join(appPath, signedFilePath);
|
||||
const fileData = fs.readFileSync(resourcePath);
|
||||
validateDataSignature(fileData, signatures[signedFilePath], signedFilePath);
|
||||
});
|
||||
}
|
||||
|
||||
function validateDataSignature(data, signature, name) {
|
||||
const crypto = require('crypto');
|
||||
const publicKey = 'PUBLIC_KEY_CONTENT';
|
||||
const verify = crypto.createVerify('RSA-SHA256');
|
||||
verify.write(data);
|
||||
verify.end();
|
||||
signature = Buffer.from(signature, 'base64');
|
||||
if (!verify.verify(publicKey, signature)) {
|
||||
exitWithError('Resource corrupted: ' + name);
|
||||
}
|
||||
}
|
||||
|
||||
function exitWithError(err) {
|
||||
console.error(err); // eslint-disable-line no-console
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
require(appPath);
|
||||
|
|
Loading…
Reference in New Issue