decrypt method

T decrypt(
  1. T x, {
  2. List<int> tweak = const [],
})

Performs FF1 decryption on x, optionally using a tweak.

Implementation

T decrypt(T x, {List<int> tweak = const []}) {
  if (!x.isValid(radix)) {
    throw ArgumentException.invalidOperationArguments(
      "FF1.decrypt",
      reason: "Incorrect input for radix.",
      details: {"radix": radix},
    );
  }

  final n = x.numeralCount();
  if (n < config.minLen || n > config.maxLen) {
    throw ArgumentException.invalidOperationArguments(
      "FF1.decrypt",
      reason: "Incorrect input length for radix.",
      details: {"radix": radix},
    );
  }

  final t = tweak.length;
  final xN = x.split();
  var xA = xN[0];
  var xB = xN[1];
  final u = xA.numeralCount();
  final v = xB.numeralCount();
  final b = config.calculateB(v);
  final d = 4 * ((b + 3) ~/ 4) + 4;
  final p = [1, 2, 1, 0, 0, 0, 10, u, 0, 0, 0, 0, 0, 0, 0, 0];

  p.setRange(3, 6, IntUtils.toBytes(radix, length: 4).sublist(1));
  p.setRange(8, 12, IntUtils.toBytes(n, length: 4));
  p.setRange(12, 16, IntUtils.toBytes(t, length: 4));
  final prf = _prf;
  prf.update(p);
  prf.update(tweak);
  int padding = ((-(t + b + 1)) % 16 + 16) % 16;

  for (int i = 0; i < padding; i++) {
    prf.update([0]);
  }

  for (int i = 0; i < 10; i++) {
    int e = 9 - i;
    final newPrf = prf.clone();
    newPrf.update([e]);
    newPrf.update(xA.toBytesInternal(radix, b));
    final r = newPrf.output();
    final s = _generateS(r, d);
    final m = (e % 2) == 0 ? u : v;
    final xC = xB.subModExp(s, radix, m);
    xB = xA;
    xA = xC;
    newPrf.clean();
  }
  return x.concat(xA, xB);
}