PotatoPassCore
Core библиотека на Dart для экосистемы PotatoPass (электронные пропуска и системы контроля доступа).
Содержит реализацию бинарного протокола v1.0, 6-битную оптимизацию текста, генерацию асимметричных ключей и подписей Ed25519, а также средства сериализации/десериализации.
Подключение к проектам
Добавление заывисимости в pubspec.yaml:
dependencies:
potato_pass_core:
git:
url: https://git.mr-potato.ru/PotatoPass/PotatoPassCore.git
ref: stable
Спецификация Бинарного Протокола
Формат разработан для сверхплотной упаковки данных пропуска в 2D-коды
Структура Байтового Массива (Binary Layout)
| Секция | Длина (Байты) | Описание |
|---|---|---|
| 1. Текстовый блок | Динамическая (~20–45B) | 5 полей текста с 1-байтовым префиксом длины (6-битное кодирование) |
| 2. Блок доступа | Динамическая (~3–33B) | 1B длина маски N + N байт битовой маски зон (1 \text{ бит} = 1 \text{ зона}) |
| 3. Публичный ключ | 32B |
32 байта Ed25519 Public Key клиента (уникальный ID пропуска) |
| 4. Подпись СБ | 64B |
Подпись Службы Безопасности (подписывает секции с 1 по 3) |
| 5. Подпись Соли | 64B |
Подпись Клиента (подписывает Соль (16B) + Подпись СБ (64B)) |
6-битный кодировщик текста (CompactTextEncoder)
Для кириллицы стандартный UTF-8 использует 2 байта (16 бит) на символ. CompactTextEncoder сжимает 4 символа в 3 байта (6 бит на символ), давая 62% экономии места.
Словарь символов (64 значения = 2^6):
0..32 : А Б В Г Д Е Ё Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я
33..58 : A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
59..63 : [Пробел] - . , _ (подчеркивание/заполнитель)
Криптографическая модель подписей (Ed25519)
В системе используются две цифровые подписи для защиты от подделки и копирования:
1. [ Текст + Зоны + PubKey Клиента ] ──────────────► Подпись СБ (64B)
2. [ Challenge Salt (16B) + Подпись СБ (64B) ] ───────────────► Подпись Соли Клиентом (64B)
securityDepartmentSignature(Подпись СБ): Доказывает, что ФИО, должность и зоны доступа утверждены Службой Безопасности и не изменены владельцем.challengeSignature(Подпись Соли): Доказывает, что пропуск предъявляет именно его владелец с помощью своего приватного ключа. Одноразовая соль (16B) сгорает каждые 10 секунд, делая скриншоты и фото кода бесполезными.
Примеры использования API
1. Работа с 6-битным кодировщиком текста
import 'dart:typed_data';
import 'package:potato_pass_core/potato_pass_core.dart';
void main() {
// Упаковка строки в 6-битные байты
final Uint8List encoded = CompactTextEncoder.encode('Иванов Иван');
// Распаковка обратно в строку
final String decoded = CompactTextEncoder.decode(encoded); // "ИВАНОВ ИВАН"
}
2. Генерация ключей и подпись (Ed25519)
import 'dart:typed_data';
import 'package:cryptography/cryptography.dart';
import 'package:potato_pass_core/potato_pass_core.dart';
void main() async {
// Генерация пары ключей
final SimpleKeyPair keyPair = await CryptoService.generateKeyPair();
final Uint8List pubKeyBytes = await CryptoService.getPublicKeyBytes(keyPair);
// Подпись сообщения
final List<int> message = [1, 2, 3, 4, 5];
final Uint8List signature = await CryptoService.sign(
message: message,
keyPair: keyPair,
);
// Проверка подписи
final bool isValid = await CryptoService.verify(
message: message,
signatureBytes: signature,
publicKeyBytes: pubKeyBytes,
);
}
3. Полный цикл сериализации и проверки пропуска
import 'dart:typed_data';
import 'package:potato_pass_core/potato_pass_core.dart';
void main() async {
// Генерация маски зон доступа (разрешаем зоны 1, 5, 10)
final Uint8List zoneMask = PassPayload.createZoneMask([1, 5, 10]);
// Создание объекта пропуска
final pass = PassPayload(
lastName: 'Иванов',
firstName: 'Иван',
middleName: 'Иванович',
position: 'Инженер',
department: 'Отдел ИТ',
zoneMask: zoneMask,
clientPublicKey: clientPubKeyBytes,
securityDepartmentSignature: sbSignatureBytes,
challengeSignature: clientChallengeSigBytes,
);
// Упаковка в байты для DataMatrix / BLE
final Uint8List binaryPayload = BinarySerializer.serialize(pass);
// Распаковка из байтов на стороне Контролера
final PassPayload restoredPass = BinarySerializer.deserialize(binaryPayload);
// Проверка прав доступа в зону 5
if (restoredPass.hasZoneAccess(5)) {
print('Доступ разрешен!');
}
}
Description
Languages
Dart
100%