2026-08-10 00:08:27 +03:00
2026-08-09 23:47:39 +03:00
2026-08-09 23:47:39 +03:00
2026-08-10 00:08:27 +03:00

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)
 

  1. securityDepartmentSignature (Подпись СБ): Доказывает, что ФИО, должность и зоны доступа утверждены Службой Безопасности и не изменены владельцем.
  2. 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
Dart библиотека для системы пропусков
Readme 42 KiB
Languages
Dart 100%