fromUserCredsBytesAndChallenge static method

Future<User> fromUserCredsBytesAndChallenge({
  1. required Uint8List userIdBytes,
  2. required Uint8List passwordBytes,
  3. required Challenge challenge,
  4. bool useUserIdInPrivateKey = true,
  5. HashFunction? customHashFunction,
  6. KdfChoice? kdf,
  7. Kdf? customKdf,
  8. Uint8List? ephemeralUserPrivateKey,
})

As part of initial user authentication handshake, create a User from a challenge provided by the server.

WARNING: If the server provides the core SRP parameters (safe prime, generator, hash algorithm) it is highly recommended for the client to verify they are cryptographically secure. This could include checking the hash algorithm is one of those expected, and that the safe prime and generator and secure (see verifySafePrime and verifyGenerator).

Enable useUserIdInPrivateKey if the user ID was used for key generation during user registration. See createSaltedVerificationKey for details. If useUserIdInPrivateKey is false, the user ID is only used to generate the user-side verifier.

If kdf is not provided, Argon2id is used since it is slow and hence relatively secure. Be sure this KDF matches the one used during registration. Alternatively, provide customKdf to use a custom KDF implementation (cannot provide both kdf and customKdf).

If a ephemeralUserPrivateKey is not provided, one is generated.

This method is preferred over fromUserCredsAndChallenge for security reasons, as it avoids storing passwords as Strings in memory.

userIdBytes and passwordBytes should be UTF-8 encoded credentials.

Implementation

static Future<User> fromUserCredsBytesAndChallenge({
  required Uint8List userIdBytes,
  required Uint8List passwordBytes,
  required Challenge challenge,
  final bool useUserIdInPrivateKey = true,
  HashFunction? customHashFunction,
  KdfChoice? kdf,
  Kdf? customKdf,
  final Uint8List? ephemeralUserPrivateKey,
}) async {
  final resolvedKdf = _resolveKdf(kdf, customKdf);
  final resolvedHashFunction = _resolveHashFunction(
    challenge, customHashFunction);

  final user = User._(
    userIdBytes: userIdBytes,
    passwordBytes: passwordBytes,
    generator: challenge.generator,
    safePrime: challenge.safePrime,
    verifierKeySalt: challenge.verifierKeySalt,
    useUserIdInPrivateKey: useUserIdInPrivateKey,
    hashFunction: resolvedHashFunction,
    kdf: resolvedKdf,
  );
  user._generateEphemeralUserAsymmetricKeys(
    ephemeralUserPrivateKeyBytes: ephemeralUserPrivateKey);
  // Derives session key and its user-side verifier M1.
  await user._processChallenge(challenge);
  return user;
}