Skip to content

Argon2id.deriveKey gives segmentation fault for large parameter values #177

@elliotwutingfeng

Description

@elliotwutingfeng

I am testing out some Dart cryptography libraries for deriving Argon2id keys with large parameter values, such as the maximum allowed settings in the Bitwarden password manager, which as of today are 10 iterations, 16 parallelism, and 1024 MiB memory.

The following leads to a segmentation fault. Running the script with --old_gen_heap_size=2g sometimes gives a segmentation fault, but sometimes it works.

import 'dart:convert';
import 'dart:typed_data';

import 'package:cryptography/cryptography.dart';

Future<void> main() async {
  final Uint8List password = utf8.encode("passphrase");
  final List<int> salt =
      (await Sha256().hash(base64.decode("rNYWSe/wFO1k+Qxia0A96A=="))).bytes;

  // Bitwarden maximum settings
  final int kdfIterations = 10;
  final int kdfParallelism = 16;
  final int kdfMemory = 1024; // 1024 MiB

  final Argon2id algorithm = Argon2id(
    parallelism: kdfParallelism,
    memory: kdfMemory * 1024,
    iterations: kdfIterations,
    hashLength: 32,
  );
  final SecretKey newSecretKey =
      await algorithm.deriveKey(secretKey: SecretKey(password), nonce: salt);
  final List<int> newSecretKeyBytes = await newSecretKey.extractBytes();
  print('hashed password: $newSecretKeyBytes');
}

Equivalent working program using pointycastle.

import 'dart:convert';
import 'dart:typed_data';

import 'package:pointycastle/digests/sha256.dart';
import 'package:pointycastle/key_derivators/argon2_native_int_impl.dart';
import 'package:pointycastle/pointycastle.dart';

Future<void> main() async {
  final Uint8List password = utf8.encode("passphrase");
  final Uint8List salt =
      SHA256Digest().process(base64.decode("rNYWSe/wFO1k+Qxia0A96A=="));

  // Bitwarden maximum settings
  final int kdfIterations = 10;
  final int kdfParallelism = 16;
  final int kdfMemory = 1024; // 1024 MiB

  final List<int> newSecretKeyBytes = (Argon2BytesGenerator()
        ..init(Argon2Parameters(Argon2Parameters.ARGON2_id, salt,
            desiredKeyLength: 32,
            iterations: kdfIterations,
            memory: kdfMemory * 1024,
            lanes: kdfParallelism)))
      .process(Uint8List.fromList(password));
  print('hashed password: $newSecretKeyBytes');
}

Expected output for both programs:

hashed password: [207, 41, 183, 164, 139, 92, 97, 166, 115, 223, 111, 83, 7, 239, 193, 74, 180, 246, 103, 53, 177, 250, 203, 81, 148, 124, 62, 225, 215, 116, 170, 240]

I am aware that it is not advisable to set Argon2id KDF settings to such extreme values in either case, however, this may be worth some investigation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions