Fix issues with keys that have a creation date that is in the future.
This commit is contained in:
parent
1fcf791560
commit
9159bd5a47
7
package-lock.json
generated
7
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mailvelope-keyserver",
|
"name": "mailvelope-keyserver",
|
||||||
"version": "2.0.0",
|
"version": "3.0.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -1619,9 +1619,8 @@
|
|||||||
"integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
|
"integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
|
||||||
},
|
},
|
||||||
"openpgp": {
|
"openpgp": {
|
||||||
"version": "4.4.9",
|
"version": "github:mailvelope/openpgpjs#a9d95ef7f0b640149f0a6d5d53b06389dc82d803",
|
||||||
"resolved": "https://registry.npmjs.org/openpgp/-/openpgp-4.4.9.tgz",
|
"from": "github:mailvelope/openpgpjs#fix_user_verify_dist",
|
||||||
"integrity": "sha512-GpPRBJ/bmRtVIzM4XyZFNWueo4X7NmbeFz6/PyjolPLj2/n2XgKDaNSgR3KTjjuAoJJrbjLFAeARa+4G0mz6Ig==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@mattiasbuelens/web-streams-polyfill": "^0.3.1",
|
"@mattiasbuelens/web-streams-polyfill": "^0.3.1",
|
||||||
"address-rfc2822": "^2.0.3",
|
"address-rfc2822": "^2.0.3",
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
"koa-static": "5.0.0",
|
"koa-static": "5.0.0",
|
||||||
"mongodb": "3.1.13",
|
"mongodb": "3.1.13",
|
||||||
"nodemailer": "5.1.1",
|
"nodemailer": "5.1.1",
|
||||||
"openpgp": "4.4.9",
|
"openpgp": "github:mailvelope/openpgpjs#fix_user_verify_dist",
|
||||||
"winston": "3.2.1",
|
"winston": "3.2.1",
|
||||||
"winston-papertrail": "1.0.5"
|
"winston-papertrail": "1.0.5"
|
||||||
},
|
},
|
||||||
|
@ -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`);
|
ctx.set('Public-Key-Pins', `pin-sha256="${config.server.httpsKeyPin}"; pin-sha256="${config.server.httpsKeyPinBackup}"; max-age=16070400`);
|
||||||
}
|
}
|
||||||
// CSP
|
// 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)
|
// Prevent rendering website in foreign iframe (Clickjacking)
|
||||||
ctx.set('X-Frame-Options', 'DENY');
|
ctx.set('X-Frame-Options', 'DENY');
|
||||||
// CORS
|
// CORS
|
||||||
|
@ -82,13 +82,17 @@ class Email {
|
|||||||
* @return {string} the encrypted PGP message block
|
* @return {string} the encrypted PGP message block
|
||||||
*/
|
*/
|
||||||
async _pgpEncrypt(plaintext, publicKeyArmored) {
|
async _pgpEncrypt(plaintext, publicKeyArmored) {
|
||||||
const {keys, err} = await openpgp.key.readArmored(publicKeyArmored);
|
const {keys : [key], err} = await openpgp.key.readArmored(publicKeyArmored);
|
||||||
if (err) {
|
if (err) {
|
||||||
log.error('email', 'Reading armored key failed.', err, publicKeyArmored);
|
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({
|
const ciphertext = await openpgp.encrypt({
|
||||||
message: openpgp.message.fromText(plaintext),
|
message: openpgp.message.fromText(plaintext),
|
||||||
publicKeys: keys,
|
publicKeys: key,
|
||||||
|
date: msgCreationDate
|
||||||
});
|
});
|
||||||
return ciphertext.data;
|
return ciphertext.data;
|
||||||
}
|
}
|
||||||
|
@ -54,10 +54,9 @@ class PGP {
|
|||||||
// verify primary key
|
// verify primary key
|
||||||
const key = r.keys[0];
|
const key = r.keys[0];
|
||||||
const primaryKey = key.primaryKey;
|
const primaryKey = key.primaryKey;
|
||||||
if (primaryKey.created > new Date()) {
|
const now = new Date();
|
||||||
log.error('pgp', 'Key creation date is in the future', primaryKey.created);
|
const verifyDate = primaryKey.created > now ? primaryKey.created : now;
|
||||||
}
|
if (await key.verifyPrimaryKey(verifyDate) !== openpgp.enums.keyStatus.valid) {
|
||||||
if (await key.verifyPrimaryKey() !== openpgp.enums.keyStatus.valid) {
|
|
||||||
util.throw(400, 'Invalid PGP key: primary key verification failed');
|
util.throw(400, 'Invalid PGP key: primary key verification failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +68,7 @@ class PGP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for at least one valid user id
|
// 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) {
|
if (!userIds.length) {
|
||||||
util.throw(400, 'Invalid PGP key: invalid user IDs');
|
util.throw(400, 'Invalid PGP key: invalid user IDs');
|
||||||
}
|
}
|
||||||
@ -119,16 +118,18 @@ class PGP {
|
|||||||
/**
|
/**
|
||||||
* Parse an array of user ids and verify signatures
|
* Parse an array of user ids and verify signatures
|
||||||
* @param {Array} users A list of openpgp.js user objects
|
* @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
|
* @return {Array} An array of user id objects
|
||||||
*/
|
*/
|
||||||
async parseUserIds(users, primaryKey) {
|
async parseUserIds(users, primaryKey, verifyDate = new Date()) {
|
||||||
if (!users || !users.length) {
|
if (!users || !users.length) {
|
||||||
util.throw(400, 'Invalid PGP key: no user ID found');
|
util.throw(400, 'Invalid PGP key: no user ID found');
|
||||||
}
|
}
|
||||||
// at least one user id must be valid, revoked or expired
|
// at least one user id must be valid, revoked or expired
|
||||||
const result = [];
|
const result = [];
|
||||||
for (const user of users) {
|
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) {
|
if (userStatus !== openpgp.enums.keyStatus.invalid && user.userId && user.userId.userid) {
|
||||||
const uid = addressparser(user.userId.userid)[0];
|
const uid = addressparser(user.userId.userid)[0];
|
||||||
if (util.isEmail(uid.address)) {
|
if (util.isEmail(uid.address)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user