update
This commit is contained in:
@@ -1,162 +0,0 @@
|
|||||||
// Пример использования новой асинхронной системы очистки
|
|
||||||
import { EnhancedSecureWebRTCManager } from './src/network/EnhancedSecureWebRTCManager.js';
|
|
||||||
|
|
||||||
// Создание менеджера WebRTC с асинхронной очисткой
|
|
||||||
const webrtcManager = new EnhancedSecureWebRTCManager(
|
|
||||||
(message) => console.log('Received:', message),
|
|
||||||
(status) => console.log('Status:', status),
|
|
||||||
(keyData) => console.log('Key exchange:', keyData),
|
|
||||||
(verificationData) => console.log('Verification required:', verificationData)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Демонстрация асинхронной очистки
|
|
||||||
async function demonstrateAsyncCleanup() {
|
|
||||||
console.log('=== Демонстрация асинхронной системы очистки ===');
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 1. Демонстрация естественной очистки памяти
|
|
||||||
console.log('\n1. Тест естественной очистки памяти...');
|
|
||||||
const startTime = performance.now();
|
|
||||||
|
|
||||||
await webrtcManager._performNaturalCleanup();
|
|
||||||
|
|
||||||
const endTime = performance.now();
|
|
||||||
console.log(`✅ Естественная очистка завершена за ${(endTime - startTime).toFixed(2)}ms`);
|
|
||||||
console.log(' - Без блокировки UI');
|
|
||||||
console.log(' - Без принудительного window.gc()');
|
|
||||||
console.log(' - Использует естественные циклы сборки мусора');
|
|
||||||
|
|
||||||
// 2. Демонстрация асинхронного sleep
|
|
||||||
console.log('\n2. Тест асинхронного sleep (замена busy-wait)...');
|
|
||||||
const sleepStart = performance.now();
|
|
||||||
|
|
||||||
await webrtcManager._asyncSleep(50); // 50ms без блокировки
|
|
||||||
|
|
||||||
const sleepEnd = performance.now();
|
|
||||||
console.log(`✅ Асинхронный sleep завершен за ${(sleepEnd - sleepStart).toFixed(2)}ms`);
|
|
||||||
console.log(' - UI остается отзывчивым');
|
|
||||||
console.log(' - Нет busy-wait циклов');
|
|
||||||
|
|
||||||
// 3. Демонстрация батчевых операций
|
|
||||||
console.log('\n3. Тест батчевых операций...');
|
|
||||||
const batchStart = performance.now();
|
|
||||||
|
|
||||||
// Создаем массив "тяжелых" операций
|
|
||||||
const heavyOperations = Array.from({ length: 100 }, (_, i) =>
|
|
||||||
async () => {
|
|
||||||
// Симуляция тяжелой операции
|
|
||||||
await webrtcManager._asyncSleep(1);
|
|
||||||
return `operation_${i}`;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const results = await webrtcManager._batchAsyncOperation(heavyOperations, 10, 2);
|
|
||||||
|
|
||||||
const batchEnd = performance.now();
|
|
||||||
console.log(`✅ Батчевые операции завершены за ${(batchEnd - batchStart).toFixed(2)}ms`);
|
|
||||||
console.log(` - Обработано ${results.length} операций`);
|
|
||||||
console.log(' - UI не блокировался благодаря батчингу');
|
|
||||||
console.log(' - Задержки между батчами предотвращают зависание');
|
|
||||||
|
|
||||||
// 4. Демонстрация WebWorker очистки (если доступен)
|
|
||||||
console.log('\n4. Тест WebWorker очистки...');
|
|
||||||
const workerStart = performance.now();
|
|
||||||
|
|
||||||
const cleanupData = {
|
|
||||||
type: 'cleanup_arrays',
|
|
||||||
data: { count: 1000 }
|
|
||||||
};
|
|
||||||
|
|
||||||
const workerResult = await webrtcManager._performHeavyCleanup(cleanupData);
|
|
||||||
|
|
||||||
const workerEnd = performance.now();
|
|
||||||
console.log(`✅ WebWorker очистка завершена за ${(workerEnd - workerStart).toFixed(2)}ms`);
|
|
||||||
console.log(` - Результат: ${JSON.stringify(workerResult)}`);
|
|
||||||
console.log(' - Тяжелые операции выполнены в фоновом потоке');
|
|
||||||
console.log(' - Основной поток не блокировался');
|
|
||||||
|
|
||||||
// 5. Демонстрация запланированной очистки
|
|
||||||
console.log('\n5. Тест запланированной очистки...');
|
|
||||||
const scheduleStart = performance.now();
|
|
||||||
|
|
||||||
const cleanupPromise = webrtcManager._scheduleAsyncCleanup(async () => {
|
|
||||||
console.log(' 🧹 Выполняется запланированная очистка...');
|
|
||||||
await webrtcManager._asyncSleep(20);
|
|
||||||
console.log(' ✅ Запланированная очистка завершена');
|
|
||||||
}, 10); // Задержка 10ms
|
|
||||||
|
|
||||||
await cleanupPromise;
|
|
||||||
|
|
||||||
const scheduleEnd = performance.now();
|
|
||||||
console.log(`✅ Запланированная очистка завершена за ${(scheduleEnd - scheduleStart).toFixed(2)}ms`);
|
|
||||||
console.log(' - Очистка выполнена с задержкой');
|
|
||||||
console.log(' - Не блокирует текущий поток выполнения');
|
|
||||||
|
|
||||||
// 6. Сравнение производительности
|
|
||||||
console.log('\n6. Сравнение с старой системой...');
|
|
||||||
console.log('📊 Преимущества новой системы:');
|
|
||||||
console.log(' ✅ Нет busy-wait циклов');
|
|
||||||
console.log(' ✅ Нет принудительного window.gc()');
|
|
||||||
console.log(' ✅ UI остается отзывчивым');
|
|
||||||
console.log(' ✅ WebWorker для тяжелых операций');
|
|
||||||
console.log(' ✅ Батчинг предотвращает блокировки');
|
|
||||||
console.log(' ✅ Естественная сборка мусора');
|
|
||||||
|
|
||||||
console.log('\n❌ Проблемы старой системы (исправлены):');
|
|
||||||
console.log(' ❌ while (Date.now() - start < 10) {} - busy-wait');
|
|
||||||
console.log(' ❌ window.gc() - принудительная сборка мусора');
|
|
||||||
console.log(' ❌ Блокировка UI при очистке');
|
|
||||||
console.log(' ❌ Синхронные тяжелые операции');
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Ошибка демонстрации:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Демонстрация мониторинга производительности
|
|
||||||
async function demonstratePerformanceMonitoring() {
|
|
||||||
console.log('\n=== Мониторинг производительности ===');
|
|
||||||
|
|
||||||
// Мониторинг времени выполнения операций
|
|
||||||
const operations = [
|
|
||||||
{ name: 'Естественная очистка', fn: () => webrtcManager._performNaturalCleanup() },
|
|
||||||
{ name: 'Асинхронный sleep 10ms', fn: () => webrtcManager._asyncSleep(10) },
|
|
||||||
{ name: 'Батчевая операция', fn: () => webrtcManager._batchAsyncOperation([
|
|
||||||
async () => 'test1',
|
|
||||||
async () => 'test2',
|
|
||||||
async () => 'test3'
|
|
||||||
], 2, 1) }
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const operation of operations) {
|
|
||||||
const start = performance.now();
|
|
||||||
await operation.fn();
|
|
||||||
const end = performance.now();
|
|
||||||
|
|
||||||
console.log(`⏱️ ${operation.name}: ${(end - start).toFixed(2)}ms`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверка доступности WebWorker
|
|
||||||
if (typeof Worker !== 'undefined') {
|
|
||||||
console.log('✅ WebWorker доступен - тяжелые операции будут выполняться в фоне');
|
|
||||||
} else {
|
|
||||||
console.log('⚠️ WebWorker недоступен - fallback на батчинг в основном потоке');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Запуск демонстрации
|
|
||||||
console.log('🚀 Запуск демонстрации асинхронной системы очистки...');
|
|
||||||
|
|
||||||
demonstrateAsyncCleanup()
|
|
||||||
.then(() => demonstratePerformanceMonitoring())
|
|
||||||
.then(() => {
|
|
||||||
console.log('\n🎉 Демонстрация завершена успешно!');
|
|
||||||
console.log('💡 Новая система обеспечивает:');
|
|
||||||
console.log(' • Отзывчивый UI');
|
|
||||||
console.log(' • Эффективную очистку памяти');
|
|
||||||
console.log(' • Отсутствие блокировок');
|
|
||||||
console.log(' • Использование WebWorker для тяжелых операций');
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('❌ Ошибка демонстрации:', error);
|
|
||||||
});
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
// Пример использования новой системы мастер-ключей
|
|
||||||
import { EnhancedSecureWebRTCManager } from './src/network/EnhancedSecureWebRTCManager.js';
|
|
||||||
|
|
||||||
// Создание менеджера WebRTC
|
|
||||||
const webrtcManager = new EnhancedSecureWebRTCManager(
|
|
||||||
(message) => console.log('Received:', message),
|
|
||||||
(status) => console.log('Status:', status),
|
|
||||||
(keyData) => console.log('Key exchange:', keyData),
|
|
||||||
(verificationData) => console.log('Verification required:', verificationData)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Настройка callback для запроса пароля
|
|
||||||
webrtcManager.setMasterKeyPasswordCallback((isRetry, callback) => {
|
|
||||||
// В реальном приложении здесь должен быть UI для ввода пароля
|
|
||||||
const message = isRetry ?
|
|
||||||
'Неверный пароль. Введите мастер-пароль повторно:' :
|
|
||||||
'Введите мастер-пароль для разблокировки безопасного хранилища:';
|
|
||||||
|
|
||||||
// Пример с prompt (в реальном приложении используйте модальное окно)
|
|
||||||
const password = prompt(message);
|
|
||||||
callback(password);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Настройка callback для истечения сессии
|
|
||||||
webrtcManager.setMasterKeySessionExpiredCallback((reason) => {
|
|
||||||
console.warn(`Сессия мастер-ключа истекла: ${reason}`);
|
|
||||||
|
|
||||||
// Уведомить пользователя
|
|
||||||
if (reason === 'inactivity') {
|
|
||||||
alert('Сессия заблокирована из-за неактивности. Потребуется повторный ввод пароля.');
|
|
||||||
} else if (reason === 'timeout') {
|
|
||||||
alert('Сессия истекла по таймауту. Потребуется повторный ввод пароля.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Проверка статуса мастер-ключа
|
|
||||||
console.log('Мастер-ключ разблокирован:', webrtcManager.isMasterKeyUnlocked());
|
|
||||||
console.log('Статус сессии:', webrtcManager.getMasterKeySessionStatus());
|
|
||||||
|
|
||||||
// Ручная блокировка мастер-ключа
|
|
||||||
// webrtcManager.lockMasterKey();
|
|
||||||
|
|
||||||
// Пример использования в реальном приложении:
|
|
||||||
async function initializeSecureConnection() {
|
|
||||||
try {
|
|
||||||
// При первом обращении к зашифрованным ключам будет запрошен пароль
|
|
||||||
const offer = await webrtcManager.createSecureOffer();
|
|
||||||
console.log('Secure offer created:', offer);
|
|
||||||
|
|
||||||
// Мастер-ключ теперь разблокирован и будет автоматически заблокирован:
|
|
||||||
// - через 15 минут бездействия
|
|
||||||
// - через 5 минут после потери фокуса окна
|
|
||||||
// - при ручном вызове lockMasterKey()
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to create secure offer:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Запуск примера
|
|
||||||
initializeSecureConnection();
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
// Пример использования новой системы персистентного хранения ключей
|
|
||||||
import {
|
|
||||||
EnhancedSecureWebRTCManager,
|
|
||||||
SecureMasterKeyManager,
|
|
||||||
SecureIndexedDBWrapper,
|
|
||||||
SecurePersistentKeyStorage
|
|
||||||
} from './src/network/EnhancedSecureWebRTCManager.js';
|
|
||||||
|
|
||||||
// Создание менеджера WebRTC с персистентным хранением
|
|
||||||
const webrtcManager = new EnhancedSecureWebRTCManager(
|
|
||||||
(message) => console.log('Received:', message),
|
|
||||||
(status) => console.log('Status:', status),
|
|
||||||
(keyData) => console.log('Key exchange:', keyData),
|
|
||||||
(verificationData) => console.log('Verification required:', verificationData)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Настройка callback для запроса пароля
|
|
||||||
webrtcManager.setMasterKeyPasswordCallback((isRetry, callback) => {
|
|
||||||
const message = isRetry ?
|
|
||||||
'Неверный пароль. Введите мастер-пароль повторно:' :
|
|
||||||
'Введите мастер-пароль для разблокировки хранилища ключей:';
|
|
||||||
|
|
||||||
// В реальном приложении используйте безопасный UI
|
|
||||||
const password = prompt(message);
|
|
||||||
callback(password);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Настройка callback для истечения сессии
|
|
||||||
webrtcManager.setMasterKeySessionExpiredCallback((reason) => {
|
|
||||||
console.warn(`Сессия мастер-ключа истекла: ${reason}`);
|
|
||||||
alert(`Сессия заблокирована: ${reason}. Потребуется повторный ввод пароля.`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Демонстрация работы с персистентным хранением
|
|
||||||
async function demonstratePersistentStorage() {
|
|
||||||
try {
|
|
||||||
console.log('=== Демонстрация персистентного хранения ключей ===');
|
|
||||||
|
|
||||||
// 1. Создание и сохранение extractable ключа
|
|
||||||
console.log('\n1. Создание extractable ключа для демонстрации...');
|
|
||||||
const testKey = await crypto.subtle.generateKey(
|
|
||||||
{
|
|
||||||
name: 'AES-GCM',
|
|
||||||
length: 256
|
|
||||||
},
|
|
||||||
true, // extractable = true для персистентного хранения
|
|
||||||
['encrypt', 'decrypt']
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2. Сохранение ключа (автоматически зашифруется и сохранится в IndexedDB)
|
|
||||||
console.log('2. Сохранение ключа в персистентное хранилище...');
|
|
||||||
const keyId = 'demo_persistent_key_' + Date.now();
|
|
||||||
const stored = await webrtcManager._secureKeyStorage.storeKey(keyId, testKey, {
|
|
||||||
purpose: 'demonstration',
|
|
||||||
algorithm: 'AES-GCM'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (stored) {
|
|
||||||
console.log('✅ Ключ успешно сохранен в зашифрованном виде в IndexedDB');
|
|
||||||
} else {
|
|
||||||
console.log('❌ Ошибка сохранения ключа');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Получение статистики хранилища
|
|
||||||
console.log('\n3. Статистика хранилища:');
|
|
||||||
const stats = await webrtcManager._secureKeyStorage.getStorageStats();
|
|
||||||
console.log('Статистика:', JSON.stringify(stats, null, 2));
|
|
||||||
|
|
||||||
// 4. Список всех ключей
|
|
||||||
console.log('\n4. Список всех ключей:');
|
|
||||||
const allKeys = await webrtcManager._secureKeyStorage.listAllKeys();
|
|
||||||
console.log('Ключи:', JSON.stringify(allKeys, null, 2));
|
|
||||||
|
|
||||||
// 5. Симуляция перезапуска приложения (очистка памяти)
|
|
||||||
console.log('\n5. Симуляция перезапуска приложения...');
|
|
||||||
webrtcManager._secureKeyStorage._keyReferences.clear();
|
|
||||||
console.log('Память очищена. Ключи остались только в IndexedDB.');
|
|
||||||
|
|
||||||
// 6. Восстановление ключа из IndexedDB
|
|
||||||
console.log('\n6. Восстановление ключа из IndexedDB...');
|
|
||||||
const restoredKey = await webrtcManager._secureKeyStorage.retrieveKey(keyId);
|
|
||||||
|
|
||||||
if (restoredKey) {
|
|
||||||
console.log('✅ Ключ успешно восстановлен из IndexedDB как non-extractable');
|
|
||||||
console.log('Тип ключа:', restoredKey.type);
|
|
||||||
console.log('Алгоритм:', restoredKey.algorithm.name);
|
|
||||||
console.log('Extractable:', restoredKey.extractable); // Должно быть false
|
|
||||||
} else {
|
|
||||||
console.log('❌ Ошибка восстановления ключа');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. Тест шифрования с восстановленным ключом
|
|
||||||
console.log('\n7. Тест шифрования с восстановленным ключом...');
|
|
||||||
const testData = new TextEncoder().encode('Тестовые данные для шифрования');
|
|
||||||
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
||||||
|
|
||||||
const encrypted = await crypto.subtle.encrypt(
|
|
||||||
{ name: 'AES-GCM', iv },
|
|
||||||
restoredKey,
|
|
||||||
testData
|
|
||||||
);
|
|
||||||
|
|
||||||
const decrypted = await crypto.subtle.decrypt(
|
|
||||||
{ name: 'AES-GCM', iv },
|
|
||||||
restoredKey,
|
|
||||||
encrypted
|
|
||||||
);
|
|
||||||
|
|
||||||
const decryptedText = new TextDecoder().decode(decrypted);
|
|
||||||
console.log('✅ Шифрование/расшифровка успешно:', decryptedText);
|
|
||||||
|
|
||||||
// 8. Очистка демонстрационных данных
|
|
||||||
console.log('\n8. Очистка демонстрационных данных...');
|
|
||||||
await webrtcManager._secureKeyStorage.deleteKey(keyId);
|
|
||||||
console.log('✅ Демонстрационный ключ удален');
|
|
||||||
|
|
||||||
console.log('\n=== Демонстрация завершена ===');
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Ошибка демонстрации:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Демонстрация безопасности
|
|
||||||
async function demonstrateSecurity() {
|
|
||||||
console.log('\n=== Демонстрация безопасности ===');
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Попытка прямого доступа к IndexedDB
|
|
||||||
const request = indexedDB.open('SecureKeyStorage');
|
|
||||||
request.onsuccess = (event) => {
|
|
||||||
const db = event.target.result;
|
|
||||||
const transaction = db.transaction(['encrypted_keys'], 'readonly');
|
|
||||||
const store = transaction.objectStore('encrypted_keys');
|
|
||||||
const getAllRequest = store.getAll();
|
|
||||||
|
|
||||||
getAllRequest.onsuccess = () => {
|
|
||||||
const keys = getAllRequest.result;
|
|
||||||
console.log('🔍 Прямой доступ к IndexedDB:');
|
|
||||||
|
|
||||||
if (keys.length > 0) {
|
|
||||||
const firstKey = keys[0];
|
|
||||||
console.log('📦 Найден зашифрованный ключ:');
|
|
||||||
console.log('- ID:', firstKey.keyId);
|
|
||||||
console.log('- Зашифрованные данные (первые 20 байт):',
|
|
||||||
Array.from(firstKey.encryptedData.slice(0, 20))
|
|
||||||
.map(b => b.toString(16).padStart(2, '0')).join(' '));
|
|
||||||
console.log('- IV:', Array.from(firstKey.iv)
|
|
||||||
.map(b => b.toString(16).padStart(2, '0')).join(' '));
|
|
||||||
console.log('✅ Данные зашифрованы - невозможно извлечь JWK без мастер-ключа!');
|
|
||||||
} else {
|
|
||||||
console.log('📭 Нет сохраненных ключей в IndexedDB');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Ошибка проверки безопасности:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Запуск демонстрации
|
|
||||||
console.log('Запуск демонстрации персистентного хранения ключей...');
|
|
||||||
console.log('При первом запуске будет запрошен мастер-пароль.');
|
|
||||||
|
|
||||||
// Последовательный запуск демонстраций
|
|
||||||
demonstratePersistentStorage()
|
|
||||||
.then(() => demonstrateSecurity())
|
|
||||||
.catch(error => console.error('Ошибка:', error));
|
|
||||||
BIN
public.zip
BIN
public.zip
Binary file not shown.
Reference in New Issue
Block a user