331 lines
15 KiB
Dart
331 lines
15 KiB
Dart
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<int> 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<int> 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<int> 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<int> 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<int> 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<int> restoredChallengeMessage = [...challengeSalt, ...restoredPass.securityDepartmentSignature];
|
||
final bool isClientSignatureValid = await CryptoService.verify(
|
||
message: restoredChallengeMessage,
|
||
signatureBytes: restoredPass.challengeSignature,
|
||
publicKeyBytes: restoredPass.clientPublicKey,
|
||
);
|
||
expect(isClientSignatureValid, isTrue);
|
||
});
|
||
|
||
});
|
||
|
||
} |