Skip to content

Commit

Permalink
Add newS2KFromConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
larabr committed Feb 16, 2023
1 parent 0769a58 commit cce3e9e
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 22 deletions.
4 changes: 2 additions & 2 deletions src/packet/secret_key.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/packet/sym_encrypted_session_key.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 0 additions & 3 deletions src/type/s2k/argon2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/type/s2k/generic.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -197,4 +197,4 @@ class S2K {
}
}

export default S2K;
export default GenericS2K;
36 changes: 23 additions & 13 deletions src/type/s2k/index.js
Original file line number Diff line number Diff line change
@@ -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 };
19 changes: 19 additions & 0 deletions test/general/openpgp.js
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,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({
Expand Down

0 comments on commit cce3e9e

Please sign in to comment.