Reject messages encrypted with a symmetric algo not in preferred algos
This commit is contained in:
parent
cb3f644708
commit
3b9676f2e9
|
@ -153,6 +153,7 @@ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys,
|
||||||
Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
||||||
let keyPackets = [];
|
let keyPackets = [];
|
||||||
|
|
||||||
|
let exception;
|
||||||
if (passwords) {
|
if (passwords) {
|
||||||
const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey);
|
const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey);
|
||||||
if (!symESKeyPacketlist) {
|
if (!symESKeyPacketlist) {
|
||||||
|
@ -181,10 +182,18 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
||||||
throw new Error('No public key encrypted session key packet found.');
|
throw new Error('No public key encrypted session key packet found.');
|
||||||
}
|
}
|
||||||
await Promise.all(pkESKeyPacketlist.map(async function(keyPacket) {
|
await Promise.all(pkESKeyPacketlist.map(async function(keyPacket) {
|
||||||
const privateKeyPackets = new packet.List();
|
await Promise.all(privateKeys.map(async function(privateKey) {
|
||||||
privateKeys.forEach(privateKey => {
|
const primaryUser = await privateKey.getPrimaryUser(); // TODO: Pass userId from somewhere.
|
||||||
privateKeyPackets.concat(privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket));
|
let algos = [
|
||||||
});
|
enums.symmetric.aes256, // Old OpenPGP.js default fallback
|
||||||
|
enums.symmetric.aes128, // RFC4880bis fallback
|
||||||
|
enums.symmetric.tripledes // RFC4880 fallback
|
||||||
|
];
|
||||||
|
if (primaryUser && primaryUser.selfCertification.preferredSymmetricAlgorithms) {
|
||||||
|
algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms);
|
||||||
|
}
|
||||||
|
|
||||||
|
const privateKeyPackets = privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket);
|
||||||
await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) {
|
await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) {
|
||||||
if (!privateKeyPacket) {
|
if (!privateKeyPacket) {
|
||||||
return;
|
return;
|
||||||
|
@ -194,11 +203,16 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await keyPacket.decrypt(privateKeyPacket);
|
await keyPacket.decrypt(privateKeyPacket);
|
||||||
|
if (!algos.includes(enums.write(enums.symmetric, keyPacket.sessionKeyAlgorithm))) {
|
||||||
|
throw new Error('A non-preferred symmetric algorithm was used.');
|
||||||
|
}
|
||||||
keyPackets.push(keyPacket);
|
keyPackets.push(keyPacket);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
util.print_debug_error(err);
|
util.print_debug_error(err);
|
||||||
|
exception = err;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
}));
|
||||||
stream.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory.
|
stream.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory.
|
||||||
keyPacket.encrypted = null;
|
keyPacket.encrypted = null;
|
||||||
}));
|
}));
|
||||||
|
@ -222,7 +236,7 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
||||||
|
|
||||||
return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm }));
|
return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm }));
|
||||||
}
|
}
|
||||||
throw new Error('Session key decryption failed.');
|
throw exception || new Error('Session key decryption failed.');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,4 +2,5 @@ describe('Security', function () {
|
||||||
require('./message_signature_bypass');
|
require('./message_signature_bypass');
|
||||||
require('./unsigned_subpackets');
|
require('./unsigned_subpackets');
|
||||||
require('./subkey_trust');
|
require('./subkey_trust');
|
||||||
|
require('./preferred_algo_mismatch');
|
||||||
});
|
});
|
||||||
|
|
49
test/security/preferred_algo_mismatch.js
Normal file
49
test/security/preferred_algo_mismatch.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../../dist/openpgp');
|
||||||
|
|
||||||
|
const { key, cleartext, enums, packet: { List, Signature } } = openpgp;
|
||||||
|
|
||||||
|
const chai = require('chai');
|
||||||
|
chai.use(require('chai-as-promised'));
|
||||||
|
|
||||||
|
const expect = chai.expect;
|
||||||
|
|
||||||
|
const messageArmor = `-----BEGIN PGP MESSAGE-----
|
||||||
|
Version: OpenPGP.js VERSION
|
||||||
|
Comment: https://openpgpjs.org
|
||||||
|
|
||||||
|
wYwD3eCUoDfD5yoBA/4rhxaaw+E2ma+LdmLVDBRqxglhIgnM6EgNxzf8J5Ty
|
||||||
|
ecQBLOf3BjjC72mJ9RqMmvQ16aG4EXXDAUmCP1sBLj+b7V1t4keeyTn+2nXu
|
||||||
|
7Wgu2yq9CvZahRLsayt3y8VodZwTi3K/+gmx1f8EhdLPONQgGkYAqZ3Tyyd0
|
||||||
|
KF3pknplvdI+AXqRs0n2vVr89oIdmQPJFSHEoJtltbSNxhwShdzDvOor2FKJ
|
||||||
|
vhGWNysion2aBg0fIbgDUKeXKp8YN44LDTk=
|
||||||
|
=RYrv
|
||||||
|
-----END PGP MESSAGE-----`;
|
||||||
|
|
||||||
|
const privateKeyArmor = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
Version: OpenPGP.js VERSION
|
||||||
|
Comment: https://openpgpjs.org
|
||||||
|
|
||||||
|
xcEYBFvbA08BBACl8U5VEY7TNq1PAzwU0f3soqNfFpKtNFt+LY3q5sasouJ7
|
||||||
|
zE4/TPYrAaAoM5/yOjfvbfJP5myBUCtkdtIRIY2iP2uOPhfaly8U+zH25Qnq
|
||||||
|
bmgLfvu4ytPAPrKZF8f98cIeJmHD81SPRgDMuB2U9wwgN6stgVBBCUS+lu/L
|
||||||
|
/4pyuwARAQABAAP+Jz6BIvcrCuJ0bCo8rEPZRHxWHKfO+m1Wcem+FV6Mf8lp
|
||||||
|
vJNdsfS2hwc0ZC2JVxTTo6kh1CmPYamfCXxcQ7bmsqWkkq/6d17zKE6BqE/n
|
||||||
|
spW7qTnZ14VPC0iPrBetAWRlCk+m0cEkRnBxqPOVBNd6VPcZyM7GUOGf/kiw
|
||||||
|
AsHf+nECANkN1tsqLJ3+pH2MRouF7yHevQ9OGg+rwetBO2a8avvcsAuoFjVw
|
||||||
|
hERpkHv/PQjKAE7KcBzqLLad0QbrQW+sUcMCAMO3to0tSBJrNA9YkrViT76I
|
||||||
|
siiahSB/FC9JlO+T46xncRleZeBHc0zoVAP+W/PjRo2CR4ydtwjjalrxcKX9
|
||||||
|
E6kCALfDyhkRNzZLxg2XOGDWyeXqe80VWnMBqTZK73nZlACRcUoXuvjRc15Q
|
||||||
|
K2c3/nZ7LMyQidj8XsTq4sz1zfWz4Cejj80cVGVzdCBVc2VyIDx0ZXN0QGV4
|
||||||
|
YW1wbGUuY29tPsK1BBABCAApBQJb2wNPAgsJCRDd4JSgN8PnKgQVCAoCAxYC
|
||||||
|
AQIZAQIbDwIeBwMiAQIAABGjA/4y6HjthMU03AC3bIUyYPv6EJc9czS5wysa
|
||||||
|
5rKuNhzka0Klb0INcX1YZ8usPIIl1rtr8f8xxCdSiqhJpn+uqIPVROHi0XLG
|
||||||
|
ej3gSJM5i1lIt1jxyJlvVI/7W0vzuE85KDzGXQFNFyO/T9D7T1SDHnS8KbBh
|
||||||
|
EnxUPL95HuMKoVkf4w==
|
||||||
|
=oopr
|
||||||
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
|
it('Does not accept message encrypted with algo not mentioned in preferred algorithms', async function() {
|
||||||
|
const message = await openpgp.message.readArmored(messageArmor);
|
||||||
|
const privKey = (await openpgp.key.readArmored(privateKeyArmor)).keys[0];
|
||||||
|
await expect(openpgp.decrypt({ message, privateKeys: [privKey] })).to.be.rejectedWith('A non-preferred symmetric algorithm was used.');
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user