Deduplicate getPreferredSymAlgo / getPreferredAEADAlgo
This commit is contained in:
parent
4568d080d5
commit
0376f49e01
57
src/key.js
57
src/key.js
|
@ -1436,31 +1436,34 @@ export async function getPreferredHashAlgo(key, date) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the preferred symmetric algorithm for a set of keys
|
* Returns the preferred symmetric/aead algorithm for a set of keys
|
||||||
|
* @param {symmetric|aead} type Type of preference to return
|
||||||
* @param {Array<module:key.Key>} keys Set of keys
|
* @param {Array<module:key.Key>} keys Set of keys
|
||||||
* @param {Date} date (optional) use the given date for verification instead of the current time
|
* @param {Date} date (optional) use the given date for verification instead of the current time
|
||||||
* @returns {Promise<module:enums.symmetric>} Preferred symmetric algorithm
|
* @returns {Promise<module:enums.symmetric>} Preferred symmetric algorithm
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
export async function getPreferredSymAlgo(keys, date) {
|
export async function getPreferredAlgo(type, keys, date) {
|
||||||
|
const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms';
|
||||||
|
const defaultAlgo = type === 'symmetric' ? config.encryption_cipher : config.aead_mode;
|
||||||
const prioMap = {};
|
const prioMap = {};
|
||||||
await Promise.all(keys.map(async function(key) {
|
await Promise.all(keys.map(async function(key) {
|
||||||
const primaryUser = await key.getPrimaryUser(date);
|
const primaryUser = await key.getPrimaryUser(date);
|
||||||
if (!primaryUser || !primaryUser.selfCertification.preferredSymmetricAlgorithms) {
|
if (!primaryUser || !primaryUser.selfCertification[prefProperty]) {
|
||||||
return config.encryption_cipher;
|
return defaultAlgo;
|
||||||
}
|
}
|
||||||
primaryUser.selfCertification.preferredSymmetricAlgorithms.forEach(function(algo, index) {
|
primaryUser.selfCertification[prefProperty].forEach(function(algo, index) {
|
||||||
const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo });
|
const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo });
|
||||||
entry.prio += 64 >> index;
|
entry.prio += 64 >> index;
|
||||||
entry.count++;
|
entry.count++;
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
let prefAlgo = { prio: 0, algo: config.encryption_cipher };
|
let prefAlgo = { prio: 0, algo: defaultAlgo };
|
||||||
for (const algo in prioMap) {
|
for (const algo in prioMap) {
|
||||||
try {
|
try {
|
||||||
if (algo !== enums.symmetric.plaintext &&
|
if (algo !== enums[type].plaintext &&
|
||||||
algo !== enums.symmetric.idea && // not implemented
|
algo !== enums[type].idea && // not implemented
|
||||||
enums.read(enums.symmetric, algo) && // known algorithm
|
enums.read(enums[type], algo) && // known algorithm
|
||||||
prioMap[algo].count === keys.length && // available for all keys
|
prioMap[algo].count === keys.length && // available for all keys
|
||||||
prioMap[algo].prio > prefAlgo.prio) {
|
prioMap[algo].prio > prefAlgo.prio) {
|
||||||
prefAlgo = prioMap[algo];
|
prefAlgo = prioMap[algo];
|
||||||
|
@ -1471,43 +1474,21 @@ export async function getPreferredSymAlgo(keys, date) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the preferred aead algorithm for a set of keys
|
* Returns whether aead is supported by all keys in the set
|
||||||
* @param {Array<module:key.Key>} keys Set of keys
|
* @param {Array<module:key.Key>} keys Set of keys
|
||||||
* @param {Date} date (optional) use the given date for verification instead of the current time
|
* @param {Date} date (optional) use the given date for verification instead of the current time
|
||||||
* @returns {Promise<module:enums.aead>} Preferred aead algorithm, or null if the public keys do not support aead
|
* @returns {Promise<Boolean>}
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
export async function getPreferredAeadAlgo(keys, date) {
|
export async function isAeadSupported(keys, date) {
|
||||||
let supports_aead = true;
|
let supported = true;
|
||||||
const prioMap = {};
|
// TODO replace when Promise.some or Promise.any are implemented
|
||||||
await Promise.all(keys.map(async function(key) {
|
await Promise.all(keys.map(async function(key) {
|
||||||
const primaryUser = await key.getPrimaryUser(date);
|
const primaryUser = await key.getPrimaryUser(date);
|
||||||
if (!primaryUser || !primaryUser.selfCertification.features ||
|
if (!primaryUser || !primaryUser.selfCertification.features ||
|
||||||
!(primaryUser.selfCertification.features[0] & enums.features.aead)) {
|
!(primaryUser.selfCertification.features[0] & enums.features.aead)) {
|
||||||
supports_aead = false;
|
supported = false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!primaryUser || !primaryUser.selfCertification.preferredAeadAlgorithms) {
|
|
||||||
return config.aead_mode;
|
|
||||||
}
|
|
||||||
primaryUser.selfCertification.preferredAeadAlgorithms.forEach(function(algo, index) {
|
|
||||||
const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo });
|
|
||||||
entry.prio += 64 >> index;
|
|
||||||
entry.count++;
|
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
if (!supports_aead) {
|
return supported;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let prefAlgo = { prio: 0, algo: config.aead_mode };
|
|
||||||
for (const algo in prioMap) {
|
|
||||||
try {
|
|
||||||
if (enums.read(enums.aead, algo) && // known algorithm
|
|
||||||
prioMap[algo].count === keys.length && // available for all keys
|
|
||||||
prioMap[algo].prio > prefAlgo.prio) {
|
|
||||||
prefAlgo = prioMap[algo];
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
return prefAlgo.algo;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ import enums from './enums';
|
||||||
import util from './util';
|
import util from './util';
|
||||||
import packet from './packet';
|
import packet from './packet';
|
||||||
import { Signature } from './signature';
|
import { Signature } from './signature';
|
||||||
import { getPreferredHashAlgo, getPreferredSymAlgo, getPreferredAeadAlgo } from './key';
|
import { getPreferredHashAlgo, getPreferredAlgo, isAeadSupported } from './key';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,10 +263,9 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
|
||||||
aeadAlgo = sessionKey.aeadAlgorithm;
|
aeadAlgo = sessionKey.aeadAlgorithm;
|
||||||
sessionKey = sessionKey.data;
|
sessionKey = sessionKey.data;
|
||||||
} else if (keys && keys.length) {
|
} else if (keys && keys.length) {
|
||||||
symAlgo = enums.read(enums.symmetric, await getPreferredSymAlgo(keys, date));
|
symAlgo = enums.read(enums.symmetric, await getPreferredAlgo('symmetric', keys, date));
|
||||||
aeadAlgo = await getPreferredAeadAlgo(keys, date);
|
if (config.aead_protect && config.aead_protect_version === 4 && await isAeadSupported(keys, date)) {
|
||||||
if (aeadAlgo) {
|
aeadAlgo = enums.read(enums.aead, await getPreferredAlgo('aead', keys, date));
|
||||||
aeadAlgo = enums.read(enums.aead, aeadAlgo);
|
|
||||||
}
|
}
|
||||||
} else if (passwords && passwords.length) {
|
} else if (passwords && passwords.length) {
|
||||||
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
|
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
|
||||||
|
|
|
@ -1170,42 +1170,44 @@ p92yZgB3r2+f6/GIe2+7
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('getPreferredSymAlgo() - one key - AES256', async function() {
|
it("getPreferredAlgo('symmetric') - one key - AES256", async function() {
|
||||||
const key1 = openpgp.key.readArmored(twoKeys).keys[0];
|
const key1 = openpgp.key.readArmored(twoKeys).keys[0];
|
||||||
const prefAlgo = await openpgp.key.getPreferredSymAlgo([key1]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('symmetric', [key1]);
|
||||||
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes256);
|
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes256);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('getPreferredSymAlgo() - two key - AES128', async function() {
|
it("getPreferredAlgo('symmetric') - two key - AES128", async function() {
|
||||||
const keys = openpgp.key.readArmored(twoKeys).keys;
|
const keys = openpgp.key.readArmored(twoKeys).keys;
|
||||||
const key1 = keys[0];
|
const key1 = keys[0];
|
||||||
const key2 = keys[1];
|
const key2 = keys[1];
|
||||||
const primaryUser = await key2.getPrimaryUser();
|
const primaryUser = await key2.getPrimaryUser();
|
||||||
primaryUser.selfCertification.preferredSymmetricAlgorithms = [6,7,3];
|
primaryUser.selfCertification.preferredSymmetricAlgorithms = [6,7,3];
|
||||||
const prefAlgo = await openpgp.key.getPreferredSymAlgo([key1, key2]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('symmetric', [key1, key2]);
|
||||||
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes128);
|
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes128);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('getPreferredSymAlgo() - two key - one without pref', async function() {
|
it("getPreferredAlgo('symmetric') - two key - one without pref", async function() {
|
||||||
const keys = openpgp.key.readArmored(twoKeys).keys;
|
const keys = openpgp.key.readArmored(twoKeys).keys;
|
||||||
const key1 = keys[0];
|
const key1 = keys[0];
|
||||||
const key2 = keys[1];
|
const key2 = keys[1];
|
||||||
const primaryUser = await key2.getPrimaryUser();
|
const primaryUser = await key2.getPrimaryUser();
|
||||||
primaryUser.selfCertification.preferredSymmetricAlgorithms = null;
|
primaryUser.selfCertification.preferredSymmetricAlgorithms = null;
|
||||||
const prefAlgo = await openpgp.key.getPreferredSymAlgo([key1, key2]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('symmetric', [key1, key2]);
|
||||||
expect(prefAlgo).to.equal(openpgp.config.encryption_cipher);
|
expect(prefAlgo).to.equal(openpgp.config.encryption_cipher);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('getPreferredAeadAlgo() - one key - OCB', async function() {
|
it("getPreferredAlgo('aead') - one key - OCB", async function() {
|
||||||
const key1 = openpgp.key.readArmored(twoKeys).keys[0];
|
const key1 = openpgp.key.readArmored(twoKeys).keys[0];
|
||||||
const primaryUser = await key1.getPrimaryUser();
|
const primaryUser = await key1.getPrimaryUser();
|
||||||
primaryUser.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
primaryUser.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
||||||
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
||||||
const prefAlgo = await openpgp.key.getPreferredAeadAlgo([key1]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('aead', [key1]);
|
||||||
expect(prefAlgo).to.equal(openpgp.enums.aead.ocb);
|
expect(prefAlgo).to.equal(openpgp.enums.aead.ocb);
|
||||||
|
const supported = await openpgp.key.isAeadSupported([key1]);
|
||||||
|
expect(supported).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('getPreferredAeadAlgo() - two key - one without pref', async function() {
|
it("getPreferredAlgo('aead') - two key - one without pref", async function() {
|
||||||
const keys = openpgp.key.readArmored(twoKeys).keys;
|
const keys = openpgp.key.readArmored(twoKeys).keys;
|
||||||
const key1 = keys[0];
|
const key1 = keys[0];
|
||||||
const key2 = keys[1];
|
const key2 = keys[1];
|
||||||
|
@ -1214,19 +1216,23 @@ p92yZgB3r2+f6/GIe2+7
|
||||||
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
||||||
const primaryUser2 = await key2.getPrimaryUser();
|
const primaryUser2 = await key2.getPrimaryUser();
|
||||||
primaryUser2.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
primaryUser2.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
||||||
const prefAlgo = await openpgp.key.getPreferredAeadAlgo([key1, key2]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('aead', [key1, key2]);
|
||||||
expect(prefAlgo).to.equal(openpgp.config.aead_mode);
|
expect(prefAlgo).to.equal(openpgp.config.aead_mode);
|
||||||
|
const supported = await openpgp.key.isAeadSupported([key1, key2]);
|
||||||
|
expect(supported).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('getPreferredAeadAlgo() - two key - one with no support', async function() {
|
it("getPreferredAlgo('aead') - two key - one with no support", async function() {
|
||||||
const keys = openpgp.key.readArmored(twoKeys).keys;
|
const keys = openpgp.key.readArmored(twoKeys).keys;
|
||||||
const key1 = keys[0];
|
const key1 = keys[0];
|
||||||
const key2 = keys[1];
|
const key2 = keys[1];
|
||||||
const primaryUser = await key1.getPrimaryUser();
|
const primaryUser = await key1.getPrimaryUser();
|
||||||
primaryUser.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
primaryUser.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
||||||
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
||||||
const prefAlgo = await openpgp.key.getPreferredAeadAlgo([key1, key2]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('aead', [key1, key2]);
|
||||||
expect(prefAlgo).to.be.null;
|
expect(prefAlgo).to.equal(openpgp.config.aead_mode);
|
||||||
|
const supported = await openpgp.key.isAeadSupported([key1, key2]);
|
||||||
|
expect(supported).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Preferences of generated key', function() {
|
it('Preferences of generated key', function() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user