paseto_dart
Dart неофициальная реализация PASETO (Platform-Agnostic Security Tokens) — современная криптографически защищенная альтернатива JWT.
Warning
Библиотека находится в стадии разработки и может содержать ошибки. Используйте на свой страх и риск.
Что такое PASETO
PASETO — это протокол для создания безопасных токенов доступа, разработанный в 2018 году как альтернатива JWT/JOSE, устраняющий его основные недостатки безопасности:
- Фиксированный набор алгоритмов в каждой версии — устраняет уязвимости, связанные с выбором алгоритма
- Строгое разделение режимов на
local
(шифрование) иpublic
(подпись) — предотвращает путаницу - Строгая спецификация формата — минимизирует ошибки реализации
- Современная криптография — использует XChaCha20 и BLAKE2b
📋 Поддерживаемые версии PASETO
Note
Данная библиотека поддерживает только PASETO v4, который является рекомендуемым для новых проектов.
Версия | Поддержка | Описание |
---|---|---|
v1 | ❌ | Legacy (RSA + AES-CTR) - не поддерживается |
v2 | ❌ | General purpose (NaCl/libsodium) - не поддерживается |
v3 | ❌ | NIST-compliant - не поддерживается |
v4 | ✅ | Modern (рекомендуется) |
PASERK | ✅ | PASETO формат представления ключей (v4, включая PIE, password-based и seal) |
🧾 Что такое PASERK
PASERK (Platform-Agnostic Serialized Keys) — официальный стандарт представления ключей для PASETO. Он описывает, как безопасно кодировать симметричные и асимметричные ключи, обмениваться ими и выполнять «обёртку» (wrapping) и «запечатывание» (sealing) секретов.
В библиотеке реализованы все типы PASERK v4:
k4.local
иk4.secret
— базовые сериализации симметричных и секретных ключей;k4.local-wrap
иk4.secret-wrap
— PIE-обёртки поверх ключей, позволяющие хранить их в зашифрованном виде;k4.local-pw
иk4.secret-pw
— password-based (Argon2id + XChaCha20) преобразования для безопасного хранения по паролю;- По умолчанию Argon2id запускается с параметрами
timeCost = 2/3
,memoryCost = 64 MiB
,parallelism = 1
, но их можно увеличить или уменьшить в зависимости от требований среды выполнения; k4.seal
— асимметричное запечатывание ключа на публичный ключ получателя.
Пример сериализации и восстановления ключа
import 'package:paseto_dart/paseto_dart.dart';
void main() {
final localKey = K4LocalKey.generate();
// Сериализация для хранения (k4.local)
final serialized = localKey.encode();
// Восстановление из строки
final restored = K4LocalKey.fromString(serialized);
assert(restored.encode() == serialized);
}
Дополнительные примеры использования PIE-обёрток, password-based преобразований и k4.seal
можно найти в тестах test/paserk
.
🔐 Быстрый старт
Примеры использования библиотеки можно найти в example.
📚 Руководство по выбору типа токена
Тип токена | Когда использовать | Преимущества |
---|---|---|
local | - Защита чувствительных данных - Хранение секретов |
- Данные зашифрованы - Доступны только с ключом |
public | - Авторизация - Аутентификация |
- Проверка без секретного ключа - Совместим с подходом JWT |
🔑 Лучшие практики
- Включайте срок действия (
exp
) в токены авторизации - Всегда проверяйте версию токена перед использованием
- Храните ключи в безопасности
- Для токенов авторизации используйте режим
public
- Для защиты данных используйте режим
local
⚠️ Правильная реализация авторизации
Важно! Токены PASETO не предназначены для повторного использования в качестве долгосрочных токенов доступа.
PASETO не имеет встроенной защиты от атак повторного воспроизведения (повторное использование токена). Если токен перехвачен, злоумышленник может использовать его до истечения срока действия.
Рекомендуемая архитектура авторизации
- Используйте двухуровневую систему токенов:
- Краткосрочные токены доступа PASETO (5-15 минут)
- Долгосрочные токены обновления (хранятся в базе данных сервера)
// Пример создания токенов в двухуровневой системе авторизации
Future<AuthTokens> createAuthTokens(User user) async {
// Краткосрочный токен доступа
final accessTokenData = {
'sub': user.id,
'exp': DateTime.now().add(Duration(minutes: 15)).millisecondsSinceEpoch ~/ 1000,
'jti': generateUniqueId(), // ID токена для защиты от повторного использования
};
// Создаем пакет с данными
final package = Package(
content: utf8.encode(jsonEncode(accessTokenData)),
);
// Подписываем с помощью PublicV4
final signedPayload = await PublicV4.sign(
package,
keyPair: authKeyPair,
);
// Создаем токен
final token = Token(
header: PublicV4.header,
payload: signedPayload,
footer: null,
);
// Генерируем токен обновления и сохраняем его в базе данных
final refreshToken = generateSecureRandomString();
await storeRefreshTokenInDatabase(user.id, refreshToken);
return AuthTokens(
accessToken: token.toTokenString,
refreshToken: refreshToken,
);
}
-
Добавьте проверку состояния на сервере:
- Храните ID использованных токенов
- Поддерживайте белый/черный список активных сессий
- Реализуйте механизм немедленного отзыва токена
-
Для критических операций используйте одноразовые токены:
- Добавьте уникальный идентификатор (
jti
) в полезную нагрузку - Проверяйте на сервере, был ли токен уже использован
- После использования добавляйте ID токена в список использованных токенов
- Добавьте уникальный идентификатор (
Чего не следует делать
❌ Не используйте PASETO как постоянные токены доступа:
// НЕПРАВИЛЬНО: использование долгосрочного токена для всех запросов
final userData = {
'sub': 'user123',
'exp': DateTime.now().add(Duration(days: 30)).millisecondsSinceEpoch ~/ 1000
};
❌ Не полагайтесь только на срок действия токена для обеспечения безопасности:
// НЕПРАВИЛЬНО: нет дополнительных проверок на стороне сервера
if (tokenData['exp'] > currentTimestamp) {
// Предоставление доступа только на основе срока действия
grantAccess();
}
⚙️ Реализации PASETO на других языках
PASETO имеет реализации на многих языках. Вы можете найти их на официальном сайте.
📖 Полезные ссылки
🧪 Тестирование
Для запуска тестов требуется Dart SDK и Python 3.10 с установленным пакетом python-paseto
(библиотека пока не поддерживает Python 3.11+).
python -m pip install -r tool/python_requirements.txt
dart pub get
dart test
Интеграционные тесты взаимодействуют с библиотекой python-paseto и проверяют совместимость реализаций.
Libraries
- blake2/_index
- blake2/blake2b_pointycastle
- blake2/byte_utils
- blake2/digest
- blake2/ufixnum
- chacha20/_index
- chacha20/chacha20_pointycastle
- chacha20/xchacha20
- models/_index
- models/header
- models/message
- models/package
- models/payload
- models/purpose
- models/token
- models/version
- paserk/_index
- paserk/k4_lid
- paserk/k4_local
- paserk/k4_local_pw
- paserk/k4_local_wrap
- paserk/k4_pid
- paserk/k4_public
- paserk/k4_seal
- paserk/k4_secret
- paserk/k4_secret_pw
- paserk/k4_secret_wrap
- paserk/k4_sid
- paserk/paserk_key
- paseto_dart
- utils/_index
- utils/base64_ext
- utils/pae
- versions/local_v4
- versions/public_v4