diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index ed2d3119d..ca204c0a1 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -16,7 +16,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import PublicKeyPacket from './public_key'; -import { newS2KFromType } from '../type/s2k'; +import { newS2KFromConfig, newS2KFromType } from '../type/s2k'; import crypto from '../crypto'; import enums from '../enums'; import util from '../util'; @@ -283,7 +283,7 @@ class SecretKeyPacket extends PublicKeyPacket { throw new Error('A non-empty passphrase is required for key encryption.'); } - this.s2k = newS2KFromType(undefined, config); + this.s2k = newS2KFromConfig(config); this.s2k.generateSalt(); const cleartext = crypto.serializeParams(this.algorithm, this.privateParams); this.symmetric = enums.symmetric.aes256; diff --git a/src/packet/sym_encrypted_session_key.js b/src/packet/sym_encrypted_session_key.js index 09e8e1751..6e940779e 100644 --- a/src/packet/sym_encrypted_session_key.js +++ b/src/packet/sym_encrypted_session_key.js @@ -15,7 +15,7 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -import { newS2KFromType } from '../type/s2k'; +import { newS2KFromConfig, newS2KFromType } from '../type/s2k'; import defaultConfig from '../config'; import crypto from '../crypto'; import enums from '../enums'; @@ -179,7 +179,7 @@ class SymEncryptedSessionKeyPacket { this.sessionKeyEncryptionAlgorithm = algo; - this.s2k = newS2KFromType(undefined, config); + this.s2k = newS2KFromConfig(config); this.s2k.generateSalt(); const { blockSize, keySize } = crypto.getCipher(algo); diff --git a/src/type/s2k/argon2.js b/src/type/s2k/argon2.js index e931d7fd8..598c4388c 100644 --- a/src/type/s2k/argon2.js +++ b/src/type/s2k/argon2.js @@ -89,9 +89,6 @@ class Argon2S2K { */ async produceKey(passphrase, keySize) { const decodedM = 2 << (this.encodedM - 1); - if (decodedM < 8 * this.p || this.encodedM > 31) { - throw new Error('Memory size and parallelism settings are incompatible.'); - } try { if (!argon2Promise) { // first load diff --git a/src/type/s2k/generic.js b/src/type/s2k/generic.js index 1c6361ad3..9b151fe79 100644 --- a/src/type/s2k/generic.js +++ b/src/type/s2k/generic.js @@ -33,7 +33,7 @@ import crypto from '../../crypto'; import enums from '../../enums'; import util from '../../util'; -class S2K { +class GenericS2K { /** * @param {Object} [config] - Full configuration, defaults to openpgp.config */ @@ -197,4 +197,4 @@ class S2K { } } -export default S2K; +export default GenericS2K; diff --git a/src/type/s2k/index.js b/src/type/s2k/index.js index 6444405e9..cea97e417 100644 --- a/src/type/s2k/index.js +++ b/src/type/s2k/index.js @@ -1,35 +1,45 @@ import defaultConfig from '../../config'; -import Argon2S2k, { Argon2OutOfMemoryError } from './argon2'; -import OtherS2K from './generic'; +import Argon2S2K, { Argon2OutOfMemoryError } from './argon2'; +import GenericS2K from './generic'; import enums from '../../enums'; -const allowedDefaultS2KTypes = new Set([enums.s2k.argon2, enums.s2k.iterated]); +const allowedS2KTypesForEncryption = new Set([enums.s2k.argon2, enums.s2k.iterated]); /** * Instantiate a new S2K instance of the given type - * @param {module:enums.s2k} [type] - If not specified, `config.s2kTypes` is used + * @param {module:enums.s2k} type * @oaram {Object} [config] * @returns {Object} New s2k object * @throws {Error} for unknown or unsupported types */ -export function newS2KFromType(maybeType, config = defaultConfig) { - if (!maybeType && !allowedDefaultS2KTypes.has(config.s2kType)) { - throw new Error('The provided `config.s2kType` value is not allowed'); - } - - const type = maybeType || config.s2kType; - +export function newS2KFromType(type, config = defaultConfig) { switch (type) { case enums.s2k.argon2: - return new Argon2S2k(config); + return new Argon2S2K(config); case enums.s2k.iterated: case enums.s2k.gnu: case enums.s2k.salted: case enums.s2k.simple: - return new OtherS2K(type, config); + return new GenericS2K(type, config); default: throw new Error(`Unsupported S2K type ${type}`); } } +/** + * Instantiate a new S2K instance based on the config settings + * @oaram {Object} config + * @returns {Object} New s2k object + * @throws {Error} for unknown or unsupported types + */ +export function newS2KFromConfig(config) { + const { s2kType } = config; + + if (!allowedS2KTypesForEncryption.has(s2kType)) { + throw new Error('The provided `config.s2kType` value is not allowed'); + } + + return newS2KFromType(s2kType, config); +} + export { Argon2OutOfMemoryError }; diff --git a/test/general/openpgp.js b/test/general/openpgp.js index e6b9fead0..8b3403d38 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -1219,6 +1219,25 @@ module.exports = () => describe('OpenPGP.js public api tests', function() { expect(unlocked.isDecrypted()).to.be.true; }); + it('should support encrypting with argon2 s2k', async function() { + const key = await openpgp.readKey({ armoredKey: gnuDummyKeySigningSubkey }); + const locked = await openpgp.encryptKey({ + privateKey: key, + passphrase: passphrase, + config: { s2kType: openpgp.enums.s2k.argon2 } + }); + expect(key.isDecrypted()).to.be.true; + expect(locked.isDecrypted()).to.be.false; + expect(locked.keyPacket.isDummy()).to.be.true; + const unlocked = await openpgp.decryptKey({ + privateKey: locked, + passphrase: passphrase + }); + expect(key.isDecrypted()).to.be.true; + expect(unlocked.isDecrypted()).to.be.true; + expect(unlocked.keyPacket.isDummy()).to.be.true; + }); + it('should encrypt gnu-dummy key', async function() { const key = await openpgp.readKey({ armoredKey: gnuDummyKeySigningSubkey }); const locked = await openpgp.encryptKey({