crypto-refresh: add support for Argon2 S2K (#1597)

In terms of API, this feature is backwards compatible, no breaking changes.
However, since a Wasm module is loaded for the Argon2 computation, browser apps
might need to make changes to their CSP policy in order to use the feature.

Newly introduced config fields:
- `config.s2kType` (defaulting to `enums.s2k.iterated`): s2k to use on
password-based encryption as well as private key encryption;
- `config.s2kArgon2Params` (defaulting to "uniformly safe settings" from Argon
RFC): parameters to use on encryption when `config.s2kType` is set to
`enums.s2k.argon2`;
This commit is contained in:
larabr
2023-04-04 14:22:13 +02:00
committed by larabr
parent 204f32791d
commit ebf22f2ee7
14 changed files with 387 additions and 32 deletions

View File

@@ -16,7 +16,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import PublicKeyPacket from './public_key';
import S2K from '../type/s2k';
import { newS2KFromConfig, newS2KFromType } from '../type/s2k';
import crypto from '../crypto';
import enums from '../enums';
import util from '../util';
@@ -115,7 +115,8 @@ class SecretKeyPacket extends PublicKeyPacket {
// - [Optional] If string-to-key usage octet was 255, 254, or 253, a
// string-to-key specifier. The length of the string-to-key
// specifier is implied by its type, as described above.
this.s2k = new S2K();
const s2kType = bytes[i++];
this.s2k = newS2KFromType(s2kType);
i += this.s2k.read(bytes.subarray(i, bytes.length));
if (this.s2k.type === 'gnu-dummy') {
@@ -279,7 +280,7 @@ class SecretKeyPacket extends PublicKeyPacket {
delete this.unparseableKeyMaterial;
this.isEncrypted = null;
this.keyMaterial = null;
this.s2k = new S2K(config);
this.s2k = newS2KFromType(enums.s2k.gnu, config);
this.s2k.algorithm = 0;
this.s2k.c = 0;
this.s2k.type = 'gnu-dummy';
@@ -310,8 +311,8 @@ class SecretKeyPacket extends PublicKeyPacket {
throw new Error('A non-empty passphrase is required for key encryption.');
}
this.s2k = new S2K(config);
this.s2k.salt = crypto.random.getRandomBytes(8);
this.s2k = newS2KFromConfig(config);
this.s2k.generateSalt();
const cleartext = crypto.serializeParams(this.algorithm, this.privateParams);
this.symmetric = enums.symmetric.aes256;
const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric);

View File

@@ -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 S2K from '../type/s2k';
import { newS2KFromConfig, newS2KFromType } from '../type/s2k';
import defaultConfig from '../config';
import crypto from '../crypto';
import enums from '../enums';
@@ -89,7 +89,8 @@ class SymEncryptedSessionKeyPacket {
}
// A string-to-key (S2K) specifier, length as defined above.
this.s2k = new S2K();
const s2kType = bytes[offset++];
this.s2k = newS2KFromType(s2kType);
offset += this.s2k.read(bytes.subarray(offset, bytes.length));
if (this.version === 5) {
@@ -178,8 +179,8 @@ class SymEncryptedSessionKeyPacket {
this.sessionKeyEncryptionAlgorithm = algo;
this.s2k = new S2K(config);
this.s2k.salt = crypto.random.getRandomBytes(8);
this.s2k = newS2KFromConfig(config);
this.s2k.generateSalt();
const { blockSize, keySize } = crypto.getCipher(algo);
const encryptionKey = await this.s2k.produceKey(passphrase, keySize);