import 'dart:typed_data'; import 'package:potato_pass_core/potato_pass_core.dart'; import 'package:cryptography/cryptography.dart'; import 'package:test/test.dart'; void main() { group('6-и битный колдировщик', () { test('Кодирование и декодирование русской строки', () { const input = 'ИВАНОВ ИВАН ИВАНОВИЧ'; // Кодируем final Uint8List encoded = CompactTextEncoder.encode(input); // Проверяем декодирование final String decoded = CompactTextEncoder.decode(encoded); expect(decoded, equals(input)); }); test('Проверка сжатия размера', () { const input = 'ИВАНОВ ИВАН'; // 11 символов // В UTF-8 кириллица весит 2 байта на символ и займут 22 байта // В 6-битном кодировщике 11 символов округляются до 12 и займут 9 байт final Uint8List encoded = CompactTextEncoder.encode(input); expect(encoded.length, equals(9)); }); test('Обработка строчных букв (автоперевод в верхний регистр)', () { const input = 'Петров Петр'; final Uint8List encoded = CompactTextEncoder.encode(input); final String decoded = CompactTextEncoder.decode(encoded); expect(decoded, equals('ПЕТРОВ ПЕТР')); }); test('Тест некодируемых символов', () { const input = '_.`~!@#\$%^&*()=+\\||//1234567890.';//2 точки и 29 некодирукемый символ (точки чтобы не обрезало) и _ в начале которе final Uint8List encoded = CompactTextEncoder.encode(input); final String decoded = CompactTextEncoder.decode(encoded); expect(decoded, equals('. .'));//2 точки и 29 пробелов (некодируемые символы заменяются на пробелы) }); test('Тест кодируемости всех символов', () { const input = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯABCDEFGHIJKLMNOPQRSTUVWXYZ .-,';//Все неслужебные символы final Uint8List encoded = CompactTextEncoder.encode(input); final String decoded = CompactTextEncoder.decode(encoded); expect(decoded, equals('АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯABCDEFGHIJKLMNOPQRSTUVWXYZ .-,')); }); }); group('Тест полного цикла', () { test('Нормальные данные', () async { // 1. Создаем ключи СБ и Клиента final SimpleKeyPair sbKeyPair = await CryptoService.generateKeyPair(); final Uint8List sbPubKey = await CryptoService.getPublicKeyBytes(sbKeyPair); final SimpleKeyPair clientKeyPair = await CryptoService.generateKeyPair(); final Uint8List clientPubKey = await CryptoService.getPublicKeyBytes(clientKeyPair); // 2. СБ создает маску зон доступа (разрешаем зоны 1, 5, 10) final Uint8List zoneMask = PassPayload.createZoneMask([1, 5, 10]); // 3. Формируем тело пропуска для СБ final passWithoutSignatures = PassPayload( lastName: 'Иванов', firstName: 'Иван', middleName: 'Иванович', position: 'Инженер', department: 'Отдел ИТ', zoneMask: zoneMask, clientPublicKey: clientPubKey, securityDepartmentSignature: Uint8List(64), challengeSignature: Uint8List(64), ); // 4. Служба Безопасности подписывает тело пропуска final Uint8List sbSignedBodyBytes = passWithoutSignatures.getSignedBodyBytes(); final Uint8List securityDepartmentSignature = await CryptoService.sign( message: sbSignedBodyBytes, keyPair: sbKeyPair, ); // 5. Контролер/Сервер дает соль final Uint8List challengeSalt = SaltGenerator.generate(16); // 6. Клиент подписывает (Соль + Подпись СБ) своим приватным ключом final List challengeMessage = [...challengeSalt, ...securityDepartmentSignature]; final Uint8List challengeSignature = await CryptoService.sign( message: challengeMessage, keyPair: clientKeyPair, ); // 7. Собираем итоговый рабочий пропуск final PassPayload fullPass = PassPayload( lastName: 'Иванов', firstName: 'Иван', middleName: 'Иванович', position: 'Инженер', department: 'Отдел ИТ', zoneMask: zoneMask, clientPublicKey: clientPubKey, securityDepartmentSignature: securityDepartmentSignature, challengeSignature: challengeSignature, ); // 8. СЕРИАЛИЗАЦИЯ В БИТЫ final Uint8List binaryPayload = BinarySerializer.serialize(fullPass); // 9. ДЕСЕРИАЛИЗАЦИЯ ИЗ БИТОВ final PassPayload restoredPass = BinarySerializer.deserialize(binaryPayload); // --- ПРОВЕРКА ДАННЫХ --- expect(restoredPass.lastName, equals('ИВАНОВ')); expect(restoredPass.firstName, equals('ИВАН')); expect(restoredPass.position, equals('ИНЖЕНЕР')); expect(restoredPass.department, equals('ОТДЕЛ ИТ')); // --- ПРОВЕРКА ЗОН ДОСТУПА --- expect(restoredPass.hasZoneAccess(1), isTrue); expect(restoredPass.hasZoneAccess(5), isTrue); expect(restoredPass.hasZoneAccess(10), isTrue); expect(restoredPass.hasZoneAccess(2), isFalse); // --- ПРОВЕРКА КРИПТОГРАФИИ (1): ВАЛИДНОСТЬ ПОДПИСИ СЛУЖБЫ БЕЗОПАСНОСТИ --- final bool isSecuritySignatureValid = await CryptoService.verify( message: restoredPass.getSignedBodyBytes(), signatureBytes: restoredPass.securityDepartmentSignature, publicKeyBytes: sbPubKey, ); expect(isSecuritySignatureValid, isTrue); // --- ПРОВЕРКА КРИПТОГРАФИИ (2): ВАЛИДНОСТЬ ПОДПИСИ СОЛИ КЛИЕНТОМ --- final List restoredChallengeMessage = [...challengeSalt, ...restoredPass.securityDepartmentSignature]; final bool isClientSignatureValid = await CryptoService.verify( message: restoredChallengeMessage, signatureBytes: restoredPass.challengeSignature, publicKeyBytes: restoredPass.clientPublicKey, ); expect(isClientSignatureValid, isTrue); }); test('Пустые строки', () async { // 1. Создаем ключи СБ и Клиента final SimpleKeyPair sbKeyPair = await CryptoService.generateKeyPair(); final Uint8List sbPubKey = await CryptoService.getPublicKeyBytes(sbKeyPair); final SimpleKeyPair clientKeyPair = await CryptoService.generateKeyPair(); final Uint8List clientPubKey = await CryptoService.getPublicKeyBytes(clientKeyPair); // 2. СБ создает маску зон доступа (разрешаем зоны 1, 5, 10) final Uint8List zoneMask = PassPayload.createZoneMask([1, 5, 10]); // 3. Формируем тело пропуска для СБ final passWithoutSignatures = PassPayload( lastName: '', firstName: '', middleName: '', position: '', department: '', zoneMask: zoneMask, clientPublicKey: clientPubKey, securityDepartmentSignature: Uint8List(64), challengeSignature: Uint8List(64), ); // 4. Служба Безопасности подписывает тело пропуска final Uint8List sbSignedBodyBytes = passWithoutSignatures.getSignedBodyBytes(); final Uint8List securityDepartmentSignature = await CryptoService.sign( message: sbSignedBodyBytes, keyPair: sbKeyPair, ); // 5. Контролер/Сервер дает соль final Uint8List challengeSalt = SaltGenerator.generate(16); // 6. Клиент подписывает (Соль + Подпись СБ) своим приватным ключом final List challengeMessage = [...challengeSalt, ...securityDepartmentSignature]; final Uint8List challengeSignature = await CryptoService.sign( message: challengeMessage, keyPair: clientKeyPair, ); // 7. Собираем итоговый рабочий пропуск final PassPayload fullPass = PassPayload( lastName: '', firstName: '', middleName: '', position: '', department: '', zoneMask: zoneMask, clientPublicKey: clientPubKey, securityDepartmentSignature: securityDepartmentSignature, challengeSignature: challengeSignature, ); // 8. СЕРИАЛИЗАЦИЯ В БИТЫ final Uint8List binaryPayload = BinarySerializer.serialize(fullPass); // 9. ДЕСЕРИАЛИЗАЦИЯ ИЗ БИТОВ final PassPayload restoredPass = BinarySerializer.deserialize(binaryPayload); // --- ПРОВЕРКА ДАННЫХ --- expect(restoredPass.lastName, equals('')); expect(restoredPass.firstName, equals('')); expect(restoredPass.position, equals('')); expect(restoredPass.department, equals('')); // --- ПРОВЕРКА ЗОН ДОСТУПА --- expect(restoredPass.hasZoneAccess(1), isTrue); expect(restoredPass.hasZoneAccess(5), isTrue); expect(restoredPass.hasZoneAccess(10), isTrue); expect(restoredPass.hasZoneAccess(2), isFalse); // --- ПРОВЕРКА КРИПТОГРАФИИ (1): ВАЛИДНОСТЬ ПОДПИСИ СЛУЖБЫ БЕЗОПАСНОСТИ --- final bool isSecuritySignatureValid = await CryptoService.verify( message: restoredPass.getSignedBodyBytes(), signatureBytes: restoredPass.securityDepartmentSignature, publicKeyBytes: sbPubKey, ); expect(isSecuritySignatureValid, isTrue); // --- ПРОВЕРКА КРИПТОГРАФИИ (2): ВАЛИДНОСТЬ ПОДПИСИ СОЛИ КЛИЕНТОМ --- final List restoredChallengeMessage = [...challengeSalt, ...restoredPass.securityDepartmentSignature]; final bool isClientSignatureValid = await CryptoService.verify( message: restoredChallengeMessage, signatureBytes: restoredPass.challengeSignature, publicKeyBytes: restoredPass.clientPublicKey, ); expect(isClientSignatureValid, isTrue); }); test('Пустые зоны', () async { // 1. Создаем ключи СБ и Клиента final SimpleKeyPair sbKeyPair = await CryptoService.generateKeyPair(); final Uint8List sbPubKey = await CryptoService.getPublicKeyBytes(sbKeyPair); final SimpleKeyPair clientKeyPair = await CryptoService.generateKeyPair(); final Uint8List clientPubKey = await CryptoService.getPublicKeyBytes(clientKeyPair); // 2. Заполняем пустые зоны final Uint8List zoneMask = PassPayload.createZoneMask([]); // 3. Формируем тело пропуска для СБ final passWithoutSignatures = PassPayload( lastName: 'Иванов', firstName: 'Иван', middleName: 'Иванович', position: 'Инженер', department: 'Отдел ИТ', zoneMask: zoneMask, clientPublicKey: clientPubKey, securityDepartmentSignature: Uint8List(64), challengeSignature: Uint8List(64), ); // 4. Служба Безопасности подписывает тело пропуска final Uint8List sbSignedBodyBytes = passWithoutSignatures.getSignedBodyBytes(); final Uint8List securityDepartmentSignature = await CryptoService.sign( message: sbSignedBodyBytes, keyPair: sbKeyPair, ); // 5. Контролер/Сервер дает соль final Uint8List challengeSalt = SaltGenerator.generate(16); // 6. Клиент подписывает (Соль + Подпись СБ) своим приватным ключом final List challengeMessage = [...challengeSalt, ...securityDepartmentSignature]; final Uint8List challengeSignature = await CryptoService.sign( message: challengeMessage, keyPair: clientKeyPair, ); // 7. Собираем итоговый рабочий пропуск final PassPayload fullPass = PassPayload( lastName: 'Иванов', firstName: 'Иван', middleName: 'Иванович', position: 'Инженер', department: 'Отдел ИТ', zoneMask: zoneMask, clientPublicKey: clientPubKey, securityDepartmentSignature: securityDepartmentSignature, challengeSignature: challengeSignature, ); // 8. СЕРИАЛИЗАЦИЯ В БИТЫ final Uint8List binaryPayload = BinarySerializer.serialize(fullPass); // 9. ДЕСЕРИАЛИЗАЦИЯ ИЗ БИТОВ final PassPayload restoredPass = BinarySerializer.deserialize(binaryPayload); // --- ПРОВЕРКА ДАННЫХ --- expect(restoredPass.lastName, equals('ИВАНОВ')); expect(restoredPass.firstName, equals('ИВАН')); expect(restoredPass.position, equals('ИНЖЕНЕР')); expect(restoredPass.department, equals('ОТДЕЛ ИТ')); // --- ПРОВЕРКА ЗОН ДОСТУПА --- expect(restoredPass.hasZoneAccess(1), isFalse); expect(restoredPass.hasZoneAccess(2), isFalse); expect(restoredPass.hasZoneAccess(3), isFalse); expect(restoredPass.hasZoneAccess(4), isFalse); expect(restoredPass.hasZoneAccess(5), isFalse); expect(restoredPass.hasZoneAccess(6), isFalse); expect(restoredPass.hasZoneAccess(7), isFalse); // --- ПРОВЕРКА КРИПТОГРАФИИ (1): ВАЛИДНОСТЬ ПОДПИСИ СЛУЖБЫ БЕЗОПАСНОСТИ --- final bool isSecuritySignatureValid = await CryptoService.verify( message: restoredPass.getSignedBodyBytes(), signatureBytes: restoredPass.securityDepartmentSignature, publicKeyBytes: sbPubKey, ); expect(isSecuritySignatureValid, isTrue); // --- ПРОВЕРКА КРИПТОГРАФИИ (2): ВАЛИДНОСТЬ ПОДПИСИ СОЛИ КЛИЕНТОМ --- final List restoredChallengeMessage = [...challengeSalt, ...restoredPass.securityDepartmentSignature]; final bool isClientSignatureValid = await CryptoService.verify( message: restoredChallengeMessage, signatureBytes: restoredPass.challengeSignature, publicKeyBytes: restoredPass.clientPublicKey, ); expect(isClientSignatureValid, isTrue); }); }); }