encrypt static method
Шифрует пакет данных, создавая 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
);
}