Update session pricing and demo mode
- Updated demo mode: now includes basic protection features, still stronger than many competing messengers. - Adjusted pricing for Basic and Premium sessions to better reflect security levels. - Added restrictions to Basic session and enhanced Premium session to deliver maximum protection.
This commit is contained in:
@@ -6,11 +6,13 @@ const EnhancedMinimalHeader = ({
|
||||
isConnected,
|
||||
securityLevel,
|
||||
sessionManager,
|
||||
sessionTimeLeft
|
||||
sessionTimeLeft,
|
||||
webrtcManager
|
||||
}) => {
|
||||
const [currentTimeLeft, setCurrentTimeLeft] = React.useState(sessionTimeLeft || 0);
|
||||
const [hasActiveSession, setHasActiveSession] = React.useState(false);
|
||||
const [sessionType, setSessionType] = React.useState('unknown');
|
||||
const [realSecurityLevel, setRealSecurityLevel] = React.useState(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
const updateSessionInfo = () => {
|
||||
@@ -22,17 +24,122 @@ const EnhancedMinimalHeader = ({
|
||||
setHasActiveSession(isActive);
|
||||
setCurrentTimeLeft(timeLeft);
|
||||
setSessionType(currentSession?.type || 'unknown');
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
updateSessionInfo();
|
||||
|
||||
const interval = setInterval(updateSessionInfo, 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [sessionManager]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const updateSecurityStatus = () => {
|
||||
try {
|
||||
const activeWebrtcManager = webrtcManager || window.webrtcManager;
|
||||
const activeSessionManager = sessionManager || window.sessionManager;
|
||||
|
||||
if (activeWebrtcManager && activeWebrtcManager.getSecurityStatus) {
|
||||
const securityStatus = activeWebrtcManager.getSecurityStatus();
|
||||
const sessionInfo = activeSessionManager ? activeSessionManager.getSessionInfo() : null;
|
||||
|
||||
if (window.DEBUG_MODE) {
|
||||
console.log('🔍 Header security update:', {
|
||||
hasWebrtcManager: !!activeWebrtcManager,
|
||||
hasSessionManager: !!activeSessionManager,
|
||||
securityStatus: securityStatus,
|
||||
sessionInfo: sessionInfo
|
||||
});
|
||||
}
|
||||
|
||||
const realLevel = calculateRealSecurityLevel(securityStatus, sessionInfo);
|
||||
setRealSecurityLevel(realLevel);
|
||||
|
||||
if (window.DEBUG_MODE) {
|
||||
console.log('🔍 Calculated real security level:', realLevel);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('⚠️ Error updating security status:', error);
|
||||
}
|
||||
};
|
||||
|
||||
updateSecurityStatus();
|
||||
const interval = setInterval(updateSecurityStatus, 3000);
|
||||
return () => clearInterval(interval);
|
||||
}, [webrtcManager, sessionManager]);
|
||||
|
||||
const calculateRealSecurityLevel = (securityStatus, sessionInfo) => {
|
||||
if (!securityStatus) {
|
||||
return {
|
||||
level: 'Unknown',
|
||||
score: 0,
|
||||
color: 'red',
|
||||
details: 'Security status not available'
|
||||
};
|
||||
}
|
||||
|
||||
const activeFeatures = securityStatus.activeFeaturesNames || [];
|
||||
const totalFeatures = securityStatus.totalFeatures || 12;
|
||||
const sessionType = sessionInfo?.type || securityStatus.sessionType || 'unknown';
|
||||
const securityLevel = securityStatus.securityLevel || 'basic';
|
||||
const stage = securityStatus.stage || 1;
|
||||
|
||||
let finalScore = securityStatus.score || 0;
|
||||
let level = 'Basic';
|
||||
let color = 'red';
|
||||
|
||||
// score от crypto utils
|
||||
if (finalScore > 0) {
|
||||
if (finalScore >= 90) {
|
||||
level = 'Maximum';
|
||||
color = 'green';
|
||||
} else if (finalScore >= 60) {
|
||||
level = 'Enhanced';
|
||||
color = sessionType === 'demo' ? 'yellow' : 'green';
|
||||
} else if (finalScore >= 30) {
|
||||
level = 'Basic';
|
||||
color = 'yellow';
|
||||
} else {
|
||||
level = 'Low';
|
||||
color = 'red';
|
||||
}
|
||||
} else {
|
||||
const baseScores = {
|
||||
'basic': 30,
|
||||
'enhanced': 65,
|
||||
'maximum': 90
|
||||
};
|
||||
|
||||
const featureScore = totalFeatures > 0 ? Math.min(40, (activeFeatures.length / totalFeatures) * 40) : 0;
|
||||
finalScore = Math.min(100, (baseScores[securityLevel] || 30) + featureScore);
|
||||
|
||||
if (sessionType === 'demo') {
|
||||
level = 'Basic';
|
||||
color = finalScore >= 40 ? 'yellow' : 'red';
|
||||
} else if (securityLevel === 'enhanced') {
|
||||
level = 'Enhanced';
|
||||
color = finalScore >= 70 ? 'green' : 'yellow';
|
||||
} else if (securityLevel === 'maximum') {
|
||||
level = 'Maximum';
|
||||
color = 'green';
|
||||
} else {
|
||||
level = 'Basic';
|
||||
color = finalScore >= 50 ? 'yellow' : 'red';
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
level: level,
|
||||
score: Math.round(finalScore),
|
||||
color: color,
|
||||
details: `${activeFeatures.length}/${totalFeatures} security features active`,
|
||||
activeFeatures: activeFeatures,
|
||||
sessionType: sessionType,
|
||||
stage: stage,
|
||||
securityLevel: securityLevel
|
||||
};
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (sessionManager?.hasActiveSession()) {
|
||||
setCurrentTimeLeft(sessionManager.getTimeLeft());
|
||||
@@ -43,14 +150,33 @@ const EnhancedMinimalHeader = ({
|
||||
}, [sessionManager, sessionTimeLeft]);
|
||||
|
||||
const handleSecurityClick = () => {
|
||||
if (securityLevel?.verificationResults) {
|
||||
const currentSecurity = realSecurityLevel || securityLevel;
|
||||
|
||||
if (!currentSecurity) {
|
||||
alert('Security information not available');
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSecurity.activeFeatures) {
|
||||
const activeList = currentSecurity.activeFeatures.map(feature =>
|
||||
`✅ ${feature.replace('has', '').replace(/([A-Z])/g, ' $1').trim()}`
|
||||
).join('\n');
|
||||
|
||||
const message = `Security Level: ${currentSecurity.level} (${currentSecurity.score}%)\n` +
|
||||
`Session Type: ${currentSecurity.sessionType}\n` +
|
||||
`Stage: ${currentSecurity.stage}\n\n` +
|
||||
`Active Security Features:\n${activeList || 'No features detected'}\n\n` +
|
||||
`${currentSecurity.details || 'No additional details'}`;
|
||||
|
||||
alert(message);
|
||||
} else if (currentSecurity.verificationResults) {
|
||||
alert('Security check details:\n\n' +
|
||||
Object.entries(securityLevel.verificationResults)
|
||||
Object.entries(currentSecurity.verificationResults)
|
||||
.map(([key, result]) => `${key}: ${result.passed ? '✅' : '❌'} ${result.details}`)
|
||||
.join('\n')
|
||||
);
|
||||
} else if (securityLevel) {
|
||||
alert(`Security Level: ${securityLevel.level}\nScore: ${securityLevel.score}%\nDetails: ${securityLevel.details || 'No additional details available'}`);
|
||||
} else {
|
||||
alert(`Security Level: ${currentSecurity.level}\nScore: ${currentSecurity.score}%\nDetails: ${currentSecurity.details || 'No additional details available'}`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,7 +184,6 @@ const EnhancedMinimalHeader = ({
|
||||
|
||||
React.useEffect(() => {
|
||||
const handleForceUpdate = (event) => {
|
||||
|
||||
if (sessionManager) {
|
||||
const isActive = sessionManager.hasActiveSession();
|
||||
const timeLeft = sessionManager.getTimeLeft();
|
||||
@@ -128,6 +253,7 @@ const EnhancedMinimalHeader = ({
|
||||
};
|
||||
|
||||
const config = getStatusConfig();
|
||||
const displaySecurityLevel = realSecurityLevel || securityLevel;
|
||||
|
||||
return React.createElement('header', {
|
||||
className: 'header-minimal sticky top-0 z-50'
|
||||
@@ -163,7 +289,7 @@ const EnhancedMinimalHeader = ({
|
||||
React.createElement('p', {
|
||||
key: 'subtitle',
|
||||
className: 'text-xs sm:text-sm text-muted hidden sm:block'
|
||||
}, 'End-to-end freedom. v4.0.03.00')
|
||||
}, 'End-to-end freedom. v4.1.1')
|
||||
])
|
||||
]),
|
||||
|
||||
@@ -181,23 +307,23 @@ const EnhancedMinimalHeader = ({
|
||||
}),
|
||||
|
||||
// Security Level Indicator
|
||||
securityLevel && React.createElement('div', {
|
||||
displaySecurityLevel && React.createElement('div', {
|
||||
key: 'security-level',
|
||||
className: 'hidden md:flex items-center space-x-2 cursor-pointer hover:opacity-80 transition-opacity duration-200',
|
||||
onClick: handleSecurityClick,
|
||||
title: `${securityLevel.level} (${securityLevel.score}%) - Click for details`
|
||||
title: `${displaySecurityLevel.level} (${displaySecurityLevel.score}%) - ${displaySecurityLevel.details || 'Click for details'}`
|
||||
}, [
|
||||
React.createElement('div', {
|
||||
key: 'security-icon',
|
||||
className: `w-6 h-6 rounded-full flex items-center justify-center ${
|
||||
securityLevel.color === 'green' ? 'bg-green-500/20' :
|
||||
securityLevel.color === 'yellow' ? 'bg-yellow-500/20' : 'bg-red-500/20'
|
||||
displaySecurityLevel.color === 'green' ? 'bg-green-500/20' :
|
||||
displaySecurityLevel.color === 'yellow' ? 'bg-yellow-500/20' : 'bg-red-500/20'
|
||||
}`
|
||||
}, [
|
||||
React.createElement('i', {
|
||||
className: `fas fa-shield-alt text-xs ${
|
||||
securityLevel.color === 'green' ? 'text-green-400' :
|
||||
securityLevel.color === 'yellow' ? 'text-yellow-400' : 'text-red-400'
|
||||
displaySecurityLevel.color === 'green' ? 'text-green-400' :
|
||||
displaySecurityLevel.color === 'yellow' ? 'text-yellow-400' : 'text-red-400'
|
||||
}`
|
||||
})
|
||||
]),
|
||||
@@ -208,11 +334,11 @@ const EnhancedMinimalHeader = ({
|
||||
React.createElement('div', {
|
||||
key: 'security-level-text',
|
||||
className: 'text-xs font-medium text-primary'
|
||||
}, `${securityLevel.level} (${securityLevel.score}%)`),
|
||||
securityLevel.details && React.createElement('div', {
|
||||
}, `${displaySecurityLevel.level} (${displaySecurityLevel.score}%)`),
|
||||
React.createElement('div', {
|
||||
key: 'security-details',
|
||||
className: 'text-xs text-muted mt-1 hidden lg:block'
|
||||
}, securityLevel.details),
|
||||
}, displaySecurityLevel.details || `Stage ${displaySecurityLevel.stage || 1}`),
|
||||
React.createElement('div', {
|
||||
key: 'security-progress',
|
||||
className: 'w-16 h-1 bg-gray-600 rounded-full overflow-hidden'
|
||||
@@ -220,33 +346,33 @@ const EnhancedMinimalHeader = ({
|
||||
React.createElement('div', {
|
||||
key: 'progress-bar',
|
||||
className: `h-full transition-all duration-500 ${
|
||||
securityLevel.color === 'green' ? 'bg-green-400' :
|
||||
securityLevel.color === 'yellow' ? 'bg-yellow-400' : 'bg-red-400'
|
||||
displaySecurityLevel.color === 'green' ? 'bg-green-400' :
|
||||
displaySecurityLevel.color === 'yellow' ? 'bg-yellow-400' : 'bg-red-400'
|
||||
}`,
|
||||
style: { width: `${securityLevel.score}%` }
|
||||
style: { width: `${displaySecurityLevel.score}%` }
|
||||
})
|
||||
])
|
||||
])
|
||||
]),
|
||||
|
||||
// Mobile Security Indicator
|
||||
securityLevel && React.createElement('div', {
|
||||
displaySecurityLevel && React.createElement('div', {
|
||||
key: 'mobile-security',
|
||||
className: 'md:hidden flex items-center'
|
||||
}, [
|
||||
React.createElement('div', {
|
||||
key: 'mobile-security-icon',
|
||||
className: `w-8 h-8 rounded-full flex items-center justify-center cursor-pointer hover:opacity-80 transition-opacity duration-200 ${
|
||||
securityLevel.color === 'green' ? 'bg-green-500/20' :
|
||||
securityLevel.color === 'yellow' ? 'bg-yellow-500/20' : 'bg-red-500/20'
|
||||
displaySecurityLevel.color === 'green' ? 'bg-green-500/20' :
|
||||
displaySecurityLevel.color === 'yellow' ? 'bg-yellow-500/20' : 'bg-red-500/20'
|
||||
}`,
|
||||
title: `${securityLevel.level} (${securityLevel.score}%) - Click for details`,
|
||||
title: `${displaySecurityLevel.level} (${displaySecurityLevel.score}%) - Click for details`,
|
||||
onClick: handleSecurityClick
|
||||
}, [
|
||||
React.createElement('i', {
|
||||
className: `fas fa-shield-alt text-sm ${
|
||||
securityLevel.color === 'green' ? 'text-green-400' :
|
||||
securityLevel.color === 'yellow' ? 'text-yellow-400' : 'bg-red-400'
|
||||
displaySecurityLevel.color === 'green' ? 'text-green-400' :
|
||||
displaySecurityLevel.color === 'yellow' ? 'text-yellow-400' : 'text-red-400'
|
||||
}`
|
||||
})
|
||||
])
|
||||
@@ -288,4 +414,4 @@ const EnhancedMinimalHeader = ({
|
||||
|
||||
window.EnhancedMinimalHeader = EnhancedMinimalHeader;
|
||||
|
||||
console.log('✅ EnhancedMinimalHeader loaded with timer fixes');
|
||||
console.log('✅ EnhancedMinimalHeader v4.1.1 loaded with real security status integration');
|
||||
@@ -2,20 +2,20 @@ const React = window.React;
|
||||
const { useState, useEffect, useRef } = React;
|
||||
|
||||
const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) => {
|
||||
const [step, setStep] = useState('select');
|
||||
const [selectedType, setSelectedType] = useState(null);
|
||||
const [invoice, setInvoice] = useState(null);
|
||||
const [paymentStatus, setPaymentStatus] = useState('pending');
|
||||
const [error, setError] = useState('');
|
||||
const [paymentMethod, setPaymentMethod] = useState('webln');
|
||||
const [preimageInput, setPreimageInput] = useState('');
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
const [qrCodeUrl, setQrCodeUrl] = useState('');
|
||||
const [paymentTimer, setPaymentTimer] = useState(null);
|
||||
const [timeLeft, setTimeLeft] = useState(0);
|
||||
const pollInterval = useRef(null);
|
||||
const [step, setStep] = React.useState('select');
|
||||
const [selectedType, setSelectedType] = React.useState(null);
|
||||
const [invoice, setInvoice] = React.useState(null);
|
||||
const [paymentStatus, setPaymentStatus] = React.useState('pending');
|
||||
const [error, setError] = React.useState('');
|
||||
const [paymentMethod, setPaymentMethod] = React.useState('webln');
|
||||
const [preimageInput, setPreimageInput] = React.useState('');
|
||||
const [isProcessing, setIsProcessing] = React.useState(false);
|
||||
const [qrCodeUrl, setQrCodeUrl] = React.useState('');
|
||||
const [paymentTimer, setPaymentTimer] = React.useState(null);
|
||||
const [timeLeft, setTimeLeft] = React.useState(0);
|
||||
const pollInterval = React.useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
React.useEffect(() => {
|
||||
if (!isOpen) {
|
||||
resetModal();
|
||||
if (pollInterval.current) {
|
||||
@@ -45,7 +45,6 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
setError('');
|
||||
|
||||
if (type === 'demo') {
|
||||
// Создаем demo сессию
|
||||
try {
|
||||
if (!sessionManager || !sessionManager.createDemoSession) {
|
||||
throw new Error('Demo session manager not available');
|
||||
@@ -64,7 +63,8 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
createdAt: Date.now(),
|
||||
isDemo: true,
|
||||
preimage: demoSession.preimage,
|
||||
warning: demoSession.warning
|
||||
warning: demoSession.warning,
|
||||
securityLevel: 'Basic'
|
||||
});
|
||||
setPaymentStatus('demo');
|
||||
} catch (error) {
|
||||
@@ -83,7 +83,7 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
setError('');
|
||||
|
||||
try {
|
||||
console.log(`Creating real Lightning invoice for ${type} session...`);
|
||||
console.log(`Creating Lightning invoice for ${type} session...`);
|
||||
|
||||
if (!sessionManager) {
|
||||
throw new Error('Session manager not initialized');
|
||||
@@ -95,6 +95,8 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
throw new Error('Failed to create Lightning invoice');
|
||||
}
|
||||
|
||||
createdInvoice.securityLevel = sessionManager.getSecurityLevelForSession(type);
|
||||
|
||||
setInvoice(createdInvoice);
|
||||
setPaymentStatus('created');
|
||||
|
||||
@@ -205,8 +207,8 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
}
|
||||
|
||||
const dummyPreimages = ['1'.repeat(64), 'a'.repeat(64), 'f'.repeat(64), '0'.repeat(64)];
|
||||
if (dummyPreimages.includes(trimmedPreimage) && selectedType !== 'free') {
|
||||
setError('The entered preimage is invalid. Please use the actual preimage from the payment..');
|
||||
if (dummyPreimages.includes(trimmedPreimage) && selectedType !== 'demo') {
|
||||
setError('The entered preimage is invalid. Please use the actual preimage from the payment.');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -233,7 +235,6 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
throw new Error('Demo preimage not available');
|
||||
}
|
||||
|
||||
// Для demo сессий используем специальную логику верификации
|
||||
const isValid = await sessionManager.verifyPayment(invoice.preimage, invoice.paymentHash);
|
||||
|
||||
if (isValid && isValid.verified) {
|
||||
@@ -243,7 +244,8 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
paymentHash: invoice.paymentHash,
|
||||
amount: 0,
|
||||
isDemo: true,
|
||||
warning: invoice.warning
|
||||
warning: invoice.warning,
|
||||
securityLevel: 'basic'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
@@ -265,7 +267,6 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
|
||||
let isValid;
|
||||
if (selectedType === 'demo') {
|
||||
// Demo сессии уже обработаны в handleDemoSession
|
||||
return;
|
||||
} else {
|
||||
isValid = await sessionManager.verifyPayment(preimage, invoice.paymentHash);
|
||||
@@ -283,7 +284,8 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
type: selectedType,
|
||||
preimage,
|
||||
paymentHash: invoice.paymentHash,
|
||||
amount: invoice.amount
|
||||
amount: invoice.amount,
|
||||
securityLevel: invoice.securityLevel || (selectedType === 'basic' ? 'enhanced' : 'maximum')
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
@@ -313,11 +315,19 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
const getSecurityBadgeColor = (level) => {
|
||||
switch (level?.toLowerCase()) {
|
||||
case 'basic': return 'bg-blue-500/20 text-blue-300 border-blue-500/30';
|
||||
case 'enhanced': return 'bg-orange-500/20 text-orange-300 border-orange-500/30';
|
||||
case 'maximum': return 'bg-green-500/20 text-green-300 border-green-500/30';
|
||||
default: return 'bg-gray-500/20 text-gray-300 border-gray-500/30';
|
||||
}
|
||||
};
|
||||
|
||||
const pricing = sessionManager?.sessionPrices || {
|
||||
demo: { sats: 0, hours: 0.1, usd: 0.00 },
|
||||
basic: { sats: 500, hours: 1, usd: 0.20 },
|
||||
premium: { sats: 1000, hours: 4, usd: 0.40 },
|
||||
extended: { sats: 2000, hours: 24, usd: 0.80 }
|
||||
basic: { sats: 5000, hours: 1, usd: 2.00 },
|
||||
premium: { sats: 20000, hours: 6, usd: 8.00 }
|
||||
};
|
||||
|
||||
if (!isOpen) return null;
|
||||
@@ -347,7 +357,8 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
step === 'select' && window.SessionTypeSelector && React.createElement(window.SessionTypeSelector, {
|
||||
key: 'selector',
|
||||
onSelectType: handleSelectType,
|
||||
onCancel: onClose
|
||||
onCancel: onClose,
|
||||
sessionManager: sessionManager
|
||||
}),
|
||||
|
||||
step === 'payment' && React.createElement('div', {
|
||||
@@ -361,16 +372,22 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) =
|
||||
React.createElement('h3', {
|
||||
key: 'session-title',
|
||||
className: 'text-lg font-semibold text-orange-400 mb-2'
|
||||
}, `${selectedType.charAt(0).toUpperCase() + selectedType.slice(1)} session`),
|
||||
}, [
|
||||
`${selectedType.charAt(0).toUpperCase() + selectedType.slice(1)} session`,
|
||||
invoice?.securityLevel && React.createElement('span', {
|
||||
key: 'security-badge',
|
||||
className: `text-xs px-2 py-1 rounded-full border ${getSecurityBadgeColor(invoice.securityLevel)}`
|
||||
}, invoice.securityLevel.toUpperCase())
|
||||
]),
|
||||
React.createElement('div', {
|
||||
key: 'session-details',
|
||||
className: 'text-sm text-secondary'
|
||||
}, [
|
||||
React.createElement('div', { key: 'amount' }, `${pricing[selectedType].sats} sat for ${pricing[selectedType].hours}ч`),
|
||||
React.createElement('div', { key: 'amount' }, `${pricing[selectedType].sats} sat for ${pricing[selectedType].hours}h`),
|
||||
pricing[selectedType].usd > 0 && React.createElement('div', {
|
||||
key: 'usd',
|
||||
className: 'text-gray-400'
|
||||
}, `≈ $${pricing[selectedType].usd} USD`)
|
||||
}, `≈ ${pricing[selectedType].usd} USD`)
|
||||
])
|
||||
]),
|
||||
|
||||
|
||||
@@ -23,10 +23,8 @@ const SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => {
|
||||
// Update information on load and every 10 seconds
|
||||
React.useEffect(() => {
|
||||
updateDemoInfo();
|
||||
|
||||
const interval = setInterval(updateDemoInfo, 10000);
|
||||
setRefreshTimer(interval);
|
||||
|
||||
return () => {
|
||||
if (interval) clearInterval(interval);
|
||||
};
|
||||
@@ -49,33 +47,66 @@ const SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => {
|
||||
price: '0 sat',
|
||||
usd: '$0.00',
|
||||
popular: false,
|
||||
description: 'Limited testing session',
|
||||
features: ['End-to-end encryption', 'Basic features', 'No payment required']
|
||||
securityLevel: 'Basic',
|
||||
securityBadge: 'BASIC',
|
||||
securityColor: 'bg-blue-500/20 text-blue-300',
|
||||
description: 'Limited testing session with basic security',
|
||||
features: [
|
||||
'Basic end-to-end encryption',
|
||||
'Simple key exchange',
|
||||
'Message integrity',
|
||||
'Rate limiting'
|
||||
],
|
||||
limitations: [
|
||||
'No advanced security features',
|
||||
'No traffic obfuscation',
|
||||
'No metadata protection'
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'basic',
|
||||
name: 'Basic',
|
||||
duration: '1 hour',
|
||||
price: '500 sat',
|
||||
usd: '$0.20',
|
||||
features: ['End-to-end encryption', 'Full features', '1 hour duration']
|
||||
price: '5,000 sat',
|
||||
usd: '$2.00',
|
||||
securityLevel: 'Enhanced',
|
||||
securityBadge: 'ENHANCED',
|
||||
securityColor: 'bg-orange-500/20 text-orange-300',
|
||||
popular: true,
|
||||
description: 'Full featured session with enhanced security',
|
||||
features: [
|
||||
'All basic features',
|
||||
'ECDSA digital signatures',
|
||||
'Metadata protection',
|
||||
'Perfect forward secrecy',
|
||||
'Nested encryption',
|
||||
'Packet padding'
|
||||
],
|
||||
limitations: [
|
||||
'Limited traffic obfuscation',
|
||||
'No fake traffic generation'
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'premium',
|
||||
name: 'Premium',
|
||||
duration: '4 hours',
|
||||
price: '1000 sat',
|
||||
usd: '$0.40',
|
||||
popular: true,
|
||||
features: ['End-to-end encryption', 'Full features', '4 hours duration', 'Priority support']
|
||||
},
|
||||
{
|
||||
id: 'extended',
|
||||
name: 'Extended',
|
||||
duration: '24 hours',
|
||||
price: '2000 sat',
|
||||
usd: '$0.80',
|
||||
features: ['End-to-end encryption', 'Full features', '24 hours duration', 'Priority support']
|
||||
duration: '6 hours',
|
||||
price: '20,000 sat',
|
||||
usd: '$8.00',
|
||||
securityLevel: 'Maximum',
|
||||
securityBadge: 'MAXIMUM',
|
||||
securityColor: 'bg-green-500/20 text-green-300',
|
||||
description: 'Extended session with maximum security protection',
|
||||
features: [
|
||||
'All enhanced features',
|
||||
'Traffic obfuscation',
|
||||
'Fake traffic generation',
|
||||
'Decoy channels',
|
||||
'Anti-fingerprinting',
|
||||
'Message chunking',
|
||||
'Advanced replay protection'
|
||||
],
|
||||
limitations: []
|
||||
}
|
||||
];
|
||||
|
||||
@@ -127,10 +158,10 @@ const SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => {
|
||||
React.createElement('p', {
|
||||
key: 'subtitle',
|
||||
className: 'text-gray-300 text-sm'
|
||||
}, 'Pay via Lightning Network or try our demo session')
|
||||
}, 'Different security levels for different needs')
|
||||
]),
|
||||
|
||||
React.createElement('div', { key: 'types', className: 'space-y-3' },
|
||||
React.createElement('div', { key: 'types', className: 'space-y-4' },
|
||||
sessionTypes.map(type => {
|
||||
const isDemo = type.id === 'demo';
|
||||
const isDisabled = isDemo && demoInfo && !demoInfo.canUseNow;
|
||||
@@ -138,62 +169,95 @@ const SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => {
|
||||
return React.createElement('div', {
|
||||
key: type.id,
|
||||
onClick: () => !isDisabled && handleTypeSelect(type.id),
|
||||
className: `card-minimal rounded-lg p-4 border-2 transition-all ${
|
||||
className: `relative card-minimal rounded-lg p-5 border-2 transition-all ${
|
||||
selectedType === type.id ? 'border-orange-500 bg-orange-500/10' : 'border-gray-600 hover:border-orange-400'
|
||||
} ${type.popular ? 'relative' : ''} ${
|
||||
} ${type.popular ? 'ring-2 ring-orange-500/30' : ''} ${
|
||||
isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
|
||||
}`
|
||||
}, [
|
||||
// Popular badge
|
||||
type.popular && React.createElement('div', {
|
||||
key: 'badge',
|
||||
className: 'absolute -top-2 right-3 bg-orange-500 text-white text-xs px-2 py-1 rounded-full'
|
||||
}, 'Popular'),
|
||||
key: 'popular-badge',
|
||||
className: 'absolute -top-2 right-3 bg-orange-500 text-white text-xs px-3 py-1 rounded-full font-medium'
|
||||
}, 'Most Popular'),
|
||||
|
||||
React.createElement('div', { key: 'content', className: 'flex items-start justify-between' }, [
|
||||
React.createElement('div', { key: 'info', className: 'flex-1' }, [
|
||||
React.createElement('div', { key: 'header', className: 'flex items-center gap-2 mb-2' }, [
|
||||
React.createElement('div', { key: 'content', className: 'space-y-4' }, [
|
||||
// Header with name and security level
|
||||
React.createElement('div', { key: 'header', className: 'flex items-start justify-between' }, [
|
||||
React.createElement('div', { key: 'title-section' }, [
|
||||
React.createElement('div', { key: 'name-row', className: 'flex items-center gap-3 mb-2' }, [
|
||||
React.createElement('h4', {
|
||||
key: 'name',
|
||||
className: 'text-lg font-semibold text-white'
|
||||
className: 'text-xl font-bold text-white'
|
||||
}, type.name),
|
||||
isDemo && React.createElement('span', {
|
||||
key: 'demo-badge',
|
||||
className: 'text-xs bg-blue-500/20 text-blue-300 px-2 py-1 rounded-full'
|
||||
}, 'FREE')
|
||||
key: 'free-badge',
|
||||
className: 'text-xs bg-blue-500/20 text-blue-300 px-2 py-1 rounded-full font-medium'
|
||||
}, 'FREE'),
|
||||
React.createElement('span', {
|
||||
key: 'security-badge',
|
||||
className: `text-xs px-2 py-1 rounded-full font-medium ${type.securityColor}`
|
||||
}, type.securityBadge)
|
||||
]),
|
||||
React.createElement('p', {
|
||||
key: 'duration',
|
||||
className: 'text-gray-300 text-sm mb-1'
|
||||
className: 'text-gray-300 font-medium mb-1'
|
||||
}, `Duration: ${type.duration}`),
|
||||
type.description && React.createElement('p', {
|
||||
React.createElement('p', {
|
||||
key: 'description',
|
||||
className: 'text-xs text-gray-400 mb-2'
|
||||
}, type.description),
|
||||
className: 'text-sm text-gray-400'
|
||||
}, type.description)
|
||||
]),
|
||||
React.createElement('div', { key: 'pricing', className: 'text-right' }, [
|
||||
React.createElement('div', {
|
||||
key: 'sats',
|
||||
className: `text-xl font-bold ${isDemo ? 'text-green-400' : 'text-orange-400'}`
|
||||
}, type.price),
|
||||
React.createElement('div', {
|
||||
key: 'usd',
|
||||
className: 'text-sm text-gray-400'
|
||||
}, type.usd)
|
||||
])
|
||||
]),
|
||||
|
||||
// Demo status info
|
||||
isDemo && demoInfo && React.createElement('div', {
|
||||
key: 'demo-status',
|
||||
className: 'text-xs mb-2'
|
||||
className: 'p-3 bg-blue-900/20 border border-blue-700/30 rounded-lg'
|
||||
}, [
|
||||
React.createElement('div', {
|
||||
key: 'availability',
|
||||
className: demoInfo.canUseNow ? 'text-green-400' : 'text-yellow-400'
|
||||
className: `text-sm font-medium ${demoInfo.canUseNow ? 'text-green-400' : 'text-yellow-400'}`
|
||||
}, demoInfo.canUseNow ?
|
||||
`✅ Available (${demoInfo.available}/${demoInfo.total} today)` :
|
||||
`⏰ Next: ${demoInfo.nextAvailable}`
|
||||
),
|
||||
demoInfo.globalActive > 0 && React.createElement('div', {
|
||||
key: 'global-status',
|
||||
className: 'text-blue-300 mt-1'
|
||||
className: 'text-blue-300 text-xs mt-1'
|
||||
}, `🌐 Global: ${demoInfo.globalActive}/${demoInfo.globalLimit} active`)
|
||||
]),
|
||||
|
||||
type.features && React.createElement('div', {
|
||||
key: 'features',
|
||||
className: 'text-xs text-gray-400 space-y-1'
|
||||
// Security features
|
||||
React.createElement('div', { key: 'features-section', className: 'space-y-3' }, [
|
||||
React.createElement('div', { key: 'features' }, [
|
||||
React.createElement('h5', {
|
||||
key: 'features-title',
|
||||
className: 'text-sm font-medium text-green-300 mb-2 flex items-center'
|
||||
}, [
|
||||
React.createElement('i', {
|
||||
key: 'shield-icon',
|
||||
className: 'fas fa-shield-alt mr-2'
|
||||
}),
|
||||
'Security Features'
|
||||
]),
|
||||
React.createElement('div', {
|
||||
key: 'features-list',
|
||||
className: 'grid grid-cols-1 gap-1'
|
||||
}, type.features.map((feature, index) =>
|
||||
React.createElement('div', {
|
||||
key: index,
|
||||
className: 'flex items-center gap-1'
|
||||
className: 'flex items-center gap-2 text-xs text-gray-300'
|
||||
}, [
|
||||
React.createElement('i', {
|
||||
key: 'check',
|
||||
@@ -205,15 +269,37 @@ const SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => {
|
||||
])
|
||||
))
|
||||
]),
|
||||
React.createElement('div', { key: 'pricing', className: 'text-right' }, [
|
||||
|
||||
// Limitations (if any)
|
||||
type.limitations && type.limitations.length > 0 && React.createElement('div', { key: 'limitations' }, [
|
||||
React.createElement('h5', {
|
||||
key: 'limitations-title',
|
||||
className: 'text-sm font-medium text-yellow-300 mb-2 flex items-center'
|
||||
}, [
|
||||
React.createElement('i', {
|
||||
key: 'info-icon',
|
||||
className: 'fas fa-info-circle mr-2'
|
||||
}),
|
||||
'Limitations'
|
||||
]),
|
||||
React.createElement('div', {
|
||||
key: 'sats',
|
||||
className: `text-lg font-bold ${isDemo ? 'text-green-400' : 'text-orange-400'}`
|
||||
}, type.price),
|
||||
key: 'limitations-list',
|
||||
className: 'grid grid-cols-1 gap-1'
|
||||
}, type.limitations.map((limitation, index) =>
|
||||
React.createElement('div', {
|
||||
key: 'usd',
|
||||
className: 'text-xs text-gray-400'
|
||||
}, type.usd)
|
||||
key: index,
|
||||
className: 'flex items-center gap-2 text-xs text-gray-400'
|
||||
}, [
|
||||
React.createElement('i', {
|
||||
key: 'minus',
|
||||
className: 'fas fa-minus text-yellow-400 w-3'
|
||||
}),
|
||||
React.createElement('span', {
|
||||
key: 'text'
|
||||
}, limitation)
|
||||
])
|
||||
))
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
@@ -254,12 +340,17 @@ const SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => {
|
||||
}, `🎯 Status: ${demoInfo.canUseNow ? 'Available now' : demoInfo.nextAvailable}`)
|
||||
])
|
||||
]),
|
||||
React.createElement('div', {
|
||||
key: 'security-note',
|
||||
className: 'mt-3 p-2 bg-yellow-500/10 border border-yellow-500/20 rounded text-yellow-200 text-xs'
|
||||
}, '⚠️ Demo sessions use basic security only. Upgrade to paid sessions for enhanced protection.'),
|
||||
React.createElement('div', {
|
||||
key: 'last-updated',
|
||||
className: 'text-xs text-gray-400 mt-3 text-center'
|
||||
className: 'text-xs text-gray-400 mt-2 text-center'
|
||||
}, `Last updated: ${new Date(lastRefresh).toLocaleTimeString()}`)
|
||||
]),
|
||||
|
||||
// Action buttons
|
||||
React.createElement('div', { key: 'buttons', className: 'flex space-x-3' }, [
|
||||
React.createElement('button', {
|
||||
key: 'continue',
|
||||
@@ -289,9 +380,7 @@ const SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => {
|
||||
className: 'px-3 py-3 bg-blue-600 hover:bg-blue-500 text-white rounded-lg transition-all',
|
||||
title: 'Refresh demo status'
|
||||
}, React.createElement('i', { className: 'fas fa-sync-alt' }))
|
||||
]),
|
||||
|
||||
|
||||
])
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ class EnhancedSecureWebRTCManager {
|
||||
throw new Error('EnhancedSecureCryptoUtils is not loaded. Please ensure the module is loaded first.');
|
||||
}
|
||||
|
||||
this.currentSessionType = null;
|
||||
this.currentSecurityLevel = 'basic';
|
||||
this.sessionConstraints = null;
|
||||
this.peerConnection = null;
|
||||
this.dataChannel = null;
|
||||
this.encryptionKey = null;
|
||||
@@ -43,7 +46,8 @@ class EnhancedSecureWebRTCManager {
|
||||
this.keyVersions = new Map(); // Store key versions for PFS
|
||||
this.oldKeys = new Map(); // Store old keys temporarily for decryption
|
||||
this.maxOldKeys = 3; // Keep last 3 key versions for decryption
|
||||
|
||||
this.peerConnection = null;
|
||||
this.dataChannel = null;
|
||||
this.securityFeatures = {
|
||||
hasEncryption: true,
|
||||
hasECDH: true,
|
||||
@@ -52,21 +56,20 @@ class EnhancedSecureWebRTCManager {
|
||||
hasMetadataProtection: false,
|
||||
hasEnhancedReplayProtection: false,
|
||||
hasNonExtractableKeys: false,
|
||||
hasRateLimiting: false,
|
||||
hasRateLimiting: true,
|
||||
hasEnhancedValidation: false,
|
||||
hasPFS: true,
|
||||
hasPFS: false,
|
||||
|
||||
hasNestedEncryption: true,
|
||||
hasPacketPadding: true,
|
||||
// Advanced Features (Session Managed)
|
||||
hasNestedEncryption: false,
|
||||
hasPacketPadding: false,
|
||||
hasPacketReordering: false,
|
||||
hasAntiFingerprinting: false,
|
||||
|
||||
|
||||
hasFakeTraffic: false,
|
||||
hasDecoyChannels: false,
|
||||
hasMessageChunking: false
|
||||
};
|
||||
|
||||
console.log('🔒 Enhanced WebRTC Manager initialized with tiered security');
|
||||
// ============================================
|
||||
// ENHANCED SECURITY FEATURES
|
||||
// ============================================
|
||||
@@ -192,6 +195,142 @@ class EnhancedSecureWebRTCManager {
|
||||
return mask;
|
||||
}
|
||||
|
||||
// Security configuration for session type
|
||||
configureSecurityForSession(sessionType, securityLevel) {
|
||||
console.log(`🔧 Configuring security for ${sessionType} session (${securityLevel} level)`);
|
||||
|
||||
this.currentSessionType = sessionType;
|
||||
this.currentSecurityLevel = securityLevel;
|
||||
|
||||
// We get restrictions for this session type
|
||||
if (window.sessionManager && window.sessionManager.isFeatureAllowedForSession) {
|
||||
this.sessionConstraints = {};
|
||||
|
||||
Object.keys(this.securityFeatures).forEach(feature => {
|
||||
this.sessionConstraints[feature] = window.sessionManager.isFeatureAllowedForSession(sessionType, feature);
|
||||
});
|
||||
|
||||
// Applying restrictions
|
||||
this.applySessionConstraints();
|
||||
|
||||
console.log(`✅ Security configured for ${sessionType}:`, this.sessionConstraints);
|
||||
|
||||
// Notifying the user about the security level
|
||||
this.notifySecurityLevel();
|
||||
} else {
|
||||
console.warn('⚠️ Session manager not available, using default security');
|
||||
}
|
||||
}
|
||||
|
||||
// Applying session restrictions
|
||||
applySessionConstraints() {
|
||||
if (!this.sessionConstraints) return;
|
||||
|
||||
// Applying restrictions to security features
|
||||
Object.keys(this.sessionConstraints).forEach(feature => {
|
||||
const allowed = this.sessionConstraints[feature];
|
||||
|
||||
if (!allowed && this.securityFeatures[feature]) {
|
||||
console.log(`🔒 Disabling ${feature} for ${this.currentSessionType} session`);
|
||||
this.securityFeatures[feature] = false;
|
||||
|
||||
// Disabling linked configurations
|
||||
switch (feature) {
|
||||
case 'hasFakeTraffic':
|
||||
this.fakeTrafficConfig.enabled = false;
|
||||
this.stopFakeTrafficGeneration();
|
||||
break;
|
||||
case 'hasDecoyChannels':
|
||||
this.decoyChannelConfig.enabled = false;
|
||||
this.cleanupDecoyChannels();
|
||||
break;
|
||||
case 'hasPacketReordering':
|
||||
this.reorderingConfig.enabled = false;
|
||||
this.packetBuffer.clear();
|
||||
break;
|
||||
case 'hasAntiFingerprinting':
|
||||
this.antiFingerprintingConfig.enabled = false;
|
||||
break;
|
||||
case 'hasMessageChunking':
|
||||
this.chunkingConfig.enabled = false;
|
||||
break;
|
||||
}
|
||||
} else if (allowed && !this.securityFeatures[feature]) {
|
||||
console.log(`🔓 Enabling ${feature} for ${this.currentSessionType} session`);
|
||||
this.securityFeatures[feature] = true;
|
||||
|
||||
// Enable linked configurations
|
||||
switch (feature) {
|
||||
case 'hasFakeTraffic':
|
||||
this.fakeTrafficConfig.enabled = true;
|
||||
if (this.isConnected()) {
|
||||
this.startFakeTrafficGeneration();
|
||||
}
|
||||
break;
|
||||
case 'hasDecoyChannels':
|
||||
this.decoyChannelConfig.enabled = true;
|
||||
if (this.isConnected()) {
|
||||
this.initializeDecoyChannels();
|
||||
}
|
||||
break;
|
||||
case 'hasPacketReordering':
|
||||
this.reorderingConfig.enabled = true;
|
||||
break;
|
||||
case 'hasAntiFingerprinting':
|
||||
this.antiFingerprintingConfig.enabled = true;
|
||||
break;
|
||||
case 'hasMessageChunking':
|
||||
this.chunkingConfig.enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Security Level Notification
|
||||
notifySecurityLevel() {
|
||||
const levelMessages = {
|
||||
'basic': '🔒 Basic Security Active - Demo session with essential protection',
|
||||
'enhanced': '🔐 Enhanced Security Active - Paid session with advanced protection',
|
||||
'maximum': '🛡️ Maximum Security Active - Premium session with complete protection'
|
||||
};
|
||||
|
||||
const message = levelMessages[this.currentSecurityLevel] || levelMessages['basic'];
|
||||
|
||||
if (this.onMessage) {
|
||||
this.onMessage(message, 'system');
|
||||
}
|
||||
|
||||
// Showing details of functions for paid sessions
|
||||
if (this.currentSecurityLevel !== 'basic' && this.onMessage) {
|
||||
const activeFeatures = Object.entries(this.securityFeatures)
|
||||
.filter(([key, value]) => value === true)
|
||||
.map(([key]) => key.replace('has', '').replace(/([A-Z])/g, ' $1').trim().toLowerCase())
|
||||
.slice(0, 5);
|
||||
|
||||
this.onMessage(`🔧 Active: ${activeFeatures.join(', ')}...`, 'system');
|
||||
}
|
||||
}
|
||||
|
||||
// Cleaning decoy channels
|
||||
cleanupDecoyChannels() {
|
||||
// Stopping decoy traffic
|
||||
for (const [channelName, timer] of this.decoyTimers.entries()) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
this.decoyTimers.clear();
|
||||
|
||||
// Closing decoy channels
|
||||
for (const [channelName, channel] of this.decoyChannels.entries()) {
|
||||
if (channel.readyState === 'open') {
|
||||
channel.close();
|
||||
}
|
||||
}
|
||||
this.decoyChannels.clear();
|
||||
|
||||
console.log('🧹 Decoy channels cleaned up');
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 1. NESTED ENCRYPTION LAYER
|
||||
// ============================================
|
||||
@@ -1740,65 +1879,62 @@ handleSystemMessage(message) {
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// FUNCTION MANAGEMENT METHODS
|
||||
// ============================================
|
||||
// ============================================
|
||||
// FUNCTION MANAGEMENT METHODS
|
||||
// ============================================
|
||||
|
||||
// Method to enable Stage 2 functions
|
||||
enableStage2Security() {
|
||||
|
||||
// Enable Packet Reordering
|
||||
// Method to enable Stage 2 functions
|
||||
enableStage2Security() {
|
||||
if (this.sessionConstraints?.hasPacketReordering) {
|
||||
this.securityFeatures.hasPacketReordering = true;
|
||||
this.reorderingConfig.enabled = true;
|
||||
}
|
||||
|
||||
// Enable Simplified Anti-Fingerprinting
|
||||
if (this.sessionConstraints?.hasAntiFingerprinting) {
|
||||
this.securityFeatures.hasAntiFingerprinting = true;
|
||||
this.antiFingerprintingConfig.enabled = true;
|
||||
if (this.currentSecurityLevel === 'enhanced') {
|
||||
this.antiFingerprintingConfig.randomizeSizes = false;
|
||||
this.antiFingerprintingConfig.maskPatterns = false;
|
||||
this.antiFingerprintingConfig.useRandomHeaders = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Updating the UI security indicator
|
||||
this.notifySecurityUpgrade(2);
|
||||
}
|
||||
}
|
||||
|
||||
// Method to enable Stage 3 features (traffic obfuscation)
|
||||
enableStage3Security() {
|
||||
// Method to enable Stage 3 features (traffic obfuscation)
|
||||
enableStage3Security() {
|
||||
if (this.currentSecurityLevel !== 'maximum') {
|
||||
console.log('🔒 Stage 3 features only available for premium sessions');
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable Message Chunking
|
||||
if (this.sessionConstraints?.hasMessageChunking) {
|
||||
this.securityFeatures.hasMessageChunking = true;
|
||||
this.chunkingConfig.enabled = true;
|
||||
this.chunkingConfig.maxChunkSize = 2048; // Large chunks for stability
|
||||
this.chunkingConfig.minDelay = 100;
|
||||
this.chunkingConfig.maxDelay = 300;
|
||||
}
|
||||
|
||||
// Enable Fake Traffic
|
||||
if (this.sessionConstraints?.hasFakeTraffic) {
|
||||
this.securityFeatures.hasFakeTraffic = true;
|
||||
this.fakeTrafficConfig.enabled = true;
|
||||
this.fakeTrafficConfig.minInterval = 10000; // Rare messages
|
||||
this.fakeTrafficConfig.maxInterval = 30000;
|
||||
this.fakeTrafficConfig.minSize = 32;
|
||||
this.fakeTrafficConfig.maxSize = 128; // Small sizes
|
||||
|
||||
// Launching fake traffic
|
||||
this.startFakeTrafficGeneration();
|
||||
}
|
||||
|
||||
// Updating the UI security indicator
|
||||
this.notifySecurityUpgrade(3);
|
||||
}
|
||||
}
|
||||
|
||||
// Method for enabling Stage 4 functions (maximum safety)
|
||||
enableStage4Security() {
|
||||
console.log('🚀 Enabling Stage 4 security features (Maximum Security)...');
|
||||
// Method for enabling Stage 4 functions (maximum safety)
|
||||
enableStage4Security() {
|
||||
if (this.currentSecurityLevel !== 'maximum') {
|
||||
console.log('🔒 Stage 4 features only available for premium sessions');
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable Decoy Channels (only if the connection is stable)
|
||||
if (this.isConnected() && this.isVerified) {
|
||||
if (this.sessionConstraints?.hasDecoyChannels && this.isConnected() && this.isVerified) {
|
||||
this.securityFeatures.hasDecoyChannels = true;
|
||||
this.decoyChannelConfig.enabled = true;
|
||||
this.decoyChannelConfig.maxDecoyChannels = 2; // Only 2 channels
|
||||
|
||||
// Initialize decoy channels
|
||||
try {
|
||||
this.initializeDecoyChannels();
|
||||
} catch (error) {
|
||||
@@ -1808,37 +1944,40 @@ enableStage4Security() {
|
||||
}
|
||||
}
|
||||
|
||||
// Enable full Anti-Fingerprinting
|
||||
// Full anti-fingerprinting for maximum sessions
|
||||
if (this.sessionConstraints?.hasAntiFingerprinting) {
|
||||
this.antiFingerprintingConfig.randomizeSizes = true;
|
||||
this.antiFingerprintingConfig.maskPatterns = true;
|
||||
this.antiFingerprintingConfig.useRandomHeaders = false;
|
||||
}
|
||||
|
||||
// Updating the UI security indicator
|
||||
this.notifySecurityUpgrade(4);
|
||||
}
|
||||
}
|
||||
|
||||
// Method for getting security status
|
||||
getSecurityStatus() {
|
||||
// Method for getting security status
|
||||
getSecurityStatus() {
|
||||
const activeFeatures = Object.entries(this.securityFeatures)
|
||||
.filter(([key, value]) => value === true)
|
||||
.map(([key]) => key);
|
||||
|
||||
const stage = activeFeatures.length <= 3 ? 1 :
|
||||
activeFeatures.length <= 5 ? 2 :
|
||||
activeFeatures.length <= 7 ? 3 : 4;
|
||||
const stage = this.currentSecurityLevel === 'basic' ? 1 :
|
||||
this.currentSecurityLevel === 'enhanced' ? 2 :
|
||||
this.currentSecurityLevel === 'maximum' ? 4 : 1;
|
||||
|
||||
return {
|
||||
stage: stage,
|
||||
sessionType: this.currentSessionType,
|
||||
securityLevel: this.currentSecurityLevel,
|
||||
activeFeatures: activeFeatures,
|
||||
totalFeatures: Object.keys(this.securityFeatures).length,
|
||||
securityLevel: stage === 4 ? 'MAXIMUM' : stage === 3 ? 'HIGH' : stage === 2 ? 'MEDIUM' : 'BASIC',
|
||||
activeFeaturesCount: activeFeatures.length,
|
||||
activeFeaturesNames: activeFeatures
|
||||
activeFeaturesNames: activeFeatures,
|
||||
sessionConstraints: this.sessionConstraints
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Method to notify UI about security update
|
||||
notifySecurityUpgrade(stage) {
|
||||
// Method to notify UI about security update
|
||||
notifySecurityUpgrade(stage) {
|
||||
const stageNames = {
|
||||
1: 'Basic Enhanced',
|
||||
2: 'Medium Security',
|
||||
@@ -1872,66 +2011,60 @@ notifySecurityUpgrade(stage) {
|
||||
}
|
||||
|
||||
const status = this.getSecurityStatus();
|
||||
}
|
||||
// ============================================
|
||||
// AUTOMATIC STEP-BY-STEP SWITCHING ON
|
||||
// ============================================
|
||||
}
|
||||
// ============================================
|
||||
// AUTOMATIC STEP-BY-STEP SWITCHING ON
|
||||
// ============================================
|
||||
|
||||
// Method for automatic feature enablement with stability check
|
||||
async autoEnableSecurityFeatures() {
|
||||
// Method for automatic feature enablement with stability check
|
||||
async autoEnableSecurityFeatures() {
|
||||
|
||||
if (this.currentSessionType === 'demo') {
|
||||
console.log('🔒 Demo session - keeping basic security only');
|
||||
this.notifySecurityUpgrade(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// For paid sessions, we enable functions gradually
|
||||
const checkStability = () => {
|
||||
const isStable = this.isConnected() &&
|
||||
this.isVerified &&
|
||||
this.connectionAttempts === 0 &&
|
||||
this.messageQueue.length === 0 &&
|
||||
this.peerConnection?.connectionState === 'connected';
|
||||
|
||||
console.log('🔍 Stability check:', {
|
||||
isConnected: this.isConnected(),
|
||||
isVerified: this.isVerified,
|
||||
connectionAttempts: this.connectionAttempts,
|
||||
messageQueueLength: this.messageQueue.length,
|
||||
connectionState: this.peerConnection?.connectionState
|
||||
});
|
||||
|
||||
return isStable;
|
||||
};
|
||||
|
||||
// Stage 1 is already active
|
||||
console.log('🔒 Stage 1 active: Basic Enhanced Security');
|
||||
console.log(`🔒 ${this.currentSessionType} session - starting graduated security activation`);
|
||||
this.notifySecurityUpgrade(1);
|
||||
|
||||
// Wait 15 seconds of stable operation before Stage 2
|
||||
// For enhanced and maximum sessions, turn on Stage 2 after 10 seconds
|
||||
if (this.currentSecurityLevel === 'enhanced' || this.currentSecurityLevel === 'maximum') {
|
||||
setTimeout(() => {
|
||||
if (checkStability()) {
|
||||
console.log('✅ Stage 1 stable for 15 seconds, activating Stage 2');
|
||||
console.log('✅ Activating Stage 2 for paid session');
|
||||
this.enableStage2Security();
|
||||
|
||||
// Wait another 20 seconds before Stage 3
|
||||
// For maximum sessions, turn on Stage 3 and 4
|
||||
if (this.currentSecurityLevel === 'maximum') {
|
||||
setTimeout(() => {
|
||||
if (checkStability()) {
|
||||
console.log('✅ Stage 2 stable for 20 seconds, activating Stage 3');
|
||||
console.log('✅ Activating Stage 3 for premium session');
|
||||
this.enableStage3Security();
|
||||
|
||||
// Wait another 25 seconds before Stage 4
|
||||
setTimeout(() => {
|
||||
if (checkStability()) {
|
||||
console.log('✅ Stage 3 stable for 25 seconds, activating Stage 4');
|
||||
console.log('✅ Activating Stage 4 for premium session');
|
||||
this.enableStage4Security();
|
||||
} else {
|
||||
console.log('⚠️ Connection not stable enough for Stage 4');
|
||||
}
|
||||
}, 25000);
|
||||
} else {
|
||||
console.log('⚠️ Connection not stable enough for Stage 3');
|
||||
}
|
||||
}, 20000);
|
||||
} else {
|
||||
console.log('⚠️ Connection not stable enough for Stage 2');
|
||||
}
|
||||
}, 15000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// CONNECTION MANAGEMENT WITH ENHANCED SECURITY
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
class PayPerSessionManager {
|
||||
constructor(config = {}) {
|
||||
this.sessionPrices = {
|
||||
// SAFE demo mode with limitations
|
||||
demo: { sats: 0, hours: 0.1, usd: 0.00 },
|
||||
basic: { sats: 500, hours: 1, usd: 0.20 },
|
||||
premium: { sats: 1000, hours: 4, usd: 0.40 },
|
||||
extended: { sats: 2000, hours: 24, usd: 0.80 }
|
||||
demo: { sats: 0, hours: 0.1, usd: 0.00, securityLevel: 'basic' },
|
||||
basic: { sats: 5000, hours: 1, usd: 2.00, securityLevel: 'enhanced' },
|
||||
premium: { sats: 20000, hours: 6, usd: 8.00, securityLevel: 'maximum' }
|
||||
};
|
||||
|
||||
this.currentSession = null;
|
||||
@@ -33,7 +31,7 @@ class PayPerSessionManager {
|
||||
this.minTimeBetweenCompletedSessions = 15 * 60 * 1000;
|
||||
|
||||
// Minimum cost for paid sessions (protection against micropayment attacks)
|
||||
this.minimumPaymentSats = 100;
|
||||
this.minimumPaymentSats = 1000;
|
||||
|
||||
this.verificationConfig = {
|
||||
method: config.method || 'lnbits',
|
||||
@@ -66,7 +64,7 @@ class PayPerSessionManager {
|
||||
console.warn('❌ Multi-tab protection triggered:', multiTabCheck.message);
|
||||
}
|
||||
|
||||
console.log('💰 PayPerSessionManager initialized with ENHANCED secure demo mode');
|
||||
console.log('💰 PayPerSessionManager initialized with TIERED security levels');
|
||||
|
||||
setInterval(() => {
|
||||
this.savePersistentData();
|
||||
@@ -75,6 +73,89 @@ class PayPerSessionManager {
|
||||
console.log('💰 PayPerSessionManager initialized with ENHANCED secure demo mode and auto-save');
|
||||
}
|
||||
|
||||
getSecurityLevelForSession(sessionType) {
|
||||
const pricing = this.sessionPrices[sessionType];
|
||||
if (!pricing) return 'basic';
|
||||
|
||||
return pricing.securityLevel || 'basic';
|
||||
}
|
||||
|
||||
// Check if the function is allowed for the given session type
|
||||
isFeatureAllowedForSession(sessionType, feature) {
|
||||
const securityLevel = this.getSecurityLevelForSession(sessionType);
|
||||
|
||||
const featureMatrix = {
|
||||
'basic': {
|
||||
// DEMO сессии - только базовые функции
|
||||
hasEncryption: true,
|
||||
hasECDH: true,
|
||||
hasECDSA: false,
|
||||
hasMutualAuth: false,
|
||||
hasMetadataProtection: false,
|
||||
hasEnhancedReplayProtection: false,
|
||||
hasNonExtractableKeys: false,
|
||||
hasRateLimiting: true,
|
||||
hasEnhancedValidation: false,
|
||||
hasPFS: false,
|
||||
|
||||
// Advanced features are DISABLED for demo
|
||||
hasNestedEncryption: false,
|
||||
hasPacketPadding: false,
|
||||
hasPacketReordering: false,
|
||||
hasAntiFingerprinting: false,
|
||||
hasFakeTraffic: false,
|
||||
hasDecoyChannels: false,
|
||||
hasMessageChunking: false
|
||||
},
|
||||
'enhanced': {
|
||||
// BASIC paid sessions - improved security
|
||||
hasEncryption: true,
|
||||
hasECDH: true,
|
||||
hasECDSA: true,
|
||||
hasMutualAuth: true,
|
||||
hasMetadataProtection: true,
|
||||
hasEnhancedReplayProtection: true,
|
||||
hasNonExtractableKeys: true,
|
||||
hasRateLimiting: true,
|
||||
hasEnhancedValidation: true,
|
||||
hasPFS: true,
|
||||
|
||||
// Partially enabled advanced features
|
||||
hasNestedEncryption: true,
|
||||
hasPacketPadding: true,
|
||||
hasPacketReordering: false,
|
||||
hasAntiFingerprinting: false,
|
||||
hasFakeTraffic: false,
|
||||
hasDecoyChannels: false,
|
||||
hasMessageChunking: false
|
||||
},
|
||||
'maximum': {
|
||||
// PREMIUM sessions - all functions included
|
||||
hasEncryption: true,
|
||||
hasECDH: true,
|
||||
hasECDSA: true,
|
||||
hasMutualAuth: true,
|
||||
hasMetadataProtection: true,
|
||||
hasEnhancedReplayProtection: true,
|
||||
hasNonExtractableKeys: true,
|
||||
hasRateLimiting: true,
|
||||
hasEnhancedValidation: true,
|
||||
hasPFS: true,
|
||||
|
||||
// ALL advanced features
|
||||
hasNestedEncryption: true,
|
||||
hasPacketPadding: true,
|
||||
hasPacketReordering: true,
|
||||
hasAntiFingerprinting: true,
|
||||
hasFakeTraffic: true,
|
||||
hasDecoyChannels: true,
|
||||
hasMessageChunking: true
|
||||
}
|
||||
};
|
||||
|
||||
return featureMatrix[securityLevel]?.[feature] || false;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// FIXED DEMO MODE: Improved controls and management
|
||||
// ============================================
|
||||
@@ -1410,12 +1491,12 @@ class PayPerSessionManager {
|
||||
startTime: now,
|
||||
expiresAt: expiresAt,
|
||||
preimage: preimage,
|
||||
isDemo: sessionType === 'demo'
|
||||
isDemo: sessionType === 'demo',
|
||||
securityLevel: this.getSecurityLevelForSession(sessionType) // НОВОЕ ПОЛЕ
|
||||
};
|
||||
|
||||
this.startSessionTimer();
|
||||
|
||||
// IMPORTANT: Set up automatic cleaning for demo sessions
|
||||
if (sessionType === 'demo') {
|
||||
setTimeout(() => {
|
||||
this.handleDemoSessionExpiry(preimage);
|
||||
@@ -1423,31 +1504,94 @@ class PayPerSessionManager {
|
||||
}
|
||||
|
||||
const durationMinutes = Math.round(duration / (60 * 1000));
|
||||
console.log(`📅 Session ${sessionId.substring(0, 8)}... activated for ${durationMinutes} minutes`);
|
||||
console.log(`📅 Session ${sessionId.substring(0, 8)}... activated for ${durationMinutes} minutes with ${this.currentSession.securityLevel} security`);
|
||||
|
||||
if (sessionType === 'demo') {
|
||||
this.activeDemoSessions.add(preimage);
|
||||
this.usedPreimages.add(preimage);
|
||||
console.log(`🌐 Demo session added to active sessions. Total: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`);
|
||||
|
||||
if (window.DEBUG_MODE) {
|
||||
console.log(`🔍 Demo session debug:`, {
|
||||
sessionId: sessionId.substring(0, 8),
|
||||
duration: durationMinutes + ' minutes',
|
||||
expiresAt: new Date(expiresAt).toLocaleTimeString(),
|
||||
currentTime: new Date(now).toLocaleTimeString(),
|
||||
timeLeft: this.getTimeLeft() + 'ms'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// SENDING SECURITY LEVEL INFORMATION TO WebRTC
|
||||
setTimeout(() => {
|
||||
this.notifySessionActivated();
|
||||
// Notify WebRTC manager about session type
|
||||
if (window.webrtcManager && window.webrtcManager.configureSecurityForSession) {
|
||||
window.webrtcManager.configureSecurityForSession(sessionType, this.currentSession.securityLevel);
|
||||
}
|
||||
}, 100);
|
||||
|
||||
return this.currentSession;
|
||||
}
|
||||
|
||||
// UPDATED method for getting session information
|
||||
getSessionInfo() {
|
||||
if (!this.currentSession) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const securityLevel = this.getSecurityLevelForSession(this.currentSession.type);
|
||||
const pricing = this.sessionPrices[this.currentSession.type];
|
||||
|
||||
return {
|
||||
...this.currentSession,
|
||||
securityLevel: securityLevel,
|
||||
securityDescription: this.getSecurityDescription(securityLevel),
|
||||
pricing: pricing,
|
||||
timeLeft: this.getTimeLeft(),
|
||||
isConnected: this.hasActiveSession()
|
||||
};
|
||||
}
|
||||
|
||||
getSecurityDescription(level) {
|
||||
const descriptions = {
|
||||
'basic': {
|
||||
title: 'Basic Security',
|
||||
features: [
|
||||
'End-to-end encryption',
|
||||
'Basic key exchange',
|
||||
'Rate limiting',
|
||||
'Message integrity'
|
||||
],
|
||||
limitations: [
|
||||
'No advanced obfuscation',
|
||||
'No traffic padding',
|
||||
'No decoy channels'
|
||||
]
|
||||
},
|
||||
'enhanced': {
|
||||
title: 'Enhanced Security',
|
||||
features: [
|
||||
'All basic features',
|
||||
'ECDSA signatures',
|
||||
'Metadata protection',
|
||||
'Perfect forward secrecy',
|
||||
'Nested encryption',
|
||||
'Packet padding'
|
||||
],
|
||||
limitations: [
|
||||
'Limited traffic obfuscation',
|
||||
'No fake traffic generation'
|
||||
]
|
||||
},
|
||||
'maximum': {
|
||||
title: 'Maximum Security',
|
||||
features: [
|
||||
'All enhanced features',
|
||||
'Traffic obfuscation',
|
||||
'Fake traffic generation',
|
||||
'Decoy channels',
|
||||
'Anti-fingerprinting',
|
||||
'Message chunking',
|
||||
'Packet reordering protection'
|
||||
],
|
||||
limitations: []
|
||||
}
|
||||
};
|
||||
|
||||
return descriptions[level] || descriptions['basic'];
|
||||
}
|
||||
|
||||
notifySessionActivated() {
|
||||
if (!this.currentSession) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user