Updated all text to English
This commit is contained in:
@@ -2,7 +2,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
constructor(onMessage, onStatusChange, onKeyExchange, onVerificationRequired, onAnswerError = null) {
|
constructor(onMessage, onStatusChange, onKeyExchange, onVerificationRequired, onAnswerError = null) {
|
||||||
// Проверяем доступность глобального объекта
|
// Проверяем доступность глобального объекта
|
||||||
if (!window.EnhancedSecureCryptoUtils) {
|
if (!window.EnhancedSecureCryptoUtils) {
|
||||||
throw new Error('EnhancedSecureCryptoUtils не загружен. Убедитесь, что модуль загружен первым.');
|
throw new Error('EnhancedSecureCryptoUtils is not loaded. Please ensure the module is loaded first.');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.peerConnection = null;
|
this.peerConnection = null;
|
||||||
@@ -109,7 +109,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Отправляем сигнал о ротации ключей партнеру
|
// Sending key rotation signal to partner.
|
||||||
const rotationSignal = {
|
const rotationSignal = {
|
||||||
type: 'key_rotation_signal',
|
type: 'key_rotation_signal',
|
||||||
newVersion: this.currentKeyVersion + 1,
|
newVersion: this.currentKeyVersion + 1,
|
||||||
@@ -118,14 +118,14 @@ class EnhancedSecureWebRTCManager {
|
|||||||
|
|
||||||
this.dataChannel.send(JSON.stringify(rotationSignal));
|
this.dataChannel.send(JSON.stringify(rotationSignal));
|
||||||
|
|
||||||
// Ждем подтверждения от партнера перед ротацией
|
// Waiting for partner's confirmation before rotation.
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this.pendingRotation = {
|
this.pendingRotation = {
|
||||||
newVersion: this.currentKeyVersion + 1,
|
newVersion: this.currentKeyVersion + 1,
|
||||||
resolve: resolve
|
resolve: resolve
|
||||||
};
|
};
|
||||||
|
|
||||||
// Таймаут на случай если партнер не ответит
|
// Timeout in case the partner doesn't respond.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this.pendingRotation) {
|
if (this.pendingRotation) {
|
||||||
this.pendingRotation.resolve(false);
|
this.pendingRotation.resolve(false);
|
||||||
@@ -159,7 +159,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
|
|
||||||
// PFS: Get keys for specific version (for decryption)
|
// PFS: Get keys for specific version (for decryption)
|
||||||
getKeysForVersion(version) {
|
getKeysForVersion(version) {
|
||||||
// Сначала проверяем старые ключи (включая версию 0)
|
// First, we check the old keys (including version 0).
|
||||||
const oldKeySet = this.oldKeys.get(version);
|
const oldKeySet = this.oldKeys.get(version);
|
||||||
if (oldKeySet && oldKeySet.encryptionKey && oldKeySet.macKey && oldKeySet.metadataKey) {
|
if (oldKeySet && oldKeySet.encryptionKey && oldKeySet.macKey && oldKeySet.metadataKey) {
|
||||||
return {
|
return {
|
||||||
@@ -169,7 +169,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Если это текущая версия, возвращаем текущие ключи
|
// If this is the current version, return the current keys.
|
||||||
if (version === this.currentKeyVersion) {
|
if (version === this.currentKeyVersion) {
|
||||||
if (this.encryptionKey && this.macKey && this.metadataKey) {
|
if (this.encryptionKey && this.macKey && this.metadataKey) {
|
||||||
return {
|
return {
|
||||||
@@ -213,12 +213,12 @@ class EnhancedSecureWebRTCManager {
|
|||||||
} else if (state === 'connected' && this.isVerified) {
|
} else if (state === 'connected' && this.isVerified) {
|
||||||
this.onStatusChange('connected');
|
this.onStatusChange('connected');
|
||||||
} else if (state === 'disconnected' || state === 'closed') {
|
} else if (state === 'disconnected' || state === 'closed') {
|
||||||
// Если это намеренное отключение, сразу очищаем
|
// If this is an intentional disconnect, clear immediately.
|
||||||
if (this.intentionalDisconnect) {
|
if (this.intentionalDisconnect) {
|
||||||
this.onStatusChange('disconnected');
|
this.onStatusChange('disconnected');
|
||||||
setTimeout(() => this.cleanupConnection(), 100);
|
setTimeout(() => this.cleanupConnection(), 100);
|
||||||
} else {
|
} else {
|
||||||
// Неожиданное отключение - пытаемся уведомить партнера
|
// Unexpected disconnection — attempting to notify partner.
|
||||||
this.onStatusChange('reconnecting');
|
this.onStatusChange('reconnecting');
|
||||||
this.handleUnexpectedDisconnect();
|
this.handleUnexpectedDisconnect();
|
||||||
}
|
}
|
||||||
@@ -261,11 +261,11 @@ class EnhancedSecureWebRTCManager {
|
|||||||
|
|
||||||
if (!this.intentionalDisconnect) {
|
if (!this.intentionalDisconnect) {
|
||||||
this.onStatusChange('reconnecting');
|
this.onStatusChange('reconnecting');
|
||||||
this.onMessage('🔄 Канал данных закрыт. Попытка восстановления...', 'system');
|
this.onMessage('🔄 Data channel closed. Attempting recovery...', 'system');
|
||||||
this.handleUnexpectedDisconnect();
|
this.handleUnexpectedDisconnect();
|
||||||
} else {
|
} else {
|
||||||
this.onStatusChange('disconnected');
|
this.onStatusChange('disconnected');
|
||||||
this.onMessage('🔌 Соединение закрыто', 'system');
|
this.onMessage('🔌 Connection closed', 'system');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stopHeartbeat();
|
this.stopHeartbeat();
|
||||||
@@ -334,22 +334,22 @@ class EnhancedSecureWebRTCManager {
|
|||||||
throw new Error(`Invalid key types for version ${keyVersion}`);
|
throw new Error(`Invalid key types for version ${keyVersion}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Используем более гибкую проверку sequence number
|
// Using a more flexible sequence number check
|
||||||
const decryptedData = await window.EnhancedSecureCryptoUtils.decryptMessage(
|
const decryptedData = await window.EnhancedSecureCryptoUtils.decryptMessage(
|
||||||
payload.data,
|
payload.data,
|
||||||
keys.encryptionKey,
|
keys.encryptionKey,
|
||||||
keys.macKey,
|
keys.macKey,
|
||||||
keys.metadataKey,
|
keys.metadataKey,
|
||||||
null // Отключаем строгую проверку sequence number
|
null // Disabling strict sequence number verification
|
||||||
);
|
);
|
||||||
|
|
||||||
// Проверяем replay attack по messageId
|
// Checking for replay attack using messageId
|
||||||
if (this.processedMessageIds.has(decryptedData.messageId)) {
|
if (this.processedMessageIds.has(decryptedData.messageId)) {
|
||||||
throw new Error('Duplicate message detected - possible replay attack');
|
throw new Error('Duplicate message detected - possible replay attack');
|
||||||
}
|
}
|
||||||
this.processedMessageIds.add(decryptedData.messageId);
|
this.processedMessageIds.add(decryptedData.messageId);
|
||||||
|
|
||||||
// Обновляем ожидаемый sequence number более гибко
|
// Updating expected sequence number more flexibly
|
||||||
if (decryptedData.sequenceNumber >= this.expectedSequenceNumber) {
|
if (decryptedData.sequenceNumber >= this.expectedSequenceNumber) {
|
||||||
this.expectedSequenceNumber = decryptedData.sequenceNumber + 1;
|
this.expectedSequenceNumber = decryptedData.sequenceNumber + 1;
|
||||||
}
|
}
|
||||||
@@ -411,13 +411,13 @@ class EnhancedSecureWebRTCManager {
|
|||||||
window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Message processing error', {
|
window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Message processing error', {
|
||||||
error: error.message
|
error: error.message
|
||||||
});
|
});
|
||||||
this.onMessage(`❌ Ошибка обработки: ${error.message}`, 'system');
|
this.onMessage(`❌ Processing error: ${error.message}`, 'system');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.dataChannel.onerror = (error) => {
|
this.dataChannel.onerror = (error) => {
|
||||||
console.error('Data channel error:', error);
|
console.error('Data channel error:', error);
|
||||||
this.onMessage('❌ Ошибка канала данных', 'system');
|
this.onMessage('❌ Data channel error', 'system');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,7 +546,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!this.validateEnhancedOfferData(offerData)) {
|
if (!this.validateEnhancedOfferData(offerData)) {
|
||||||
throw new Error('Неверный формат данных подключения');
|
throw new Error('Invalid connection data format');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check rate limiting
|
// Check rate limiting
|
||||||
@@ -602,7 +602,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
privateKeyType: typeof this.ecdhKeyPair?.privateKey,
|
privateKeyType: typeof this.ecdhKeyPair?.privateKey,
|
||||||
privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name
|
privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name
|
||||||
});
|
});
|
||||||
throw new Error('Локальный ECDH приватный ключ не является CryptoKey');
|
throw new Error('The local ECDH private key is not a valid CryptoKey.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(peerECDHPublicKey instanceof CryptoKey)) {
|
if (!(peerECDHPublicKey instanceof CryptoKey)) {
|
||||||
@@ -610,7 +610,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
publicKeyType: typeof peerECDHPublicKey,
|
publicKeyType: typeof peerECDHPublicKey,
|
||||||
publicKeyAlgorithm: peerECDHPublicKey?.algorithm?.name
|
publicKeyAlgorithm: peerECDHPublicKey?.algorithm?.name
|
||||||
});
|
});
|
||||||
throw new Error('ECDH публичный ключ собеседника не является CryptoKey');
|
throw new Error('The peer"s ECDH public key is not a valid CryptoKey');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store peer's public key for PFS key rotation
|
// Store peer's public key for PFS key rotation
|
||||||
@@ -745,22 +745,22 @@ class EnhancedSecureWebRTCManager {
|
|||||||
async handleSecureAnswer(answerData) {
|
async handleSecureAnswer(answerData) {
|
||||||
try {
|
try {
|
||||||
if (!answerData || answerData.type !== 'enhanced_secure_answer' || !answerData.sdp) {
|
if (!answerData || answerData.type !== 'enhanced_secure_answer' || !answerData.sdp) {
|
||||||
throw new Error('Неверный формат ответа');
|
throw new Error('Invalid response format');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import peer's ECDH public key from the signed package
|
// Import peer's ECDH public key from the signed package
|
||||||
if (!answerData.ecdhPublicKey || !answerData.ecdhPublicKey.keyData) {
|
if (!answerData.ecdhPublicKey || !answerData.ecdhPublicKey.keyData) {
|
||||||
throw new Error('Отсутствуют данные ECDH публичного ключа');
|
throw new Error('Missing ECDH public key data');
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, import and verify the ECDSA public key for signature verification
|
// First, import and verify the ECDSA public key for signature verification
|
||||||
if (!answerData.ecdsaPublicKey || !answerData.ecdsaPublicKey.keyData) {
|
if (!answerData.ecdsaPublicKey || !answerData.ecdsaPublicKey.keyData) {
|
||||||
throw new Error('Отсутствуют данные ECDSA публичного ключа для верификации подписи');
|
throw new Error('Missing ECDSA public key data for signature verification');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional MITM protection: Validate answer data structure
|
// Additional MITM protection: Validate answer data structure
|
||||||
if (!answerData.timestamp || !answerData.version) {
|
if (!answerData.timestamp || !answerData.version) {
|
||||||
throw new Error('Отсутствуют обязательные поля в данных ответа - возможная MITM атака');
|
throw new Error('Missing required fields in response data – possible MITM attack');
|
||||||
}
|
}
|
||||||
|
|
||||||
// MITM Protection: Verify session ID if present (for enhanced security)
|
// MITM Protection: Verify session ID if present (for enhanced security)
|
||||||
@@ -769,7 +769,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
expectedSessionId: this.sessionId,
|
expectedSessionId: this.sessionId,
|
||||||
receivedSessionId: answerData.sessionId
|
receivedSessionId: answerData.sessionId
|
||||||
});
|
});
|
||||||
throw new Error('Несоответствие идентификатора сессии - возможная MITM атака');
|
throw new Error('Session ID mismatch – possible MITM attack');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for replay attacks (reject answers older than 1 hour)
|
// Check for replay attacks (reject answers older than 1 hour)
|
||||||
@@ -782,10 +782,10 @@ class EnhancedSecureWebRTCManager {
|
|||||||
|
|
||||||
// Уведомляем основной код о ошибке replay attack
|
// Уведомляем основной код о ошибке replay attack
|
||||||
if (this.onAnswerError) {
|
if (this.onAnswerError) {
|
||||||
this.onAnswerError('replay_attack', 'Данные ответа слишком старые - возможная атака повтора');
|
this.onAnswerError('replay_attack', 'Response data is too old – possible replay attack');
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('Данные ответа слишком старые - возможная атака повтора');
|
throw new Error('Response data is too old – possible replay attack');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check protocol version compatibility
|
// Check protocol version compatibility
|
||||||
@@ -823,7 +823,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
timestamp: answerData.timestamp,
|
timestamp: answerData.timestamp,
|
||||||
version: answerData.version
|
version: answerData.version
|
||||||
});
|
});
|
||||||
throw new Error('Недействительная подпись ECDSA ключа - возможная MITM атака');
|
throw new Error('Invalid ECDSA key signature – possible MITM attack');
|
||||||
}
|
}
|
||||||
|
|
||||||
window.EnhancedSecureCryptoUtils.secureLog.log('info', 'ECDSA signature verification passed', {
|
window.EnhancedSecureCryptoUtils.secureLog.log('info', 'ECDSA signature verification passed', {
|
||||||
@@ -842,7 +842,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Invalid session salt detected - possible session hijacking', {
|
window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Invalid session salt detected - possible session hijacking', {
|
||||||
saltLength: this.sessionSalt ? this.sessionSalt.length : 0
|
saltLength: this.sessionSalt ? this.sessionSalt.length : 0
|
||||||
});
|
});
|
||||||
throw new Error('Недействительная сессионная соль - возможная атака перехвата сессии');
|
throw new Error('Invalid session salt – possible session hijacking attempt');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the session salt hasn't been tampered with
|
// Verify that the session salt hasn't been tampered with
|
||||||
@@ -858,7 +858,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
privateKeyType: typeof this.ecdhKeyPair?.privateKey,
|
privateKeyType: typeof this.ecdhKeyPair?.privateKey,
|
||||||
privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name
|
privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name
|
||||||
});
|
});
|
||||||
throw new Error('Локальный ECDH приватный ключ не является CryptoKey');
|
throw new Error('Local ECDH private key is not a CryptoKey');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(peerPublicKey instanceof CryptoKey)) {
|
if (!(peerPublicKey instanceof CryptoKey)) {
|
||||||
@@ -866,7 +866,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
publicKeyType: typeof peerPublicKey,
|
publicKeyType: typeof peerPublicKey,
|
||||||
publicKeyAlgorithm: peerPublicKey?.algorithm?.name
|
publicKeyAlgorithm: peerPublicKey?.algorithm?.name
|
||||||
});
|
});
|
||||||
throw new Error('ECDH публичный ключ собеседника не является CryptoKey');
|
throw new Error('Peer ECDH public key is not a CryptoKey');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store peer's public key for PFS key rotation
|
// Store peer's public key for PFS key rotation
|
||||||
@@ -898,7 +898,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
macKeyAlgorithm: this.macKey?.algorithm?.name,
|
macKeyAlgorithm: this.macKey?.algorithm?.name,
|
||||||
metadataKeyAlgorithm: this.metadataKey?.algorithm?.name
|
metadataKeyAlgorithm: this.metadataKey?.algorithm?.name
|
||||||
});
|
});
|
||||||
throw new Error('Недействительные типы ключей после вывода');
|
throw new Error('Invalid key types after export');
|
||||||
}
|
}
|
||||||
|
|
||||||
window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Encryption keys set in handleSecureAnswer', {
|
window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Encryption keys set in handleSecureAnswer', {
|
||||||
@@ -938,8 +938,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Enhanced secure answer handling failed:', error);
|
console.error('Enhanced secure answer handling failed:', error);
|
||||||
this.onStatusChange('failed');
|
this.onStatusChange('failed');
|
||||||
|
|
||||||
// Уведомляем основной код о критических ошибках
|
|
||||||
if (this.onAnswerError) {
|
if (this.onAnswerError) {
|
||||||
if (error.message.includes('слишком старые') || error.message.includes('too old')) {
|
if (error.message.includes('слишком старые') || error.message.includes('too old')) {
|
||||||
this.onAnswerError('replay_attack', error.message);
|
this.onAnswerError('replay_attack', error.message);
|
||||||
@@ -957,7 +956,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
initiateVerification() {
|
initiateVerification() {
|
||||||
if (this.isInitiator) {
|
if (this.isInitiator) {
|
||||||
// Initiator waits for verification confirmation
|
// Initiator waits for verification confirmation
|
||||||
this.onMessage('🔐 Подтвердите код безопасности с собеседником для завершения подключения', 'system');
|
this.onMessage('🔐 Confirm the security code with your peer to complete the connection', 'system');
|
||||||
} else {
|
} else {
|
||||||
// Responder confirms verification automatically if codes match
|
// Responder confirms verification automatically if codes match
|
||||||
this.confirmVerification();
|
this.confirmVerification();
|
||||||
@@ -977,11 +976,11 @@ class EnhancedSecureWebRTCManager {
|
|||||||
this.dataChannel.send(JSON.stringify(verificationPayload));
|
this.dataChannel.send(JSON.stringify(verificationPayload));
|
||||||
this.isVerified = true;
|
this.isVerified = true;
|
||||||
this.onStatusChange('connected');
|
this.onStatusChange('connected');
|
||||||
this.onMessage('✅ Верификация прошла успешно. Канал защищен!', 'system');
|
this.onMessage('✅ Verification successful. The channel is now secure!', 'system');
|
||||||
this.processMessageQueue();
|
this.processMessageQueue();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Verification failed:', error);
|
console.error('Verification failed:', error);
|
||||||
this.onMessage('❌ Ошибка верификации', 'system');
|
this.onMessage('❌ Verification failed', 'system');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -997,10 +996,10 @@ class EnhancedSecureWebRTCManager {
|
|||||||
this.dataChannel.send(JSON.stringify(responsePayload));
|
this.dataChannel.send(JSON.stringify(responsePayload));
|
||||||
this.isVerified = true;
|
this.isVerified = true;
|
||||||
this.onStatusChange('connected');
|
this.onStatusChange('connected');
|
||||||
this.onMessage('✅ Верификация прошла успешно. Канал защищен!', 'system');
|
this.onMessage('✅ Verification successful. The channel is now secure!', 'system');
|
||||||
this.processMessageQueue();
|
this.processMessageQueue();
|
||||||
} else {
|
} else {
|
||||||
this.onMessage('❌ Код верификации не совпадает! Возможна атака!', 'system');
|
this.onMessage('❌ Verification code mismatch! Possible MITM attack detected. Connection aborted for safety!', 'system');
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1009,10 +1008,10 @@ class EnhancedSecureWebRTCManager {
|
|||||||
if (data.verified) {
|
if (data.verified) {
|
||||||
this.isVerified = true;
|
this.isVerified = true;
|
||||||
this.onStatusChange('connected');
|
this.onStatusChange('connected');
|
||||||
this.onMessage('✅ Верификация прошла успешно. Канал защищен!', 'system');
|
this.onMessage('✅ Verification successful. The channel is now secure.!', 'system');
|
||||||
this.processMessageQueue();
|
this.processMessageQueue();
|
||||||
} else {
|
} else {
|
||||||
this.onMessage('❌ Верификация не прошла!', 'system');
|
this.onMessage('❌ Verification failed!', 'system');
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1137,7 +1136,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
async sendSecureMessage(message) {
|
async sendSecureMessage(message) {
|
||||||
if (!this.isConnected() || !this.isVerified) {
|
if (!this.isConnected() || !this.isVerified) {
|
||||||
this.messageQueue.push(message);
|
this.messageQueue.push(message);
|
||||||
throw new Error('Соединение не готово. Сообщение добавлено в очередь.');
|
throw new Error('Connection not ready. Message queued for sending.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate encryption keys
|
// Validate encryption keys
|
||||||
@@ -1149,7 +1148,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
isConnected: this.isConnected(),
|
isConnected: this.isConnected(),
|
||||||
isVerified: this.isVerified
|
isVerified: this.isVerified
|
||||||
});
|
});
|
||||||
throw new Error('Ключи шифрования не инициализированы. Проверьте соединение.');
|
throw new Error('Encryption keys not initialized. Please check the connection.');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1273,17 +1272,14 @@ class EnhancedSecureWebRTCManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
// Устанавливаем флаг намеренного отключения
|
|
||||||
this.intentionalDisconnect = true;
|
this.intentionalDisconnect = true;
|
||||||
|
|
||||||
window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Starting intentional disconnect');
|
window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Starting intentional disconnect');
|
||||||
|
|
||||||
// Отправляем уведомление несколько раз для надежности
|
|
||||||
this.sendDisconnectNotification();
|
this.sendDisconnectNotification();
|
||||||
|
|
||||||
// Ждем немного для доставки уведомления, затем очищаем
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.sendDisconnectNotification(); // Еще одна попытка
|
this.sendDisconnectNotification();
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -1294,7 +1290,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
handleUnexpectedDisconnect() {
|
handleUnexpectedDisconnect() {
|
||||||
this.sendDisconnectNotification();
|
this.sendDisconnectNotification();
|
||||||
this.isVerified = false;
|
this.isVerified = false;
|
||||||
this.onMessage('🔌 Соединение потеряно. Попытка переподключения...', 'system');
|
this.onMessage('🔌 Connection lost. Attempting to reconnect...', 'system');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!this.intentionalDisconnect) {
|
if (!this.intentionalDisconnect) {
|
||||||
@@ -1311,8 +1307,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
reason: this.intentionalDisconnect ? 'user_disconnect' : 'connection_lost'
|
reason: this.intentionalDisconnect ? 'user_disconnect' : 'connection_lost'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Пытаемся отправить уведомление несколько раз
|
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
try {
|
try {
|
||||||
this.dataChannel.send(JSON.stringify(notification));
|
this.dataChannel.send(JSON.stringify(notification));
|
||||||
@@ -1322,7 +1317,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
} catch (sendError) {
|
} catch (sendError) {
|
||||||
if (i === 2) { // Последняя попытка
|
if (i === 2) {
|
||||||
window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Failed to send disconnect notification', {
|
window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Failed to send disconnect notification', {
|
||||||
error: sendError.message
|
error: sendError.message
|
||||||
});
|
});
|
||||||
@@ -1338,27 +1333,24 @@ class EnhancedSecureWebRTCManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attemptReconnection() {
|
attemptReconnection() {
|
||||||
this.onMessage('❌ Не удается переподключиться. Требуется новое соединение.', 'system');
|
this.onMessage('❌ Unable to reconnect. A new connection is required.', 'system');
|
||||||
this.cleanupConnection();
|
this.cleanupConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePeerDisconnectNotification(data) {
|
handlePeerDisconnectNotification(data) {
|
||||||
const reason = data.reason || 'unknown';
|
const reason = data.reason || 'unknown';
|
||||||
const reasonText = reason === 'user_disconnect' ? 'намеренно отключился' : 'потерял соединение';
|
const reasonText = reason === 'user_disconnect' ? 'manually disconnected.' : 'connection lost.';
|
||||||
|
|
||||||
this.onMessage(`👋 Собеседник ${reasonText}`, 'system');
|
this.onMessage(`👋 Peer ${reasonText}`, 'system');
|
||||||
this.onStatusChange('peer_disconnected');
|
this.onStatusChange('peer_disconnected');
|
||||||
|
|
||||||
// Устанавливаем флаг что это не наше намеренное отключение
|
|
||||||
this.intentionalDisconnect = false;
|
this.intentionalDisconnect = false;
|
||||||
this.isVerified = false;
|
this.isVerified = false;
|
||||||
this.stopHeartbeat();
|
this.stopHeartbeat();
|
||||||
|
|
||||||
// Очищаем UI данные
|
this.onKeyExchange('');
|
||||||
this.onKeyExchange(''); // Очищаем отпечаток
|
this.onVerificationRequired('');
|
||||||
this.onVerificationRequired(''); // Очищаем код верификации
|
|
||||||
|
|
||||||
// Очищаем соединение через небольшую задержку
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.cleanupConnection();
|
this.cleanupConnection();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
@@ -1373,8 +1365,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
this.isVerified = false;
|
this.isVerified = false;
|
||||||
this.processedMessageIds.clear();
|
this.processedMessageIds.clear();
|
||||||
this.messageCounter = 0;
|
this.messageCounter = 0;
|
||||||
|
|
||||||
// Полная очистка всех криптографических данных
|
|
||||||
this.encryptionKey = null;
|
this.encryptionKey = null;
|
||||||
this.macKey = null;
|
this.macKey = null;
|
||||||
this.metadataKey = null;
|
this.metadataKey = null;
|
||||||
@@ -1384,21 +1375,21 @@ class EnhancedSecureWebRTCManager {
|
|||||||
this.peerPublicKey = null;
|
this.peerPublicKey = null;
|
||||||
this.verificationCode = null;
|
this.verificationCode = null;
|
||||||
|
|
||||||
// PFS: Очистка всех версий ключей
|
// PFS: Clearing all key versions
|
||||||
this.keyVersions.clear();
|
this.keyVersions.clear();
|
||||||
this.oldKeys.clear();
|
this.oldKeys.clear();
|
||||||
this.currentKeyVersion = 0;
|
this.currentKeyVersion = 0;
|
||||||
this.lastKeyRotation = Date.now();
|
this.lastKeyRotation = Date.now();
|
||||||
|
|
||||||
// Очистка пар ключей
|
// Clearing key pairs
|
||||||
this.ecdhKeyPair = null;
|
this.ecdhKeyPair = null;
|
||||||
this.ecdsaKeyPair = null;
|
this.ecdsaKeyPair = null;
|
||||||
|
|
||||||
// Сброс счетчиков сообщений
|
// Resetting message counters
|
||||||
this.sequenceNumber = 0;
|
this.sequenceNumber = 0;
|
||||||
this.expectedSequenceNumber = 0;
|
this.expectedSequenceNumber = 0;
|
||||||
|
|
||||||
// Сброс флагов безопасности
|
// Security flags reset completed
|
||||||
this.securityFeatures = {
|
this.securityFeatures = {
|
||||||
hasEncryption: false,
|
hasEncryption: false,
|
||||||
hasECDH: false,
|
hasECDH: false,
|
||||||
@@ -1412,7 +1403,7 @@ class EnhancedSecureWebRTCManager {
|
|||||||
hasPFS: false
|
hasPFS: false
|
||||||
};
|
};
|
||||||
|
|
||||||
// Закрытие соединений
|
// Closing connections
|
||||||
if (this.dataChannel) {
|
if (this.dataChannel) {
|
||||||
this.dataChannel.close();
|
this.dataChannel.close();
|
||||||
this.dataChannel = null;
|
this.dataChannel = null;
|
||||||
@@ -1422,23 +1413,22 @@ class EnhancedSecureWebRTCManager {
|
|||||||
this.peerConnection = null;
|
this.peerConnection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Очистка очереди сообщений
|
// Clearing message queue
|
||||||
this.messageQueue = [];
|
this.messageQueue = [];
|
||||||
|
|
||||||
// ВАЖНО: Очистка логов безопасности
|
// IMPORTANT: Clearing security logs
|
||||||
window.EnhancedSecureCryptoUtils.secureLog.clearLogs();
|
window.EnhancedSecureCryptoUtils.secureLog.clearLogs();
|
||||||
|
|
||||||
// Уведомляем UI о полной очистке
|
// Notifying the UI about complete cleanup
|
||||||
this.onStatusChange('disconnected');
|
this.onStatusChange('disconnected');
|
||||||
this.onKeyExchange('');
|
this.onKeyExchange('');
|
||||||
this.onVerificationRequired('');
|
this.onVerificationRequired('');
|
||||||
|
|
||||||
window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Connection cleaned up completely');
|
window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Connection cleaned up completely');
|
||||||
|
|
||||||
// Сброс флага намеренного отключения
|
// Resetting the intentional disconnect flag
|
||||||
this.intentionalDisconnect = false;
|
this.intentionalDisconnect = false;
|
||||||
|
|
||||||
// Принудительная сборка мусора
|
|
||||||
if (window.gc) {
|
if (window.gc) {
|
||||||
window.gc();
|
window.gc();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user