fix(ios): prevent chat crash when Notifications API is unavailable on iPhones
- Guarded all Notification API usage to avoid ReferenceError on iOS Safari. - Set default permission to 'denied' when Notification is undefined. - Added early return in notification flow when Notifications API is unavailable. - Wrapped Notification.permission, requestPermission(), and new Notification(...) with typeof checks. - Updated SecureNotificationManager and app.jsx to degrade gracefully. - Verified build passes and chat loads correctly on iOS without notifications.
This commit is contained in:
Vendored
+25
-1
@@ -29,7 +29,7 @@ var require_SecureNotificationManager = __commonJS({
|
|||||||
"src/notifications/SecureNotificationManager.js"(exports, module) {
|
"src/notifications/SecureNotificationManager.js"(exports, module) {
|
||||||
var SecureChatNotificationManager = class {
|
var SecureChatNotificationManager = class {
|
||||||
constructor(config = {}) {
|
constructor(config = {}) {
|
||||||
this.permission = Notification.permission;
|
this.permission = typeof Notification !== "undefined" && Notification && typeof Notification.permission === "string" ? Notification.permission : "denied";
|
||||||
this.isTabActive = this.checkTabActive();
|
this.isTabActive = this.checkTabActive();
|
||||||
this.unreadCount = 0;
|
this.unreadCount = 0;
|
||||||
this.originalTitle = document.title;
|
this.originalTitle = document.title;
|
||||||
@@ -213,6 +213,9 @@ var require_SecureNotificationManager = __commonJS({
|
|||||||
* @returns {Notification|null} Created notification or null
|
* @returns {Notification|null} Created notification or null
|
||||||
*/
|
*/
|
||||||
notify(senderName, message, options = {}) {
|
notify(senderName, message, options = {}) {
|
||||||
|
if (typeof Notification === "undefined") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
this.isTabActive = this.checkTabActive();
|
this.isTabActive = this.checkTabActive();
|
||||||
if (this.isTabActive) {
|
if (this.isTabActive) {
|
||||||
return null;
|
return null;
|
||||||
@@ -1684,10 +1687,18 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
|
|||||||
// Verify ECDSA signature (P-384 or P-256)
|
// Verify ECDSA signature (P-384 or P-256)
|
||||||
static async verifySignature(publicKey, signature, data) {
|
static async verifySignature(publicKey, signature, data) {
|
||||||
try {
|
try {
|
||||||
|
console.log("DEBUG: verifySignature called with:", {
|
||||||
|
publicKey,
|
||||||
|
signature,
|
||||||
|
data
|
||||||
|
});
|
||||||
const encoder = new TextEncoder();
|
const encoder = new TextEncoder();
|
||||||
const dataBuffer = typeof data === "string" ? encoder.encode(data) : data;
|
const dataBuffer = typeof data === "string" ? encoder.encode(data) : data;
|
||||||
const signatureBuffer = new Uint8Array(signature);
|
const signatureBuffer = new Uint8Array(signature);
|
||||||
|
console.log("DEBUG: verifySignature dataBuffer:", dataBuffer);
|
||||||
|
console.log("DEBUG: verifySignature signatureBuffer:", signatureBuffer);
|
||||||
try {
|
try {
|
||||||
|
console.log("DEBUG: Trying SHA-384 verification...");
|
||||||
const isValid = await crypto.subtle.verify(
|
const isValid = await crypto.subtle.verify(
|
||||||
{
|
{
|
||||||
name: "ECDSA",
|
name: "ECDSA",
|
||||||
@@ -1697,13 +1708,16 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
|
|||||||
signatureBuffer,
|
signatureBuffer,
|
||||||
dataBuffer
|
dataBuffer
|
||||||
);
|
);
|
||||||
|
console.log("DEBUG: SHA-384 verification result:", isValid);
|
||||||
_EnhancedSecureCryptoUtils.secureLog.log("info", "Signature verification completed (SHA-384)", {
|
_EnhancedSecureCryptoUtils.secureLog.log("info", "Signature verification completed (SHA-384)", {
|
||||||
isValid,
|
isValid,
|
||||||
dataSize: dataBuffer.length
|
dataSize: dataBuffer.length
|
||||||
});
|
});
|
||||||
return isValid;
|
return isValid;
|
||||||
} catch (sha384Error) {
|
} catch (sha384Error) {
|
||||||
|
console.log("DEBUG: SHA-384 verification failed, trying SHA-256:", sha384Error);
|
||||||
_EnhancedSecureCryptoUtils.secureLog.log("warn", "SHA-384 verification failed, trying SHA-256", { error: sha384Error.message });
|
_EnhancedSecureCryptoUtils.secureLog.log("warn", "SHA-384 verification failed, trying SHA-256", { error: sha384Error.message });
|
||||||
|
console.log("DEBUG: Trying SHA-256 verification...");
|
||||||
const isValid = await crypto.subtle.verify(
|
const isValid = await crypto.subtle.verify(
|
||||||
{
|
{
|
||||||
name: "ECDSA",
|
name: "ECDSA",
|
||||||
@@ -1713,6 +1727,7 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
|
|||||||
signatureBuffer,
|
signatureBuffer,
|
||||||
dataBuffer
|
dataBuffer
|
||||||
);
|
);
|
||||||
|
console.log("DEBUG: SHA-256 verification result:", isValid);
|
||||||
_EnhancedSecureCryptoUtils.secureLog.log("info", "Signature verification completed (SHA-256 fallback)", {
|
_EnhancedSecureCryptoUtils.secureLog.log("info", "Signature verification completed (SHA-256 fallback)", {
|
||||||
isValid,
|
isValid,
|
||||||
dataSize: dataBuffer.length
|
dataSize: dataBuffer.length
|
||||||
@@ -1973,6 +1988,11 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
|
|||||||
// Import and verify signed public key
|
// Import and verify signed public key
|
||||||
static async importSignedPublicKey(signedPackage, verifyingKey, expectedKeyType = "ECDH") {
|
static async importSignedPublicKey(signedPackage, verifyingKey, expectedKeyType = "ECDH") {
|
||||||
try {
|
try {
|
||||||
|
console.log("DEBUG: importSignedPublicKey called with:", {
|
||||||
|
signedPackage,
|
||||||
|
verifyingKey,
|
||||||
|
expectedKeyType
|
||||||
|
});
|
||||||
if (!signedPackage || typeof signedPackage !== "object") {
|
if (!signedPackage || typeof signedPackage !== "object") {
|
||||||
throw new Error("Invalid signed package format");
|
throw new Error("Invalid signed package format");
|
||||||
}
|
}
|
||||||
@@ -1990,7 +2010,11 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
|
|||||||
await _EnhancedSecureCryptoUtils.validateKeyStructure(keyData, keyType);
|
await _EnhancedSecureCryptoUtils.validateKeyStructure(keyData, keyType);
|
||||||
const packageCopy = { keyType, keyData, timestamp, version };
|
const packageCopy = { keyType, keyData, timestamp, version };
|
||||||
const packageString = JSON.stringify(packageCopy);
|
const packageString = JSON.stringify(packageCopy);
|
||||||
|
console.log("DEBUG: Web version package string for verification:", packageString);
|
||||||
|
console.log("DEBUG: Web version signature to verify:", signature);
|
||||||
|
console.log("DEBUG: Web version verifying key:", verifyingKey);
|
||||||
const isValidSignature = await _EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signature, packageString);
|
const isValidSignature = await _EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signature, packageString);
|
||||||
|
console.log("DEBUG: Web version signature verification result:", isValidSignature);
|
||||||
if (!isValidSignature) {
|
if (!isValidSignature) {
|
||||||
throw new Error("Invalid signature on key package - possible MITM attack");
|
throw new Error("Invalid signature on key package - possible MITM attack");
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+16
-4
@@ -293,8 +293,8 @@ var EnhancedConnectionSetup = ({
|
|||||||
if (!window.isSecureContext && window.location.protocol !== "https:" && window.location.hostname !== "localhost") {
|
if (!window.isSecureContext && window.location.protocol !== "https:" && window.location.hostname !== "localhost") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const currentPermission = Notification.permission;
|
const currentPermission = typeof Notification !== "undefined" && Notification ? Notification.permission : "denied";
|
||||||
if (currentPermission === "default") {
|
if (typeof Notification !== "undefined" && currentPermission === "default") {
|
||||||
const permission = await Notification.requestPermission();
|
const permission = await Notification.requestPermission();
|
||||||
if (permission === "granted") {
|
if (permission === "granted") {
|
||||||
try {
|
try {
|
||||||
@@ -307,6 +307,7 @@ var EnhancedConnectionSetup = ({
|
|||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
|
if (typeof Notification === "undefined") return;
|
||||||
const welcomeNotification = new Notification("SecureBit Chat", {
|
const welcomeNotification = new Notification("SecureBit Chat", {
|
||||||
body: "Notifications enabled! You will receive alerts for new messages.",
|
body: "Notifications enabled! You will receive alerts for new messages.",
|
||||||
icon: "/logo/icon-192x192.png",
|
icon: "/logo/icon-192x192.png",
|
||||||
@@ -322,7 +323,7 @@ var EnhancedConnectionSetup = ({
|
|||||||
}
|
}
|
||||||
}, 1e3);
|
}, 1e3);
|
||||||
}
|
}
|
||||||
} else if (currentPermission === "granted") {
|
} else if (typeof Notification !== "undefined" && currentPermission === "granted") {
|
||||||
try {
|
try {
|
||||||
if (window.NotificationIntegration && webrtcManagerRef.current && !notificationIntegrationRef.current) {
|
if (window.NotificationIntegration && webrtcManagerRef.current && !notificationIntegrationRef.current) {
|
||||||
const integration = new window.NotificationIntegration(webrtcManagerRef.current);
|
const integration = new window.NotificationIntegration(webrtcManagerRef.current);
|
||||||
@@ -333,6 +334,7 @@ var EnhancedConnectionSetup = ({
|
|||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
|
if (typeof Notification === "undefined") return;
|
||||||
const testNotification = new Notification("SecureBit Chat", {
|
const testNotification = new Notification("SecureBit Chat", {
|
||||||
body: "Notifications are working! You will receive alerts for new messages.",
|
body: "Notifications are working! You will receive alerts for new messages.",
|
||||||
icon: "/logo/icon-192x192.png",
|
icon: "/logo/icon-192x192.png",
|
||||||
@@ -1670,7 +1672,7 @@ var EnhancedSecureP2PChat = () => {
|
|||||||
handleAnswerError,
|
handleAnswerError,
|
||||||
handleVerificationStateChange
|
handleVerificationStateChange
|
||||||
);
|
);
|
||||||
if (Notification.permission === "granted" && window.NotificationIntegration && !notificationIntegrationRef.current) {
|
if (typeof Notification !== "undefined" && Notification.permission === "granted" && window.NotificationIntegration && !notificationIntegrationRef.current) {
|
||||||
try {
|
try {
|
||||||
const integration = new window.NotificationIntegration(webrtcManagerRef2.current);
|
const integration = new window.NotificationIntegration(webrtcManagerRef2.current);
|
||||||
integration.init().then(() => {
|
integration.init().then(() => {
|
||||||
@@ -2557,14 +2559,24 @@ var EnhancedSecureP2PChat = () => {
|
|||||||
}]);
|
}]);
|
||||||
let offer;
|
let offer;
|
||||||
try {
|
try {
|
||||||
|
console.log("DEBUG: Processing offer input:", offerInput.trim().substring(0, 100) + "...");
|
||||||
|
console.log("DEBUG: decodeAnyPayload available:", typeof window.decodeAnyPayload === "function");
|
||||||
|
console.log("DEBUG: decompressIfNeeded available:", typeof window.decompressIfNeeded === "function");
|
||||||
if (typeof window.decodeAnyPayload === "function") {
|
if (typeof window.decodeAnyPayload === "function") {
|
||||||
|
console.log("DEBUG: Using decodeAnyPayload...");
|
||||||
const any = window.decodeAnyPayload(offerInput.trim());
|
const any = window.decodeAnyPayload(offerInput.trim());
|
||||||
|
console.log("DEBUG: decodeAnyPayload result type:", typeof any);
|
||||||
|
console.log("DEBUG: decodeAnyPayload result:", any);
|
||||||
offer = typeof any === "string" ? JSON.parse(any) : any;
|
offer = typeof any === "string" ? JSON.parse(any) : any;
|
||||||
} else {
|
} else {
|
||||||
|
console.log("DEBUG: Using decompressIfNeeded...");
|
||||||
const rawText = typeof window.decompressIfNeeded === "function" ? window.decompressIfNeeded(offerInput.trim()) : offerInput.trim();
|
const rawText = typeof window.decompressIfNeeded === "function" ? window.decompressIfNeeded(offerInput.trim()) : offerInput.trim();
|
||||||
|
console.log("DEBUG: decompressIfNeeded result:", rawText.substring(0, 100) + "...");
|
||||||
offer = JSON.parse(rawText);
|
offer = JSON.parse(rawText);
|
||||||
}
|
}
|
||||||
|
console.log("DEBUG: Final offer:", offer);
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
|
console.error("DEBUG: Parse error:", parseError);
|
||||||
throw new Error(`Invalid invitation format: ${parseError.message}`);
|
throw new Error(`Invalid invitation format: ${parseError.message}`);
|
||||||
}
|
}
|
||||||
if (!offer || typeof offer !== "object") {
|
if (!offer || typeof offer !== "object") {
|
||||||
|
|||||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
+20
-5
@@ -317,10 +317,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check current permission status
|
// Check current permission status
|
||||||
const currentPermission = Notification.permission;
|
const currentPermission = (typeof Notification !== 'undefined' && Notification)
|
||||||
|
? Notification.permission
|
||||||
|
: 'denied';
|
||||||
|
|
||||||
// Only request if permission is default (not granted or denied)
|
// Only request if permission is default (not granted or denied)
|
||||||
if (currentPermission === 'default') {
|
if (typeof Notification !== 'undefined' && currentPermission === 'default') {
|
||||||
const permission = await Notification.requestPermission();
|
const permission = await Notification.requestPermission();
|
||||||
|
|
||||||
if (permission === 'granted') {
|
if (permission === 'granted') {
|
||||||
@@ -337,9 +339,10 @@
|
|||||||
// Handle error silently
|
// Handle error silently
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send welcome notification
|
// Send welcome notification (only if Notifications API exists)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
|
if (typeof Notification === 'undefined') return;
|
||||||
const welcomeNotification = new Notification('SecureBit Chat', {
|
const welcomeNotification = new Notification('SecureBit Chat', {
|
||||||
body: 'Notifications enabled! You will receive alerts for new messages.',
|
body: 'Notifications enabled! You will receive alerts for new messages.',
|
||||||
icon: '/logo/icon-192x192.png',
|
icon: '/logo/icon-192x192.png',
|
||||||
@@ -360,7 +363,7 @@
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (currentPermission === 'granted') {
|
} else if (typeof Notification !== 'undefined' && currentPermission === 'granted') {
|
||||||
// Initialize notification integration immediately
|
// Initialize notification integration immediately
|
||||||
try {
|
try {
|
||||||
if (window.NotificationIntegration && webrtcManagerRef.current && !notificationIntegrationRef.current) {
|
if (window.NotificationIntegration && webrtcManagerRef.current && !notificationIntegrationRef.current) {
|
||||||
@@ -377,6 +380,7 @@
|
|||||||
// Test notification to confirm it works
|
// Test notification to confirm it works
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
|
if (typeof Notification === 'undefined') return;
|
||||||
const testNotification = new Notification('SecureBit Chat', {
|
const testNotification = new Notification('SecureBit Chat', {
|
||||||
body: 'Notifications are working! You will receive alerts for new messages.',
|
body: 'Notifications are working! You will receive alerts for new messages.',
|
||||||
icon: '/logo/icon-192x192.png',
|
icon: '/logo/icon-192x192.png',
|
||||||
@@ -1900,7 +1904,7 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Initialize notification integration if permission was already granted
|
// Initialize notification integration if permission was already granted
|
||||||
if (Notification.permission === 'granted' && window.NotificationIntegration && !notificationIntegrationRef.current) {
|
if (typeof Notification !== 'undefined' && Notification.permission === 'granted' && window.NotificationIntegration && !notificationIntegrationRef.current) {
|
||||||
try {
|
try {
|
||||||
const integration = new window.NotificationIntegration(webrtcManagerRef.current);
|
const integration = new window.NotificationIntegration(webrtcManagerRef.current);
|
||||||
integration.init().then(() => {
|
integration.init().then(() => {
|
||||||
@@ -2926,15 +2930,26 @@
|
|||||||
|
|
||||||
let offer;
|
let offer;
|
||||||
try {
|
try {
|
||||||
|
console.log('DEBUG: Processing offer input:', offerInput.trim().substring(0, 100) + '...');
|
||||||
|
console.log('DEBUG: decodeAnyPayload available:', typeof window.decodeAnyPayload === 'function');
|
||||||
|
console.log('DEBUG: decompressIfNeeded available:', typeof window.decompressIfNeeded === 'function');
|
||||||
|
|
||||||
// Prefer binary decode first, then gzip JSON
|
// Prefer binary decode first, then gzip JSON
|
||||||
if (typeof window.decodeAnyPayload === 'function') {
|
if (typeof window.decodeAnyPayload === 'function') {
|
||||||
|
console.log('DEBUG: Using decodeAnyPayload...');
|
||||||
const any = window.decodeAnyPayload(offerInput.trim());
|
const any = window.decodeAnyPayload(offerInput.trim());
|
||||||
|
console.log('DEBUG: decodeAnyPayload result type:', typeof any);
|
||||||
|
console.log('DEBUG: decodeAnyPayload result:', any);
|
||||||
offer = (typeof any === 'string') ? JSON.parse(any) : any;
|
offer = (typeof any === 'string') ? JSON.parse(any) : any;
|
||||||
} else {
|
} else {
|
||||||
|
console.log('DEBUG: Using decompressIfNeeded...');
|
||||||
const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(offerInput.trim()) : offerInput.trim();
|
const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(offerInput.trim()) : offerInput.trim();
|
||||||
|
console.log('DEBUG: decompressIfNeeded result:', rawText.substring(0, 100) + '...');
|
||||||
offer = JSON.parse(rawText);
|
offer = JSON.parse(rawText);
|
||||||
}
|
}
|
||||||
|
console.log('DEBUG: Final offer:', offer);
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
|
console.error('DEBUG: Parse error:', parseError);
|
||||||
throw new Error(`Invalid invitation format: ${parseError.message}`);
|
throw new Error(`Invalid invitation format: ${parseError.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1204,12 +1204,22 @@ class EnhancedSecureCryptoUtils {
|
|||||||
// Verify ECDSA signature (P-384 or P-256)
|
// Verify ECDSA signature (P-384 or P-256)
|
||||||
static async verifySignature(publicKey, signature, data) {
|
static async verifySignature(publicKey, signature, data) {
|
||||||
try {
|
try {
|
||||||
|
console.log('DEBUG: verifySignature called with:', {
|
||||||
|
publicKey: publicKey,
|
||||||
|
signature: signature,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
|
||||||
const encoder = new TextEncoder();
|
const encoder = new TextEncoder();
|
||||||
const dataBuffer = typeof data === 'string' ? encoder.encode(data) : data;
|
const dataBuffer = typeof data === 'string' ? encoder.encode(data) : data;
|
||||||
const signatureBuffer = new Uint8Array(signature);
|
const signatureBuffer = new Uint8Array(signature);
|
||||||
|
|
||||||
|
console.log('DEBUG: verifySignature dataBuffer:', dataBuffer);
|
||||||
|
console.log('DEBUG: verifySignature signatureBuffer:', signatureBuffer);
|
||||||
|
|
||||||
// Try SHA-384 first, fallback to SHA-256
|
// Try SHA-384 first, fallback to SHA-256
|
||||||
try {
|
try {
|
||||||
|
console.log('DEBUG: Trying SHA-384 verification...');
|
||||||
const isValid = await crypto.subtle.verify(
|
const isValid = await crypto.subtle.verify(
|
||||||
{
|
{
|
||||||
name: 'ECDSA',
|
name: 'ECDSA',
|
||||||
@@ -1220,6 +1230,8 @@ class EnhancedSecureCryptoUtils {
|
|||||||
dataBuffer
|
dataBuffer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log('DEBUG: SHA-384 verification result:', isValid);
|
||||||
|
|
||||||
EnhancedSecureCryptoUtils.secureLog.log('info', 'Signature verification completed (SHA-384)', {
|
EnhancedSecureCryptoUtils.secureLog.log('info', 'Signature verification completed (SHA-384)', {
|
||||||
isValid,
|
isValid,
|
||||||
dataSize: dataBuffer.length
|
dataSize: dataBuffer.length
|
||||||
@@ -1227,8 +1239,10 @@ class EnhancedSecureCryptoUtils {
|
|||||||
|
|
||||||
return isValid;
|
return isValid;
|
||||||
} catch (sha384Error) {
|
} catch (sha384Error) {
|
||||||
|
console.log('DEBUG: SHA-384 verification failed, trying SHA-256:', sha384Error);
|
||||||
EnhancedSecureCryptoUtils.secureLog.log('warn', 'SHA-384 verification failed, trying SHA-256', { error: sha384Error.message });
|
EnhancedSecureCryptoUtils.secureLog.log('warn', 'SHA-384 verification failed, trying SHA-256', { error: sha384Error.message });
|
||||||
|
|
||||||
|
console.log('DEBUG: Trying SHA-256 verification...');
|
||||||
const isValid = await crypto.subtle.verify(
|
const isValid = await crypto.subtle.verify(
|
||||||
{
|
{
|
||||||
name: 'ECDSA',
|
name: 'ECDSA',
|
||||||
@@ -1239,6 +1253,8 @@ class EnhancedSecureCryptoUtils {
|
|||||||
dataBuffer
|
dataBuffer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log('DEBUG: SHA-256 verification result:', isValid);
|
||||||
|
|
||||||
EnhancedSecureCryptoUtils.secureLog.log('info', 'Signature verification completed (SHA-256 fallback)', {
|
EnhancedSecureCryptoUtils.secureLog.log('info', 'Signature verification completed (SHA-256 fallback)', {
|
||||||
isValid,
|
isValid,
|
||||||
dataSize: dataBuffer.length
|
dataSize: dataBuffer.length
|
||||||
@@ -1583,6 +1599,12 @@ class EnhancedSecureCryptoUtils {
|
|||||||
// Import and verify signed public key
|
// Import and verify signed public key
|
||||||
static async importSignedPublicKey(signedPackage, verifyingKey, expectedKeyType = 'ECDH') {
|
static async importSignedPublicKey(signedPackage, verifyingKey, expectedKeyType = 'ECDH') {
|
||||||
try {
|
try {
|
||||||
|
console.log('DEBUG: importSignedPublicKey called with:', {
|
||||||
|
signedPackage: signedPackage,
|
||||||
|
verifyingKey: verifyingKey,
|
||||||
|
expectedKeyType: expectedKeyType
|
||||||
|
});
|
||||||
|
|
||||||
// Validate package structure
|
// Validate package structure
|
||||||
if (!signedPackage || typeof signedPackage !== 'object') {
|
if (!signedPackage || typeof signedPackage !== 'object') {
|
||||||
throw new Error('Invalid signed package format');
|
throw new Error('Invalid signed package format');
|
||||||
@@ -1609,7 +1631,11 @@ class EnhancedSecureCryptoUtils {
|
|||||||
// Verify signature
|
// Verify signature
|
||||||
const packageCopy = { keyType, keyData, timestamp, version };
|
const packageCopy = { keyType, keyData, timestamp, version };
|
||||||
const packageString = JSON.stringify(packageCopy);
|
const packageString = JSON.stringify(packageCopy);
|
||||||
|
console.log('DEBUG: Web version package string for verification:', packageString);
|
||||||
|
console.log('DEBUG: Web version signature to verify:', signature);
|
||||||
|
console.log('DEBUG: Web version verifying key:', verifyingKey);
|
||||||
const isValidSignature = await EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signature, packageString);
|
const isValidSignature = await EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signature, packageString);
|
||||||
|
console.log('DEBUG: Web version signature verification result:', isValidSignature);
|
||||||
|
|
||||||
if (!isValidSignature) {
|
if (!isValidSignature) {
|
||||||
throw new Error('Invalid signature on key package - possible MITM attack');
|
throw new Error('Invalid signature on key package - possible MITM attack');
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
|
|
||||||
class SecureChatNotificationManager {
|
class SecureChatNotificationManager {
|
||||||
constructor(config = {}) {
|
constructor(config = {}) {
|
||||||
this.permission = Notification.permission;
|
// Safely read Notification permission (iOS Safari may not define Notification)
|
||||||
|
this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')
|
||||||
|
? Notification.permission
|
||||||
|
: 'denied';
|
||||||
this.isTabActive = this.checkTabActive(); // Initialize with proper check
|
this.isTabActive = this.checkTabActive(); // Initialize with proper check
|
||||||
this.unreadCount = 0;
|
this.unreadCount = 0;
|
||||||
this.originalTitle = document.title;
|
this.originalTitle = document.title;
|
||||||
@@ -238,6 +241,10 @@ class SecureChatNotificationManager {
|
|||||||
* @returns {Notification|null} Created notification or null
|
* @returns {Notification|null} Created notification or null
|
||||||
*/
|
*/
|
||||||
notify(senderName, message, options = {}) {
|
notify(senderName, message, options = {}) {
|
||||||
|
// Abort if Notifications API is not available (e.g., iOS Safari)
|
||||||
|
if (typeof Notification === 'undefined') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// Update tab active state before checking
|
// Update tab active state before checking
|
||||||
this.isTabActive = this.checkTabActive();
|
this.isTabActive = this.checkTabActive();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user