From 9159bd5a47f83750e7acb4369ef8e830ee0eb0ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Obernd=C3=B6rfer?= Date: Thu, 7 Mar 2019 11:53:27 +0100 Subject: [PATCH] Fix issues with keys that have a creation date that is in the future. --- package-lock.json | 7 +++---- package.json | 2 +- src/app/middleware.js | 2 +- src/email/email.js | 8 ++++++-- src/service/pgp.js | 15 ++++++++------- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5d10213..1c61cb3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mailvelope-keyserver", - "version": "2.0.0", + "version": "3.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1619,9 +1619,8 @@ "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" }, "openpgp": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-4.4.9.tgz", - "integrity": "sha512-GpPRBJ/bmRtVIzM4XyZFNWueo4X7NmbeFz6/PyjolPLj2/n2XgKDaNSgR3KTjjuAoJJrbjLFAeARa+4G0mz6Ig==", + "version": "github:mailvelope/openpgpjs#a9d95ef7f0b640149f0a6d5d53b06389dc82d803", + "from": "github:mailvelope/openpgpjs#fix_user_verify_dist", "requires": { "@mattiasbuelens/web-streams-polyfill": "^0.3.1", "address-rfc2822": "^2.0.3", diff --git a/package.json b/package.json index 81818fe..a04b56a 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "koa-static": "5.0.0", "mongodb": "3.1.13", "nodemailer": "5.1.1", - "openpgp": "4.4.9", + "openpgp": "github:mailvelope/openpgpjs#fix_user_verify_dist", "winston": "3.2.1", "winston-papertrail": "1.0.5" }, diff --git a/src/app/middleware.js b/src/app/middleware.js index ddf8057..622ec71 100644 --- a/src/app/middleware.js +++ b/src/app/middleware.js @@ -39,7 +39,7 @@ exports.setHTTPResponseHeaders = async function(ctx, next) { ctx.set('Public-Key-Pins', `pin-sha256="${config.server.httpsKeyPin}"; pin-sha256="${config.server.httpsKeyPinBackup}"; max-age=16070400`); } // CSP - ctx.set('Content-Security-Policy', "default-src 'self'; object-src 'none'; script-src 'self' code.jquery.com; style-src 'self' stackpath.bootstrapcdn.com; font-src 'self' stackpath.bootstrapcdn.com"); + ctx.set('Content-Security-Policy', "default-src 'self'; object-src 'none'; script-src 'self' code.jquery.com; style-src 'self' stackpath.bootstrapcdn.com 'unsafe-inline'; font-src 'self' stackpath.bootstrapcdn.com"); // Prevent rendering website in foreign iframe (Clickjacking) ctx.set('X-Frame-Options', 'DENY'); // CORS diff --git a/src/email/email.js b/src/email/email.js index c932323..13d2dbf 100644 --- a/src/email/email.js +++ b/src/email/email.js @@ -82,13 +82,17 @@ class Email { * @return {string} the encrypted PGP message block */ async _pgpEncrypt(plaintext, publicKeyArmored) { - const {keys, err} = await openpgp.key.readArmored(publicKeyArmored); + const {keys : [key], err} = await openpgp.key.readArmored(publicKeyArmored); if (err) { log.error('email', 'Reading armored key failed.', err, publicKeyArmored); } + const now = new Date(); + // set message creation date if key has been created with future creation date + const msgCreationDate = key.primaryKey.created > now ? key.primaryKey.created : now; const ciphertext = await openpgp.encrypt({ message: openpgp.message.fromText(plaintext), - publicKeys: keys, + publicKeys: key, + date: msgCreationDate }); return ciphertext.data; } diff --git a/src/service/pgp.js b/src/service/pgp.js index 3613a1a..92d32d5 100644 --- a/src/service/pgp.js +++ b/src/service/pgp.js @@ -54,10 +54,9 @@ class PGP { // verify primary key const key = r.keys[0]; const primaryKey = key.primaryKey; - if (primaryKey.created > new Date()) { - log.error('pgp', 'Key creation date is in the future', primaryKey.created); - } - if (await key.verifyPrimaryKey() !== openpgp.enums.keyStatus.valid) { + const now = new Date(); + const verifyDate = primaryKey.created > now ? primaryKey.created : now; + if (await key.verifyPrimaryKey(verifyDate) !== openpgp.enums.keyStatus.valid) { util.throw(400, 'Invalid PGP key: primary key verification failed'); } @@ -69,7 +68,7 @@ class PGP { } // check for at least one valid user id - const userIds = await this.parseUserIds(key.users, primaryKey); + const userIds = await this.parseUserIds(key.users, primaryKey, verifyDate); if (!userIds.length) { util.throw(400, 'Invalid PGP key: invalid user IDs'); } @@ -119,16 +118,18 @@ class PGP { /** * Parse an array of user ids and verify signatures * @param {Array} users A list of openpgp.js user objects + * @param {Object} primaryKey The primary key packet of the key + * @param {Date} verifyDate Verify user IDs at this point in time * @return {Array} An array of user id objects */ - async parseUserIds(users, primaryKey) { + async parseUserIds(users, primaryKey, verifyDate = new Date()) { if (!users || !users.length) { util.throw(400, 'Invalid PGP key: no user ID found'); } // at least one user id must be valid, revoked or expired const result = []; for (const user of users) { - const userStatus = await user.verify(primaryKey); + const userStatus = await user.verify(primaryKey, verifyDate); if (userStatus !== openpgp.enums.keyStatus.invalid && user.userId && user.userId.userid) { const uid = addressparser(user.userId.userid)[0]; if (util.isEmail(uid.address)) {