encrypt static method

Future<Payload> encrypt(
  1. Package package, {
  2. required SecretKey secretKey,
  3. List<int>? implicit,
})

Шифрует пакет данных, создавая PASETO v4.local токен.

Implementation

static Future<Payload> encrypt(
  Package package, {
  required SecretKey secretKey,
  List<int>? implicit,
}) async {
  // Получаем ключ для шифрования
  final keyBytes = await secretKey.extractBytes();

  // Проверяем размер ключа
  if (keyBytes.length != keyLength) {
    throw ArgumentError(
        'Ключ должен быть $keyLength байт, получено: ${keyBytes.length}');
  }

  // Генерируем случайный nonce (32 байта)
  final nonce = Uint8List(nonceLength);
  final random = Random.secure();
  for (var i = 0; i < nonceLength; i++) {
    nonce[i] = random.nextInt(256);
  }

  // 1. Генерируем ключи шифрования (Ek) и аутентификации (Ak)
  final encKeys = await _deriveKeys(keyBytes, nonce);
  final encryptionKey = encKeys.encryptionKey;
  final counterNonce = encKeys.counterNonce;
  final authKey = encKeys.authKey;

  // 2. Шифруем сообщение с помощью нашей реализации XChaCha20
  // Создаем экземпляр нашей реализации XChaCha20
  final xchacha = XChaCha20();

  // Преобразуем входные данные в правильный формат
  final keyParam = KeyParameter(Uint8List.fromList(encryptionKey));

  // ВАЖНО: Для XChaCha20 нужен 24-байтный nonce
  // Используем все 24 байта из counterNonce
  final nonceBytes = Uint8List.fromList(counterNonce.sublist(0, 24));

  // Инициализируем с ключом и nonce для шифрования
  xchacha.init(true, ParametersWithIV<KeyParameter>(keyParam, nonceBytes));

  // Шифруем данные
  final cipherText = xchacha.process(Uint8List.fromList(package.content));

  // 3. Подготавливаем данные для аутентификации (PAE)
  final headerBytes = utf8.encode(header.toTokenString);
  final implicitBytes = implicit ?? <int>[];
  final footer = package.footer ?? <int>[];

  // 4. PAE(h, n, c, f, i)
  final preAuth = _pae([
    headerBytes, // h - заголовок
    nonce, // n - nonce
    cipherText, // c - шифротекст
    footer, // f - футер (опциональный)
    implicitBytes, // i - implicit assertion (опциональный)
  ]);

  // 5. Вычисляем BLAKE2b-MAC с помощью ключа аутентификации
  final macBytes = _computeMac(preAuth, authKey);
  final mac = Mac(macBytes);

  // 6. Объединяем данные для токена
  final secretBox = SecretBox(
    cipherText,
    nonce: nonceBytes,
    mac: mac,
  );

  final payload = PayloadLocal(
    nonce: Mac(nonce),
    secretBox: secretBox,
    mac: mac,
  );

  return payload;
}