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 implicitBytes = implicit ?? <int>[];
  final footer = package.footer ?? <int>[];

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

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

  // 6. Создаем payload согласно спецификации PASETO v4.local
  // payload = nonce || (ciphertext + MAC)
  final cipherTextWithMac = Uint8List.fromList(cipherText + macBytes);
  final payloadBytes = Uint8List.fromList(nonce + cipherTextWithMac);

  // 7. Возвращаем PayloadLocal согласно спецификации PASETO v4.local
  return PayloadLocal(
    nonce: Mac(nonce), // Используем Mac для nonce
    secretBox: SecretBox(cipherTextWithMac,
        nonce: Uint8List.fromList(counterNonce.sublist(0, 12)),
        mac: Mac(macBytes)),
    mac: null, // MAC включен в secretBox.cipherText
    payloadBytes: payloadBytes, // Сохраняем сырые байты payload
  );
}