convert method

  1. @override
BcryptHashDigest convert(
  1. List<int> password
)
override

Generate a derived key using the Bcrypt algorithm.

Implementation

@override
BcryptHashDigest convert(List<int> password) {
  int i, j, l, h, t;
  int s0, s1, s2, s3;
  int nb = 1 << _ctx.cost;
  var pass32 = _ctx.makePassword(password);
  var salt32 = _makeSaltKey(_ctx.salt);

  // Initialize state: P (Subkeys) + S (Substitution boxes)
  var state = Uint32List.fromList(_sv);
  var p = Uint32List.view(state.buffer, 0, 18);
  var s = Uint32List.view(state.buffer, 18 << 2, 1024);

  // Blowfish encrypt routine
  l = 0;
  h = 0;
  void encrypt() {
    l ^= p[0];
    h ^= _fsub(s, l) ^ p[1];
    l ^= _fsub(s, h) ^ p[2];
    h ^= _fsub(s, l) ^ p[3];
    l ^= _fsub(s, h) ^ p[4];
    h ^= _fsub(s, l) ^ p[5];
    l ^= _fsub(s, h) ^ p[6];
    h ^= _fsub(s, l) ^ p[7];
    l ^= _fsub(s, h) ^ p[8];
    h ^= _fsub(s, l) ^ p[9];
    l ^= _fsub(s, h) ^ p[10];
    h ^= _fsub(s, l) ^ p[11];
    l ^= _fsub(s, h) ^ p[12];
    h ^= _fsub(s, l) ^ p[13];
    l ^= _fsub(s, h) ^ p[14];
    h ^= _fsub(s, l) ^ p[15];
    l ^= _fsub(s, h) ^ p[16];
    h ^= p[17];
    // swap
    t = l;
    l = h;
    h = t;
  }

  // Key Expansion
  l = 0;
  h = 0;
  s0 = salt32[0];
  s1 = salt32[1];
  s2 = salt32[2];
  s3 = salt32[3];
  for (i = 0; i < 18; ++i) {
    p[i] ^= pass32[i];
  }
  for (i = 0; i < state.length; i += 2) {
    // block ^= salt
    l ^= s0;
    h ^= s1;
    // blowfish encrypt
    encrypt();
    // set state
    state[i] = l;
    state[i + 1] = h;
    // s0 <-> s2
    t = s0;
    s0 = s2;
    s2 = t;
    // s1 <-> s3
    t = s1;
    s1 = s3;
    s3 = t;
  }

  // Bcrypt Rounds
  for (j = 0; j < nb; ++j) {
    // mix with password
    l = 0;
    h = 0;
    for (i = 0; i < 18; ++i) {
      p[i] ^= pass32[i];
    }
    for (i = 0; i < state.length;) {
      encrypt();
      state[i++] = l;
      state[i++] = h;
    }
    // mix with salt
    l = 0;
    h = 0;
    for (i = 0; i < 18; ++i) {
      p[i] ^= salt32[i];
    }
    for (i = 0; i < state.length;) {
      encrypt();
      state[i++] = l;
      state[i++] = h;
    }
  }

  // Encrypt IV
  var result = Uint32List.fromList(_iv);
  for (i = 0; i < 64; i++) {
    l = result[0];
    h = result[1];
    encrypt();
    result[0] = l;
    result[1] = h;

    l = result[2];
    h = result[3];
    encrypt();
    result[2] = l;
    result[3] = h;

    l = result[4];
    h = result[5];
    encrypt();
    result[4] = l;
    result[5] = h;
  }

  // Transform to bytes
  for (i = 0; i < result.length; ++i) {
    result[i] = _swap32(result[i]);
  }
  var output = Uint8List.view(result.buffer, 0, derivedKeyLength);
  return BcryptHashDigest(_ctx, output);
}