Merge pull request #816 from twiss/security-fixes

Security fixes
This commit is contained in:
Daniel Huigens 2018-12-17 18:55:30 +01:00 committed by GitHub
commit b1b19946d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 233 additions and 91 deletions

View File

@ -181,7 +181,7 @@ export default {
cipherfn = new cipher[cipherfn](key);
const block_size = cipherfn.blockSize;
let iblock = new Uint8Array(block_size);
const iblock = new Uint8Array(block_size);
let ablock = new Uint8Array(block_size);
let i;
@ -189,30 +189,10 @@ export default {
let n;
let text = new Uint8Array(ciphertext.length - block_size);
// initialisation vector
for (i = 0; i < block_size; i++) {
iblock[i] = 0;
}
iblock = cipherfn.encrypt(iblock);
for (i = 0; i < block_size; i++) {
ablock[i] = ciphertext[i];
iblock[i] ^= ablock[i];
}
ablock = cipherfn.encrypt(ablock);
// test check octets
if (iblock[block_size - 2] !== (ablock[0] ^ ciphertext[block_size]) ||
iblock[block_size - 1] !== (ablock[1] ^ ciphertext[block_size + 1])) {
throw new Error('CFB decrypt: invalid key');
}
/* RFC4880: Tag 18 and Resync:
* [...] Unlike the Symmetrically Encrypted Data Packet, no
* special CFB resynchronization is done after encrypting this prefix
* data. See "OpenPGP CFB Mode" below for more details.
*/
j = 0;

View File

@ -48,7 +48,7 @@ function rightXorMut(data, padding) {
function pad(data, padding, padding2) {
// if |M| in {n, 2n, 3n, ...}
if (data.length % blockLength === 0) {
if (data.length && data.length % blockLength === 0) {
// then return M xor→ B,
return rightXorMut(data, padding);
}

View File

@ -177,7 +177,14 @@ Curve.prototype.keyFromSecret = function (secret) { // Only for ed25519
};
Curve.prototype.keyFromPublic = function (pub) {
return new KeyPair(this, { pub: pub });
const keyPair = new KeyPair(this, { pub: pub });
if (
this.keyType === enums.publicKey.ecdsa &&
keyPair.keyPair.validate().result !== true
) {
throw new Error('Invalid elliptic public key');
}
return keyPair;
};
Curve.prototype.genKeyPair = async function () {

View File

@ -1451,6 +1451,19 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
packetlist.push(secretKeyPacket);
await Promise.all(options.userIds.map(async function(userId, index) {
function createdPreferredAlgos(algos, configAlgo) {
if (configAlgo) { // Not `uncompressed` / `plaintext`
const configIndex = algos.indexOf(configAlgo);
if (configIndex >= 1) { // If it is included and not in first place,
algos.splice(configIndex, 1); // remove it.
}
if (configIndex !== 0) { // If it was included and not in first place, or wasn't included,
algos.unshift(configAlgo); // add it to the front.
}
}
return algos;
}
const userIdPacket = new packet.Userid();
userIdPacket.format(userId);
@ -1462,26 +1475,30 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm;
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretKeyPacket);
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
signaturePacket.preferredSymmetricAlgorithms = [];
// prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support)
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes256);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes128);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes192);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.cast5);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.tripledes);
signaturePacket.preferredSymmetricAlgorithms = createdPreferredAlgos([
// prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support)
enums.symmetric.aes256,
enums.symmetric.aes128,
enums.symmetric.aes192,
enums.symmetric.cast5,
enums.symmetric.tripledes
], config.encryption_cipher);
if (config.aead_protect && config.aead_protect_version === 4) {
signaturePacket.preferredAeadAlgorithms = [];
signaturePacket.preferredAeadAlgorithms.push(enums.aead.eax);
signaturePacket.preferredAeadAlgorithms.push(enums.aead.ocb);
signaturePacket.preferredAeadAlgorithms = createdPreferredAlgos([
enums.aead.eax,
enums.aead.ocb
], config.aead_mode);
}
signaturePacket.preferredHashAlgorithms = [];
// prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha256);
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha512);
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha1);
signaturePacket.preferredCompressionAlgorithms = [];
signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zlib);
signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zip);
signaturePacket.preferredHashAlgorithms = createdPreferredAlgos([
// prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list
enums.hash.sha256,
enums.hash.sha512,
enums.hash.sha1
], config.prefer_hash_algorithm);
signaturePacket.preferredCompressionAlgorithms = createdPreferredAlgos([
enums.compression.zlib,
enums.compression.zip
], config.compression);
if (index === 0) {
signaturePacket.isPrimaryUserID = true;
}
@ -1690,7 +1707,7 @@ export async function getPreferredHashAlgo(key, keyPacket, date=new Date(), user
*/
export async function getPreferredAlgo(type, keys, date=new Date(), userId={}) {
const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms';
const defaultAlgo = type === 'symmetric' ? config.encryption_cipher : config.aead_mode;
const defaultAlgo = type === 'symmetric' ? enums.symmetric.aes128 : enums.aead.eax;
const prioMap = {};
await Promise.all(keys.map(async function(key) {
const primaryUser = await key.getPrimaryUser(date, userId);

View File

@ -153,6 +153,7 @@ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys,
Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
let keyPackets = [];
let exception;
if (passwords) {
const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey);
if (!symESKeyPacketlist) {
@ -181,23 +182,36 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
throw new Error('No public key encrypted session key packet found.');
}
await Promise.all(pkESKeyPacketlist.map(async function(keyPacket) {
const privateKeyPackets = new packet.List();
privateKeys.forEach(privateKey => {
privateKeyPackets.concat(privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket));
});
await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) {
if (!privateKeyPacket) {
return;
}
if (!privateKeyPacket.isDecrypted()) {
throw new Error('Private key is not decrypted.');
}
try {
await keyPacket.decrypt(privateKeyPacket);
keyPackets.push(keyPacket);
} catch (err) {
util.print_debug_error(err);
await Promise.all(privateKeys.map(async function(privateKey) {
const primaryUser = await privateKey.getPrimaryUser(); // TODO: Pass userId from somewhere.
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) {
if (!privateKeyPacket) {
return;
}
if (!privateKeyPacket.isDecrypted()) {
throw new Error('Private key is not decrypted.');
}
try {
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);
} catch (err) {
util.print_debug_error(err);
exception = err;
}
}));
}));
stream.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory.
keyPacket.encrypted = null;
@ -222,7 +236,7 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
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.');
};
/**
@ -230,7 +244,8 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
* @returns {(Uint8Array|null)} literal body of the message as Uint8Array
*/
Message.prototype.getLiteralData = function() {
const literal = this.packets.findPacket(enums.packet.literal);
const msg = this.unwrapCompressed();
const literal = msg.packets.findPacket(enums.packet.literal);
return (literal && literal.getBytes()) || null;
};
@ -239,7 +254,8 @@ Message.prototype.getLiteralData = function() {
* @returns {(String|null)} filename of literal data packet as string
*/
Message.prototype.getFilename = function() {
const literal = this.packets.findPacket(enums.packet.literal);
const msg = this.unwrapCompressed();
const literal = msg.packets.findPacket(enums.packet.literal);
return (literal && literal.getFilename()) || null;
};
@ -248,7 +264,8 @@ Message.prototype.getFilename = function() {
* @returns {(String|null)} literal body of the message interpreted as text
*/
Message.prototype.getText = function() {
const literal = this.packets.findPacket(enums.packet.literal);
const msg = this.unwrapCompressed();
const literal = msg.packets.findPacket(enums.packet.literal);
if (literal) {
return literal.getText();
}

View File

@ -168,24 +168,10 @@ List.prototype.filterByTag = function (...args) {
/**
* Traverses packet tree and returns first matching packet
* @param {module:enums.packet} type The packet type
* @returns {module:packet/packet|null}
* @returns {module:packet/packet|undefined}
*/
List.prototype.findPacket = function (type) {
const packetlist = this.filterByTag(type);
if (packetlist.length) {
return packetlist[0];
}
let found = null;
for (let i = 0; i < this.length; i++) {
if (this[i].packets.length) {
found = this[i].packets.findPacket(type);
if (found) {
return found;
}
}
}
return null;
return this.find(packet => packet.tag === type);
};
/**

View File

@ -62,6 +62,11 @@ function PublicKey(date=new Date()) {
* @type {Date}
*/
this.created = util.normalizeDate(date);
/**
* Public key algorithm.
* @type {String}
*/
this.algorithm = null;
/**
* Algorithm specific params
* @type {Array<Object>}

View File

@ -52,7 +52,10 @@ function PublicKeyEncryptedSessionKey() {
this.version = 3;
this.publicKeyId = new type_keyid();
this.publicKeyAlgorithm = null;
this.sessionKey = null;
this.sessionKeyAlgorithm = null;
/** @type {Array<module:type/mpi>} */
this.encrypted = [];
@ -150,7 +153,7 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) {
key = util.str_to_Uint8Array(decoded.substring(1, decoded.length - 2));
if (!util.equalsUint8Array(checksum, util.write_checksum(key))) {
throw new Error('Checksum mismatch');
throw new Error('Decryption error');
} else {
this.sessionKey = key;
this.sessionKeyAlgorithm = enums.read(enums.symmetric, decoded.charCodeAt(0));

View File

@ -666,6 +666,10 @@ Signature.prototype.verify = async function (key, signatureType, data) {
const publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm);
const hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm);
if (publicKeyAlgorithm !== enums.write(enums.publicKey, key.algorithm)) {
throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.');
}
let toHash;
let hash;
if (this.hashed) {

View File

@ -223,7 +223,17 @@ describe('Elliptic Curve Cryptography', async function () {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]);
const secp256k1_dummy_point = new Uint8Array([
const secp256k1_point = new Uint8Array([
0x04,
0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC,
0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07,
0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65,
0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8,
0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19,
0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8]);
const secp256k1_invalid_point = new Uint8Array([
0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -233,7 +243,7 @@ describe('Elliptic Curve Cryptography', async function () {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
const secp256k1_invalid_point = new Uint8Array([
const secp256k1_invalid_point_format = new Uint8Array([
0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -255,13 +265,18 @@ describe('Elliptic Curve Cryptography', async function () {
'secp256k1', 8, [], [], [], []
)).to.be.rejectedWith(Error, /Unknown point format/),
expect(verify_signature(
'secp256k1', 8, [], [], [], secp256k1_invalid_point
'secp256k1', 8, [], [], [], secp256k1_invalid_point_format
)).to.be.rejectedWith(Error, /Unknown point format/)
]);
});
it('Invalid point', function (done) {
expect(verify_signature(
'secp256k1', 8, [], [], [], secp256k1_invalid_point
)).to.be.rejectedWith(Error, /Invalid elliptic public key/).notify(done);
});
it('Invalid signature', function (done) {
expect(verify_signature(
'secp256k1', 8, [], [], [], secp256k1_dummy_point
'secp256k1', 8, [], [], [], secp256k1_point
)).to.eventually.be.false.notify(done);
});
@ -331,11 +346,21 @@ describe('Elliptic Curve Cryptography', async function () {
]);
const secp256k1_point = new Uint8Array([
0x04,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC,
0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07,
0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65,
0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8,
0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19,
0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8]);
const secp256k1_invalid_point = new Uint8Array([
0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
@ -354,6 +379,11 @@ describe('Elliptic Curve Cryptography', async function () {
'secp256k1', 2, 7, [], [], [], []
)).to.be.rejectedWith(Error, /Unknown point format/).notify(done);
});
it('Invalid elliptic public key', function (done) {
expect(decrypt_message(
'secp256k1', 2, 7, secp256k1_value, secp256k1_invalid_point, secp256k1_data, []
)).to.be.rejectedWith(Error, /Invalid elliptic public key/).notify(done);
});
it('Invalid key data integrity', function (done) {
expect(decrypt_message(
'secp256k1', 2, 7, secp256k1_value, secp256k1_point, secp256k1_data, []

View File

@ -1357,6 +1357,49 @@ function versionSpecificTests() {
});
});
it('Preferences of generated key - with config values', async function() {
const encryption_cipherVal = openpgp.config.encryption_cipher;
const prefer_hash_algorithmVal = openpgp.config.prefer_hash_algorithm;
const compressionVal = openpgp.config.compression;
const aead_modeVal = openpgp.config.aead_mode;
openpgp.config.encryption_cipher = openpgp.enums.symmetric.aes192;
openpgp.config.prefer_hash_algorithm = openpgp.enums.hash.sha384;
openpgp.config.compression = openpgp.enums.compression.zlib;
openpgp.config.aead_mode = openpgp.enums.aead.experimental_gcm;
const testPref = function(key) {
// key flags
const keyFlags = openpgp.enums.keyFlags;
expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.certify_keys).to.equal(keyFlags.certify_keys);
expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.sign_data).to.equal(keyFlags.sign_data);
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_communication).to.equal(keyFlags.encrypt_communication);
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage);
const sym = openpgp.enums.symmetric;
expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes192, sym.aes256, sym.aes128, sym.cast5, sym.tripledes]);
if (openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4) {
const aead = openpgp.enums.aead;
expect(key.users[0].selfCertifications[0].preferredAeadAlgorithms).to.eql([aead.experimental_gcm, aead.eax, aead.ocb]);
}
const hash = openpgp.enums.hash;
expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha384, hash.sha256, hash.sha512, hash.sha1]);
const compr = openpgp.enums.compression;
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]);
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4 ? [7] : [1]);
};
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: 'hello'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
try {
const key = await openpgp.generateKey(opt);
testPref(key.key);
testPref((await openpgp.key.readArmored(key.publicKeyArmored)).keys[0]);
} finally {
openpgp.config.encryption_cipher = encryption_cipherVal;
openpgp.config.prefer_hash_algorithm = prefer_hash_algorithmVal;
openpgp.config.compression = compressionVal;
openpgp.config.aead_mode = aead_modeVal;
}
});
it('Generated key is not unlocked by default', function() {
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: '123'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
@ -2147,14 +2190,14 @@ describe('Key', function() {
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes256);
});
it("getPreferredAlgo('symmetric') - two key - AES128", async function() {
it("getPreferredAlgo('symmetric') - two key - AES192", async function() {
const keys = (await openpgp.key.readArmored(twoKeys)).keys;
const key1 = keys[0];
const key2 = keys[1];
const primaryUser = await key2.getPrimaryUser();
primaryUser.selfCertification.preferredSymmetricAlgorithms = [6,7,3];
primaryUser.selfCertification.preferredSymmetricAlgorithms = [6,8,3];
const prefAlgo = await openpgp.key.getPreferredAlgo('symmetric', [key1, key2]);
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes128);
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes192);
});
it("getPreferredAlgo('symmetric') - two key - one without pref", async function() {
@ -2164,7 +2207,7 @@ describe('Key', function() {
const primaryUser = await key2.getPrimaryUser();
primaryUser.selfCertification.preferredSymmetricAlgorithms = null;
const prefAlgo = await openpgp.key.getPreferredAlgo('symmetric', [key1, key2]);
expect(prefAlgo).to.equal(openpgp.config.encryption_cipher);
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes128);
});
it("getPreferredAlgo('aead') - one key - OCB", async function() {
@ -2188,7 +2231,7 @@ describe('Key', function() {
const primaryUser2 = await key2.getPrimaryUser();
primaryUser2.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
const prefAlgo = await openpgp.key.getPreferredAlgo('aead', [key1, key2]);
expect(prefAlgo).to.equal(openpgp.config.aead_mode);
expect(prefAlgo).to.equal(openpgp.enums.aead.eax);
const supported = await openpgp.key.isAeadSupported([key1, key2]);
expect(supported).to.be.true;
});
@ -2201,7 +2244,7 @@ describe('Key', function() {
primaryUser.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
const prefAlgo = await openpgp.key.getPreferredAlgo('aead', [key1, key2]);
expect(prefAlgo).to.equal(openpgp.config.aead_mode);
expect(prefAlgo).to.equal(openpgp.enums.aead.eax);
const supported = await openpgp.key.isAeadSupported([key1, key2]);
expect(supported).to.be.false;
});

View File

@ -2,4 +2,5 @@ describe('Security', function () {
require('./message_signature_bypass');
require('./unsigned_subpackets');
require('./subkey_trust');
require('./preferred_algo_mismatch');
});

View 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.');
});