From 43fb58404df128c69adb46b9762edf4c1222f9bb Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Wed, 10 Mar 2021 18:06:03 +0100 Subject: [PATCH] Simplify algorithm preference selection and normalize config names (#1262) - Rename `config.compression` to `config.preferredCompressionAlgorithm` - Rename `config.encryptionCipher` to `config.preferredSymmetricAlgorithm` - Rename `config.preferHashAlgorithm` to `config.preferredHashAlgorithm` - Rename `config.aeadMode` to `config.preferredAeadAlgorithm` - When encrypting to public keys, the compression/aead/symmetric algorithm is selected by: - taking the preferred algorithm specified in config, if it is supported by all recipients - otherwise, taking the "MUST implement" algorithm specified by rfc4880bis - When encrypting to passphrases only (no public keys), the preferred algorithms from `config` are always used - EdDSA signing with a hash algorithm weaker than sha256 is explicitly disallowed (https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2) --- README.md | 24 +++++----- openpgp.d.ts | 6 +-- src/config/config.js | 14 +++--- src/crypto/public_key/elliptic/eddsa.js | 8 +++- src/key/factory.js | 29 ++++-------- src/key/helper.js | 60 ++++++++++++------------ src/message.js | 8 ++-- src/openpgp.js | 7 ++- src/packet/compressed_data.js | 2 +- src/packet/sym_encrypted_session_key.js | 2 +- test/general/config.js | 44 +++++++++--------- test/general/key.js | 61 ++++++++++++++----------- test/general/openpgp.js | 12 ++--- test/general/streaming.js | 2 +- test/general/x25519.js | 4 +- 15 files changed, 145 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index ebe3b443..9509385a 100644 --- a/README.md +++ b/README.md @@ -79,9 +79,9 @@ library to convert back and forth between them. You can change the AEAD mode by setting one of the following options: ``` - openpgp.config.aeadMode = openpgp.enums.aead.eax // Default, native - openpgp.config.aeadMode = openpgp.enums.aead.ocb // Non-native - openpgp.config.aeadMode = openpgp.enums.aead.experimentalGcm // **Non-standard**, fastest + openpgp.config.preferredAeadAlgorithm = openpgp.enums.aead.eax // Default, native + openpgp.config.preferredAeadAlgorithm = openpgp.enums.aead.ocb // Non-native + openpgp.config.preferredAeadAlgorithm = openpgp.enums.aead.experimentalGcm // **Non-standard**, fastest ``` * For environments that don't provide native crypto, the library falls back to [asm.js](https://caniuse.com/#feat=asmjs) implementations of AES, SHA-1, and SHA-256. @@ -169,7 +169,7 @@ Here are some examples of how to use OpenPGP.js v5. For more elaborate examples #### Encrypt and decrypt *Uint8Array* data with a password -Encryption will use the algorithm specified in config.encryptionCipher (defaults to aes256), and decryption will use the algorithm used for encryption. +Encryption will use the algorithm specified in config.preferredSymmetricAlgorithm (defaults to aes256), and decryption will use the algorithm used for encryption. ```js (async () => { @@ -267,11 +267,10 @@ Encrypt with multiple public keys: })(); ``` -#### Encrypt with compression +#### Encrypt symmetrically with compression -By default, `encrypt` will not use any compression. It's possible to override that behavior in two ways: - -Either set the `compression` parameter in the options object when calling `encrypt`. +By default, `encrypt` will not use any compression when encrypting symmetrically only (i.e. when no `publicKeys` are given). +It's possible to change that behaviour by enabling compression through the config, either for the single encryption: ```js (async () => { @@ -279,20 +278,21 @@ Either set the `compression` parameter in the options object when calling `encry const encrypted = await openpgp.encrypt({ message, passwords: ['secret stuff'], // multiple passwords possible - compression: openpgp.enums.compression.zip // compress the data with zip + config: { preferredCompressionAlgorithm: openpgp.enums.compression.zlib } // compress the data with zlib }); })(); ``` -Or, override the config to enable compression: - +or by changing the default global configuration: ```js -openpgp.config.compression = openpgp.enums.compression.zlib; +openpgp.config.preferredCompressionAlgorithm = openpgp.enums.compression.zlib ``` Where the value can be any of: * `openpgp.enums.compression.zip` * `openpgp.enums.compression.zlib` + * `openpgp.enums.compression.uncompressed` (default) + #### Streaming encrypt *Uint8Array* data with a password diff --git a/openpgp.d.ts b/openpgp.d.ts index 139d25e0..2927423f 100644 --- a/openpgp.d.ts +++ b/openpgp.d.ts @@ -300,9 +300,9 @@ export class Message> { /* ############## v5 CONFIG #################### */ interface Config { - preferHashAlgorithm: enums.hash; - encryptionCipher: enums.symmetric; - compression: enums.compression; + preferredHashAlgorithm: enums.hash; + preferredSymmetricAlgorithm: enums.symmetric; + preferredCompressionAlgorithm: enums.compression; showVersion: boolean; showComment: boolean; deflateLevel: number; diff --git a/src/config/config.js b/src/config/config.js index 27e83463..006969e2 100644 --- a/src/config/config.js +++ b/src/config/config.js @@ -24,19 +24,19 @@ import enums from '../enums'; export default { /** * @memberof module:config - * @property {Integer} preferHashAlgorithm Default hash algorithm {@link module:enums.hash} + * @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash} */ - preferHashAlgorithm: enums.hash.sha256, + preferredHashAlgorithm: enums.hash.sha256, /** * @memberof module:config - * @property {Integer} encryptionCipher Default encryption cipher {@link module:enums.symmetric} + * @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric} */ - encryptionCipher: enums.symmetric.aes256, + preferredSymmetricAlgorithm: enums.symmetric.aes256, /** * @memberof module:config * @property {Integer} compression Default compression algorithm {@link module:enums.compression} */ - compression: enums.compression.uncompressed, + preferredCompressionAlgorithm: enums.compression.uncompressed, /** * @memberof module:config * @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9 @@ -56,9 +56,9 @@ export default { * Default Authenticated Encryption with Additional Data (AEAD) encryption mode * Only has an effect when aeadProtect is set to true. * @memberof module:config - * @property {Integer} aeadMode Default AEAD mode {@link module:enums.aead} + * @property {Integer} preferredAeadAlgorithm Default AEAD mode {@link module:enums.aead} */ - aeadMode: enums.aead.eax, + preferredAeadAlgorithm: enums.aead.eax, /** * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode * Only has an effect when aeadProtect is set to true. diff --git a/src/crypto/public_key/elliptic/eddsa.js b/src/crypto/public_key/elliptic/eddsa.js index 6339d9bb..16aa97d5 100644 --- a/src/crypto/public_key/elliptic/eddsa.js +++ b/src/crypto/public_key/elliptic/eddsa.js @@ -24,13 +24,15 @@ import sha512 from 'hash.js/lib/hash/sha/512'; import nacl from '@openpgp/tweetnacl/nacl-fast-light.js'; import util from '../../../util'; +import enums from '../../../enums'; +import hash from '../../hash'; nacl.hash = bytes => new Uint8Array(sha512().update(bytes).digest()); /** * Sign a message using the provided key * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hash_algo - Hash algorithm used to sign + * @param {module:enums.hash} hash_algo - Hash algorithm used to sign (must be sha256 or stronger) * @param {Uint8Array} message - Message to sign * @param {Uint8Array} publicKey - Public key * @param {Uint8Array} privateKey - Private key used to sign the message @@ -40,6 +42,10 @@ nacl.hash = bytes => new Uint8Array(sha512().update(bytes).digest()); * @async */ export async function sign(oid, hash_algo, message, publicKey, privateKey, hashed) { + if (hash.getHashByteLength(hash_algo) < hash.getHashByteLength(enums.hash.sha256)) { + // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 + throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.'); + } const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]); const signature = nacl.sign.detached(hashed, secretKey); // EdDSA signature params are returned in little-endian format diff --git a/src/key/factory.js b/src/key/factory.js index af3389a5..d6eeaecf 100644 --- a/src/key/factory.js +++ b/src/key/factory.js @@ -134,17 +134,8 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, conf 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; + function createPreferredAlgos(algos, preferredAlgo) { + return [preferredAlgo, ...algos.filter(algo => algo !== preferredAlgo)]; } const userIdPacket = UserIDPacket.fromObject(userId); @@ -156,28 +147,28 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, conf signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; signaturePacket.hashAlgorithm = await helper.getPreferredHashAlgo(null, secretKeyPacket, undefined, undefined, config); signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData]; - signaturePacket.preferredSymmetricAlgorithms = createdPreferredAlgos([ + signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([ // 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 - ], config.encryptionCipher); + ], config.preferredSymmetricAlgorithm); if (config.aeadProtect) { - signaturePacket.preferredAeadAlgorithms = createdPreferredAlgos([ + signaturePacket.preferredAeadAlgorithms = createPreferredAlgos([ enums.aead.eax, enums.aead.ocb - ], config.aeadMode); + ], config.preferredAeadAlgorithm); } - signaturePacket.preferredHashAlgorithms = createdPreferredAlgos([ + signaturePacket.preferredHashAlgorithms = createPreferredAlgos([ // prefer fast asm.js implementations (SHA-256) enums.hash.sha256, enums.hash.sha512 - ], config.preferHashAlgorithm); - signaturePacket.preferredCompressionAlgorithms = createdPreferredAlgos([ + ], config.preferredHashAlgorithm); + signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([ enums.compression.zlib, enums.compression.zip, enums.compression.uncompressed - ], config.compression); + ], config.preferredCompressionAlgorithm); if (index === 0) { signaturePacket.isPrimaryUserID = true; } diff --git a/src/key/helper.js b/src/key/helper.js index c307b8db..739ca544 100644 --- a/src/key/helper.js +++ b/src/key/helper.js @@ -132,7 +132,7 @@ export async function createBindingSignature(subkey, primaryKey, options, config * @async */ export async function getPreferredHashAlgo(key, keyPacket, date = new Date(), userId = {}, config) { - let hash_algo = config.preferHashAlgorithm; + let hash_algo = config.preferredHashAlgorithm; let pref_algo = hash_algo; if (key) { const primaryUser = await key.getPrimaryUser(date, userId, config); @@ -159,43 +159,41 @@ export async function getPreferredHashAlgo(key, keyPacket, date = new Date(), us } /** - * Returns the preferred symmetric/aead algorithm for a set of keys - * @param {symmetric|aead} type - Type of preference to return - * @param {Array} keys - Set of keys + * Returns the preferred symmetric/aead/compression algorithm for a set of keys + * @param {symmetric|aead|compression} type - Type of preference to return + * @param {Array} [keys] - Set of keys * @param {Date} [date] - Use the given date for verification instead of the current time * @param {Array} [userIds] - User IDs * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {module:enums.symmetric} Preferred symmetric algorithm. + * @returns {module:enums.symmetric|aead|compression} Preferred algorithm * @async */ -export async function getPreferredAlgo(type, keys, date = new Date(), userIds = [], config = defaultConfig) { - const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms'; - const defaultAlgo = type === 'symmetric' ? enums.symmetric.aes128 : enums.aead.eax; - const prioMap = {}; - await Promise.all(keys.map(async function(key, i) { +export async function getPreferredAlgo(type, keys = [], date = new Date(), userIds = [], config = defaultConfig) { + const defaultAlgo = { // these are all must-implement in rfc4880bis + 'symmetric': enums.symmetric.aes128, + 'aead': enums.aead.eax, + 'compression': enums.compression.uncompressed + }[type]; + const preferredSenderAlgo = { + 'symmetric': config.preferredSymmetricAlgorithm, + 'aead': config.preferredAeadAlgorithm, + 'compression': config.preferredCompressionAlgorithm + }[type]; + const prefPropertyName = { + 'symmetric': 'preferredSymmetricAlgorithms', + 'aead': 'preferredAeadAlgorithms', + 'compression': 'preferredCompressionAlgorithms' + }[type]; + + // if preferredSenderAlgo appears in the prefs of all recipients, we pick it + // otherwise we use the default algo + // if no keys are available, preferredSenderAlgo is returned + const senderAlgoSupport = await Promise.all(keys.map(async function(key, i) { const primaryUser = await key.getPrimaryUser(date, userIds[i], config); - if (!primaryUser.selfCertification[prefProperty]) { - return defaultAlgo; - } - primaryUser.selfCertification[prefProperty].forEach(function(algo, index) { - const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo }); - entry.prio += 64 >> index; - entry.count++; - }); + const recipientPrefs = primaryUser.selfCertification[prefPropertyName]; + return !!recipientPrefs && recipientPrefs.indexOf(preferredSenderAlgo) >= 0; })); - let prefAlgo = { prio: 0, algo: defaultAlgo }; - Object.values(prioMap).forEach(({ prio, count, algo }) => { - try { - if (algo !== enums[type].plaintext && - algo !== enums[type].idea && // not implemented - enums.read(enums[type], algo) && // known algorithm - count === keys.length && // available for all keys - prio > prefAlgo.prio) { - prefAlgo = prioMap[algo]; - } - } catch (e) {} - }); - return prefAlgo.algo; + return senderAlgoSupport.every(Boolean) ? preferredSenderAlgo : defaultAlgo; } /** diff --git a/src/message.js b/src/message.js index 314eb517..0bd806f2 100644 --- a/src/message.js +++ b/src/message.js @@ -37,7 +37,6 @@ import { import { Signature } from './signature'; import { getPreferredHashAlgo, getPreferredAlgo, isAeadSupported, createSignaturePacket } from './key'; - /** * Class that represents an OpenPGP message. * Can be an encrypted message, signed message, compressed message or literal message @@ -287,6 +286,7 @@ export class Message { const aeadAlgorithm = config.aeadProtect && await isAeadSupported(keys, date, userIds, config) ? enums.read(enums.aead, await getPreferredAlgo('aead', keys, date, userIds, config)) : undefined; + const sessionKeyData = await crypto.generateSessionKey(algorithm); return { data: sessionKeyData, algorithm, aeadAlgorithm }; } @@ -478,15 +478,17 @@ export class Message { /** * Compresses the message (the literal and -if signed- signature data packets of the message) + * @param {module:enums.compression} algo - compression algorithm * @param {Object} [config] - Full configuration, defaults to openpgp.config * @returns {Message} New message with compressed content. */ - compress(config = defaultConfig) { - if (config.compression === enums.compression.uncompressed) { + compress(algo, config = defaultConfig) { + if (algo === enums.compression.uncompressed) { return this; } const compressed = new CompressedDataPacket(config); + compressed.algorithm = enums.read(enums.compression, algo); compressed.packets = this.packets; const packetList = new PacketList(); diff --git a/src/openpgp.js b/src/openpgp.js index 7c05278f..b646a9d0 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -19,7 +19,7 @@ import stream from '@openpgp/web-stream-tools'; import { createReadableStreamWrapper } from '@mattiasbuelens/web-streams-adapter'; import { Message } from './message'; import { CleartextMessage } from './cleartext'; -import { generate, reformat } from './key'; +import { generate, reformat, getPreferredAlgo } from './key'; import defaultConfig from './config'; import util from './util'; @@ -264,7 +264,10 @@ export function encrypt({ message, publicKeys, privateKeys, passwords, sessionKe if (privateKeys.length || signature) { // sign the message only if private keys or signature is specified message = await message.sign(privateKeys, signature, signingKeyIds, date, fromUserIds, message.fromStream, config); } - message = message.compress(config); + message = message.compress( + await getPreferredAlgo('compression', publicKeys, date, toUserIds, config), + config + ); message = await message.encrypt(publicKeys, passwords, sessionKey, wildcard, encryptionKeyIds, date, toUserIds, streaming, config); const data = armor ? message.armor(config) : message.write(); return convertStream(data, streaming, armor ? 'utf8' : 'binary'); diff --git a/src/packet/compressed_data.js b/src/packet/compressed_data.js index 8629293c..afd2e901 100644 --- a/src/packet/compressed_data.js +++ b/src/packet/compressed_data.js @@ -56,7 +56,7 @@ class CompressedDataPacket { * Compression algorithm * @type {compression} */ - this.algorithm = enums.read(enums.compression, config.compression); + this.algorithm = enums.read(enums.compression, config.preferredCompressionAlgorithm); /** * Compressed packet data diff --git a/src/packet/sym_encrypted_session_key.js b/src/packet/sym_encrypted_session_key.js index 4ca8fa72..4fc8a1d0 100644 --- a/src/packet/sym_encrypted_session_key.js +++ b/src/packet/sym_encrypted_session_key.js @@ -44,7 +44,7 @@ class SymEncryptedSessionKeyPacket { this.sessionKey = null; this.sessionKeyEncryptionAlgorithm = null; this.sessionKeyAlgorithm = 'aes256'; - this.aeadAlgorithm = enums.read(enums.aead, config.aeadMode); + this.aeadAlgorithm = enums.read(enums.aead, config.preferredAeadAlgorithm); this.encrypted = null; this.s2k = null; this.iv = null; diff --git a/test/general/config.js b/test/general/config.js index 4e13e1b6..f43f8df2 100644 --- a/test/general/config.js +++ b/test/general/config.js @@ -5,10 +5,10 @@ const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp module.exports = () => describe('Custom configuration', function() { it('openpgp.generateKey', async function() { const v5KeysVal = openpgp.config.v5Keys; - const preferHashAlgorithmVal = openpgp.config.preferHashAlgorithm; + const preferredHashAlgorithmVal = openpgp.config.preferredHashAlgorithm; const showCommentVal = openpgp.config.showComment; openpgp.config.v5Keys = false; - openpgp.config.preferHashAlgorithm = openpgp.enums.hash.sha256; + openpgp.config.preferredHashAlgorithm = openpgp.enums.hash.sha256; openpgp.config.showComment = false; try { @@ -18,12 +18,12 @@ module.exports = () => describe('Custom configuration', function() { const { key, privateKeyArmored } = await openpgp.generateKey(opt); expect(key.keyPacket.version).to.equal(4); expect(privateKeyArmored.indexOf(openpgp.config.commentString) > 0).to.be.false; - expect(key.users[0].selfCertifications[0].preferredHashAlgorithms[0]).to.equal(openpgp.config.preferHashAlgorithm); + expect(key.users[0].selfCertifications[0].preferredHashAlgorithms[0]).to.equal(openpgp.config.preferredHashAlgorithm); const config = { v5Keys: true, showComment: true, - preferHashAlgorithm: openpgp.enums.hash.sha512 + preferredHashAlgorithm: openpgp.enums.hash.sha512 }; const opt2 = { userIds: { name: 'Test User', email: 'text@example.com' }, @@ -32,20 +32,20 @@ module.exports = () => describe('Custom configuration', function() { const { key: key2, privateKeyArmored: privateKeyArmored2 } = await openpgp.generateKey(opt2); expect(key2.keyPacket.version).to.equal(5); expect(privateKeyArmored2.indexOf(openpgp.config.commentString) > 0).to.be.true; - expect(key2.users[0].selfCertifications[0].preferredHashAlgorithms[0]).to.equal(config.preferHashAlgorithm); + expect(key2.users[0].selfCertifications[0].preferredHashAlgorithms[0]).to.equal(config.preferredHashAlgorithm); } finally { openpgp.config.v5Keys = v5KeysVal; - openpgp.config.preferHashAlgorithm = preferHashAlgorithmVal; + openpgp.config.preferredHashAlgorithm = preferredHashAlgorithmVal; openpgp.config.showComment = showCommentVal; } }); it('openpgp.reformatKey', async function() { - const compressionVal = openpgp.config.compression; - const preferHashAlgorithmVal = openpgp.config.preferHashAlgorithm; + const preferredCompressionAlgorithmVal = openpgp.config.preferredCompressionAlgorithm; + const preferredHashAlgorithmVal = openpgp.config.preferredHashAlgorithm; const showCommentVal = openpgp.config.showComment; - openpgp.config.compression = openpgp.enums.compression.bzip2; - openpgp.config.preferHashAlgorithm = openpgp.enums.hash.sha256; + openpgp.config.preferredCompressionAlgorithm = openpgp.enums.compression.bzip2; + openpgp.config.preferredHashAlgorithm = openpgp.enums.hash.sha256; openpgp.config.showComment = false; try { @@ -55,24 +55,24 @@ module.exports = () => describe('Custom configuration', function() { const opt = { privateKey: origKey, userIds }; const { key: refKey, privateKeyArmored: refKeyArmored } = await openpgp.reformatKey(opt); const prefs = refKey.users[0].selfCertifications[0]; - expect(prefs.preferredCompressionAlgorithms[0]).to.equal(openpgp.config.compression); - expect(prefs.preferredHashAlgorithms[0]).to.equal(openpgp.config.preferHashAlgorithm); + expect(prefs.preferredCompressionAlgorithms[0]).to.equal(openpgp.config.preferredCompressionAlgorithm); + expect(prefs.preferredHashAlgorithms[0]).to.equal(openpgp.config.preferredHashAlgorithm); expect(refKeyArmored.indexOf(openpgp.config.commentString) > 0).to.be.false; const config = { showComment: true, - compression: openpgp.enums.compression.zip, - preferHashAlgorithm: openpgp.enums.hash.sha512 + preferredCompressionAlgorithm: openpgp.enums.compression.zip, + preferredHashAlgorithm: openpgp.enums.hash.sha512 }; const opt2 = { privateKey: origKey, userIds, config }; const { key: refKey2, privateKeyArmored: refKeyArmored2 } = await openpgp.reformatKey(opt2); const prefs2 = refKey2.users[0].selfCertifications[0]; - expect(prefs2.preferredCompressionAlgorithms[0]).to.equal(config.compression); - expect(prefs2.preferredHashAlgorithms[0]).to.equal(config.preferHashAlgorithm); + expect(prefs2.preferredCompressionAlgorithms[0]).to.equal(config.preferredCompressionAlgorithm); + expect(prefs2.preferredHashAlgorithms[0]).to.equal(config.preferredHashAlgorithm); expect(refKeyArmored2.indexOf(openpgp.config.commentString) > 0).to.be.true; } finally { - openpgp.config.compression = compressionVal; - openpgp.config.preferHashAlgorithm = preferHashAlgorithmVal; + openpgp.config.preferredCompressionAlgorithm = preferredCompressionAlgorithmVal; + openpgp.config.preferredHashAlgorithm = preferredHashAlgorithmVal; openpgp.config.showComment = showCommentVal; } }); @@ -142,9 +142,9 @@ module.exports = () => describe('Custom configuration', function() { it('openpgp.encrypt', async function() { const aeadProtectVal = openpgp.config.aeadProtect; - const compressionVal = openpgp.config.compression; + const preferredCompressionAlgorithmVal = openpgp.config.preferredCompressionAlgorithm; openpgp.config.aeadProtect = false; - openpgp.config.compression = openpgp.enums.compression.uncompressed; + openpgp.config.preferredCompressionAlgorithm = openpgp.enums.compression.uncompressed; try { const passwords = ['12345678']; @@ -160,7 +160,7 @@ module.exports = () => describe('Custom configuration', function() { const config = { aeadProtect: true, - compression: openpgp.enums.compression.zip, + preferredCompressionAlgorithm: openpgp.enums.compression.zip, deflateLevel: 1 }; const armored2 = await openpgp.encrypt({ message, passwords, config }); @@ -173,7 +173,7 @@ module.exports = () => describe('Custom configuration', function() { expect(compressed.algorithm).to.equal("zip"); } finally { openpgp.config.aeadProtect = aeadProtectVal; - openpgp.config.compression = compressionVal; + openpgp.config.preferredCompressionAlgorithm = preferredCompressionAlgorithmVal; } }); diff --git a/test/general/key.js b/test/general/key.js index 4276ef74..1410bc2c 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -2092,7 +2092,7 @@ function versionSpecificTests() { const hash = openpgp.enums.hash; expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha256, hash.sha512]); const compr = openpgp.enums.compression; - expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip, compr.uncompressed]); + expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.uncompressed, compr.zlib, compr.zip]); let expectedFeatures; if (openpgp.config.v5Keys) { @@ -2112,14 +2112,14 @@ function versionSpecificTests() { }); it('Preferences of generated key - with config values', async function() { - const encryptionCipherVal = openpgp.config.encryptionCipher; - const preferHashAlgorithmVal = openpgp.config.preferHashAlgorithm; - const compressionVal = openpgp.config.compression; - const aeadModeVal = openpgp.config.aeadMode; - openpgp.config.encryptionCipher = openpgp.enums.symmetric.aes192; - openpgp.config.preferHashAlgorithm = openpgp.enums.hash.sha224; - openpgp.config.compression = openpgp.enums.compression.zlib; - openpgp.config.aeadMode = openpgp.enums.aead.experimentalGcm; + const preferredSymmetricAlgorithmVal = openpgp.config.preferredSymmetricAlgorithm; + const preferredHashAlgorithmVal = openpgp.config.preferredHashAlgorithm; + const preferredCompressionAlgorithmVal = openpgp.config.preferredCompressionAlgorithm; + const preferredAeadAlgorithmVal = openpgp.config.preferredAeadAlgorithm; + openpgp.config.preferredSymmetricAlgorithm = openpgp.enums.symmetric.aes192; + openpgp.config.preferredHashAlgorithm = openpgp.enums.hash.sha224; + openpgp.config.preferredCompressionAlgorithm = openpgp.enums.compression.zip; + openpgp.config.preferredAeadAlgorithm = openpgp.enums.aead.experimentalGcm; const testPref = function(key) { // key flags @@ -2137,7 +2137,7 @@ function versionSpecificTests() { const hash = openpgp.enums.hash; expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha224, hash.sha256, hash.sha512]); const compr = openpgp.enums.compression; - expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip, compr.uncompressed]); + expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zip, compr.zlib, compr.uncompressed]); let expectedFeatures; if (openpgp.config.v5Keys) { @@ -2155,10 +2155,10 @@ function versionSpecificTests() { testPref(key.key); testPref(await openpgp.readKey({ armoredKey: key.publicKeyArmored })); } finally { - openpgp.config.encryptionCipher = encryptionCipherVal; - openpgp.config.preferHashAlgorithm = preferHashAlgorithmVal; - openpgp.config.compression = compressionVal; - openpgp.config.aeadMode = aeadModeVal; + openpgp.config.preferredSymmetricAlgorithm = preferredSymmetricAlgorithmVal; + openpgp.config.preferredHashAlgorithm = preferredHashAlgorithmVal; + openpgp.config.preferredCompressionAlgorithm = preferredCompressionAlgorithmVal; + openpgp.config.preferredAeadAlgorithm = preferredAeadAlgorithmVal; } }); @@ -3243,26 +3243,31 @@ module.exports = () => describe('Key', function() { expect(revKey.armor()).not.to.match(/Comment: This is a revocation certificate/); }); - it("getPreferredAlgo('symmetric') - one key - AES256", async function() { + it("getPreferredAlgo('symmetric') - one key", async function() { const [key1] = await openpgp.readKeys({ armoredKeys: twoKeys }); - const prefAlgo = await key.getPreferredAlgo('symmetric', [key1]); + const prefAlgo = await key.getPreferredAlgo('symmetric', [key1], undefined, undefined, { + ...openpgp.config, preferredSymmetricAlgorithm: openpgp.enums.symmetric.aes256 + }); expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes256); }); - it("getPreferredAlgo('symmetric') - two key - AES192", async function() { - const keys = await openpgp.readKeys({ armoredKeys: twoKeys }); - const key1 = keys[0]; - const key2 = keys[1]; + it("getPreferredAlgo('symmetric') - two key", async function() { + const { aes128, aes192, cast5 } = openpgp.enums.symmetric; + const [key1, key2] = await openpgp.readKeys({ armoredKeys: twoKeys }); const primaryUser = await key2.getPrimaryUser(); - primaryUser.selfCertification.preferredSymmetricAlgorithms = [6,8,3]; - const prefAlgo = await key.getPreferredAlgo('symmetric', [key1, key2]); - expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes192); + primaryUser.selfCertification.preferredSymmetricAlgorithms = [6, aes192, cast5]; + const prefAlgo = await key.getPreferredAlgo('symmetric', [key1, key2], undefined, undefined, { + ...openpgp.config, preferredSymmetricAlgorithm: openpgp.enums.symmetric.aes192 + }); + expect(prefAlgo).to.equal(aes192); + const prefAlgo2 = await key.getPreferredAlgo('symmetric', [key1, key2], undefined, undefined, { + ...openpgp.config, preferredSymmetricAlgorithm: openpgp.enums.symmetric.aes256 + }); + expect(prefAlgo2).to.equal(aes128); }); it("getPreferredAlgo('symmetric') - two key - one without pref", async function() { - const keys = await openpgp.readKeys({ armoredKeys: twoKeys }); - const key1 = keys[0]; - const key2 = keys[1]; + const [key1, key2] = await openpgp.readKeys({ armoredKeys: twoKeys }); const primaryUser = await key2.getPrimaryUser(); primaryUser.selfCertification.preferredSymmetricAlgorithms = null; const prefAlgo = await key.getPreferredAlgo('symmetric', [key1, key2]); @@ -3274,7 +3279,9 @@ module.exports = () => describe('Key', function() { const primaryUser = await key1.getPrimaryUser(); primaryUser.selfCertification.features = [7]; // Monkey-patch AEAD feature flag primaryUser.selfCertification.preferredAeadAlgorithms = [2,1]; - const prefAlgo = await key.getPreferredAlgo('aead', [key1]); + const prefAlgo = await key.getPreferredAlgo('aead', [key1], undefined, undefined, { + ...openpgp.config, preferredAeadAlgorithm: openpgp.enums.aead.ocb + }); expect(prefAlgo).to.equal(openpgp.enums.aead.ocb); const supported = await key.isAeadSupported([key1]); expect(supported).to.be.true; diff --git a/test/general/openpgp.js b/test/general/openpgp.js index 5536bcee..f8d3dab7 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -685,7 +685,7 @@ function withCompression(tests) { tests( function(options) { - options.config = { compression }; + options.config = { preferredCompressionAlgorithm: compression }; return options; }, function() { @@ -822,7 +822,7 @@ module.exports = () => describe('OpenPGP.js public api tests', function() { let publicKey; let publicKeyNoAEAD; let aeadProtectVal; - let aeadModeVal; + let preferredAeadAlgorithmVal; let aeadChunkSizeByteVal; let v5KeysVal; let privateKeyMismatchingParams; @@ -840,14 +840,14 @@ module.exports = () => describe('OpenPGP.js public api tests', function() { privateKeyMismatchingParams = await openpgp.readKey({ armoredKey: mismatchingKeyParams }); aeadProtectVal = openpgp.config.aeadProtect; - aeadModeVal = openpgp.config.aeadMode; + preferredAeadAlgorithmVal = openpgp.config.preferredAeadAlgorithm; aeadChunkSizeByteVal = openpgp.config.aeadChunkSizeByte; v5KeysVal = openpgp.config.v5Keys; }); afterEach(function() { openpgp.config.aeadProtect = aeadProtectVal; - openpgp.config.aeadMode = aeadModeVal; + openpgp.config.preferredAeadAlgorithm = preferredAeadAlgorithmVal; openpgp.config.aeadChunkSizeByte = aeadChunkSizeByteVal; openpgp.config.v5Keys = v5KeysVal; }); @@ -1035,7 +1035,7 @@ module.exports = () => describe('OpenPGP.js public api tests', function() { if: true, beforeEach: function() { openpgp.config.aeadProtect = true; - openpgp.config.aeadMode = openpgp.enums.aead.experimentalGcm; + openpgp.config.preferredAeadAlgorithm = openpgp.enums.aead.experimentalGcm; openpgp.config.v5Keys = true; // Monkey-patch AEAD feature flag @@ -1062,7 +1062,7 @@ module.exports = () => describe('OpenPGP.js public api tests', function() { if: !openpgp.config.ci, beforeEach: function() { openpgp.config.aeadProtect = true; - openpgp.config.aeadMode = openpgp.enums.aead.ocb; + openpgp.config.preferredAeadAlgorithm = openpgp.enums.aead.ocb; // Monkey-patch AEAD feature flag publicKey.users[0].selfCertifications[0].features = [7]; diff --git a/test/general/streaming.js b/test/general/streaming.js index fc4f96b4..132317f3 100644 --- a/test/general/streaming.js +++ b/test/general/streaming.js @@ -412,7 +412,7 @@ function tests() { const message = await openpgp.readMessage({ armoredMessage: openpgp.stream.transform(encrypted, value => { value += ''; - if (value === '=' || value.length === 6) return; // Remove checksum + if (value === '=' || value.length === 5) return; // Remove checksum const newlineIndex = value.indexOf('\n', 500); if (value.length > 1000) return value.slice(0, newlineIndex - 1) + (value[newlineIndex - 1] === 'a' ? 'b' : 'a') + value.slice(newlineIndex); return value; diff --git a/test/general/x25519.js b/test/general/x25519.js index f51e32ad..efe29150 100644 --- a/test/general/x25519.js +++ b/test/general/x25519.js @@ -231,11 +231,11 @@ module.exports = () => (openpgp.config.ci ? describe.skip : describe)('X25519 Cr const R = util.hexToUint8Array(vector.SIGNATURE.R); const S = util.hexToUint8Array(vector.SIGNATURE.S); return Promise.all([ - signature.sign(22, undefined, publicParams, privateParams, undefined, data).then(({ r, s }) => { + signature.sign(22, openpgp.enums.hash.sha256, publicParams, privateParams, undefined, data).then(({ r, s }) => { expect(R).to.deep.eq(r); expect(S).to.deep.eq(s); }), - signature.verify(22, undefined, { r: R, s: S }, publicParams, undefined, data).then(result => { + signature.verify(22, openpgp.enums.hash.sha256, { r: R, s: S }, publicParams, undefined, data).then(result => { expect(result).to.be.true; }) ]);