release: v4.8.7 WebRTC join reliability patch
This commit is contained in:
1 parent
1cc873223a
commit
2468cb495e
17 files changed
+2093
-217
No files matched your search
+21
-2
@@ -1,6 +1,25 @@
|
||||
# Changelog
|
||||
|
||||
## v4.8.6 — Security hardening patch release
|
||||
## v4.8.7 — WebRTC manual join reliability patch
|
||||
|
||||
This patch improves manual WebRTC setup across separate devices and restrictive local networks.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Stabilized the manual offer/answer join flow so verification waits for real transport readiness.
|
||||
- Preserved generated response data during manual exchange instead of resetting the joiner screen prematurely.
|
||||
- Preserved pending creator-side offer context so responses can be applied after transient ICE failures without false session-salt hijacking errors.
|
||||
- Added operator ICE override support through `config/ice-servers.js`.
|
||||
- Added ExpressTURN TURN/STUN configuration for relay fallback in environments where mDNS host candidates cannot connect.
|
||||
- Added user-visible warning when a remote peer provides only mDNS host candidates and no `srflx` or `relay` route.
|
||||
- Added safer ICE diagnostics that report candidate classes without exposing full IP addresses or TURN credentials.
|
||||
|
||||
### Verification
|
||||
|
||||
- `npm test`
|
||||
- `npm run build`
|
||||
|
||||
## v4.8.7 — Security hardening patch release
|
||||
|
||||
This patch release strengthens SecureBit.chat across verification, sanitization, privacy, transport abuse resistance, cache safety, and repository hygiene.
|
||||
|
||||
@@ -29,7 +48,7 @@ This patch release strengthens SecureBit.chat across verification, sanitization,
|
||||
- Clean install succeeds with `npm ci`.
|
||||
- Production build succeeds with `npm run build`.
|
||||
|
||||
## v4.8.5 — Security hardening release
|
||||
## v4.8.7 — Security hardening release
|
||||
|
||||
This release consolidates several months of security, privacy, and lifecycle hardening work by the SecureBit.chat team.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SecureBit.chat v4.8.6
|
||||
# SecureBit.chat v4.8.7
|
||||
|
||||
SecureBit.chat is a browser-based peer-to-peer chat application built on WebRTC and Web Crypto APIs. It is designed for direct encrypted communication, explicit peer verification, and a small operational footprint without account registration or server-side message storage.
|
||||
|
||||
@@ -15,7 +15,11 @@ SecureBit.chat uses:
|
||||
|
||||
A session is not treated as verified until both peers complete the interactive SAS flow. Each user must compare the displayed code with the peer through an out-of-band channel and enter the matching code manually. Three failed SAS attempts terminate the session.
|
||||
|
||||
## Highlights in v4.8.6
|
||||
## Highlights in v4.8.7
|
||||
|
||||
- Manual WebRTC setup now preserves pending offer/answer state during slow out-of-band exchange.
|
||||
- TURN relay fallback can be configured through `config/ice-servers.js` for restrictive networks.
|
||||
- ICE diagnostics now identify mDNS-only candidate failures without exposing full peer IPs.
|
||||
|
||||
This patch release strengthens the existing security model with a focused hardening pass:
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// SecureBit.chat operator ICE server override.
|
||||
// Loaded before the WebRTC manager is created. Credentials are visible to browsers;
|
||||
// rotate them from the ExpressTURN dashboard if this file is published publicly.
|
||||
window.SECUREBIT_ICE_SERVERS = [
|
||||
{ urls: 'stun:stun.cloudflare.com:3478' },
|
||||
{ urls: 'stun:stun.expressturn.com:3478' },
|
||||
{
|
||||
urls: [
|
||||
'turn:free.expressturn.com:3478?transport=udp',
|
||||
'turn:free.expressturn.com:3478?transport=tcp'
|
||||
],
|
||||
username: '000000002094555952',
|
||||
credential: 't1oK9Zftes9j7E7hJmsLad9jq1M='
|
||||
}
|
||||
];
|
||||
Vendored
+1646
-110
File diff suppressed because it is too large.
Load diff
Vendored
+4
-4
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../src/notifications/SecureNotificationManager.js", "../src/notifications/NotificationIntegration.js", "../src/crypto/EnhancedSecureCryptoUtils.js", "../src/transfer/EnhancedSecureFileTransfer.js", "../src/network/EnhancedSecureWebRTCManager.js", "../src/scripts/app-boot.js", "../src/components/ui/Header.jsx", "../src/components/ui/DownloadApps.jsx", "../src/components/ui/BecomePartner.jsx", "../src/components/ui/UniqueFeatureSlider.jsx", "../src/components/ui/SecurityFeatures.jsx", "../src/components/ui/Testimonials.jsx", "../src/components/ui/ComparisonTable.jsx", "../src/components/ui/Roadmap.jsx", "../src/components/ui/FileTransfer.jsx"],
|
||||
"sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise<boolean>} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n Line truncated
|
||||
"mappings": "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 truncated
|
||||
"names": ["NotificationIntegration", "fileMessageTypes", "attempts", "start", "error", "attempts", "chunk", "fileMessageTypes", "window", "start", "webrtcManager", "start"]
|
||||
"sources": ["../src/notifications/SecureNotificationManager.js", "../src/notifications/NotificationIntegration.js", "../node_modules/dompurify/src/utils.ts", "../node_modules/dompurify/src/tags.ts", "../node_modules/dompurify/src/attrs.ts", "../node_modules/dompurify/src/regexp.ts", "../node_modules/dompurify/src/purify.ts", "../src/crypto/EnhancedSecureCryptoUtils.js", "../src/transfer/EnhancedSecureFileTransfer.js", "../src/network/EnhancedSecureWebRTCManager.js", "../src/scripts/app-boot.js", "../src/components/ui/Header.jsx", "../src/components/ui/DownloadApps.jsx", "../src/components/ui/BecomePartner.jsx", "../src/components/ui/UniqueFeatureSlider.jsx", "../src/components/ui/SecurityFeatures.jsx", "../src/components/ui/Testimonials.jsx", "../src/components/ui/ComparisonTable.jsx", "../src/components/ui/Roadmap.jsx", "../src/components/ui/FileTransfer.jsx"],
|
||||
"sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise<boolean>} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n Line truncated
|
||||
"mappings": "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 truncated
|
||||
"names": ["text", "NotificationIntegration", "entries", "Object", "setPrototypeOf", "isFrozen", "getPrototypeOf", "getOwnPropertyDescriptor", "freeze", "seal", "create", "_ref", "Reflect", "apply", "construct", "x", "func", "thisArg", "_len", "arguments", "length", "args", "Array", "_key", "Func", "_len2", "_key2", "arrayForEach", "unapply", "prototype", "forEach", "arrayLastIndexOf", "lastIndexOf", "arrayPop", "pop", "arrayPush", "push", "arraySplice", "splice", "arrayIsArray", "isArray", "stringToLowerCase", "String", "toLowerCase", "stringToString", "toString", "stringMatch", "match", "stringReplace", "replace", "stringIndexOf", "indexOf", "stringTrim", "trim", "numberToString", "Number", "booleanToString", "Boolean", "bigintToString", "BigInt", "symbolToString", "Symbol", "objectHasOwnProperty", "hasOwnProperty", "objectToString", "regExpTest", "RegExp", "test", "typeErrorCreate", "unconstruct", "TypeError", "lastIndex", "_len3", "_key3", "_len4", "_key4", "addToSet", "set", "array", "transformCaseFunc", "l", "element", "lcElement", "cleanArray", "index", "isPropertyExist", "clone", "object", "newObject", "_ref2", "_ref3", "_slicedToArray", "property", "value", "constructor", "stringifyValue", "valueAsRecord", "valueToString", "lookupGetter", "stringified", "prop", "desc", "get", "fallbackValue", "isRegex", "_unused", "html", "svg", "svgFilters", "svgDisallowed", "mathMl", "mathMlDisallowed", "text", "xml", "MUSTACHE_EXPR", "ERB_EXPR", "TMPLIT_EXPR", "DATA_ATTR", "ARIA_ATTR", "IS_ALLOWED_URI", "IS_SCRIPT_OR_DATA", "ATTR_WHITESPACE", "DOCTYPE_NAME", "CUSTOM_ELEMENT", "NODE_TYPE", "progressingInstruction", "comment", "document", "getGlobal", "window", "_createTrustedTypesPolicy", "trustedTypes", "purifyHostElement", "createPolicy", "suffix", "ATTR_NAME", "hasAttribute", "getAttribute", "policyName", "createHTML", "createScriptURL", "scriptUrl", "_", "console", "warn", "_createHooksMap", "afterSanitizeAttributes", "afterSanitizeElements", "afterSanitizeShadowDOM", "beforeSanitizeAttributes", "beforeSanitizeElements", "beforeSanitizeShadowDOM", "uponSanitizeAttribute", "uponSanitizeElement", "uponSanitizeShadowNode", "createDOMPurify", "undefined", "DOMPurify", "root", "version", "VERSION", "removed", "nodeType", "Element", "isSupported", "originalDocument", "currentScript", "DocumentFragment", "HTMLTemplateElement", "Node", "NodeFilter", "_window$NamedNodeMap", "NamedNodeMap", "MozNamedAttrMap", "HTMLFormElement", "DOMParser", "ElementPrototype", "cloneNode", "remove", "getNextSibling", "getChildNodes", "getParentNode", "getNodeType", "template", "createElement", "content", "ownerDocument", "trustedTypesPolicy", "emptyHTML", "_document", "implementation", "createNodeIterator", "createDocumentFragment", "getElementsByTagName", "importNode", "hooks", "createHTMLDocument", "EXPRESSIONS", "ALLOWED_TAGS", "DEFAULT_ALLOWED_TAGS", "TAGS", "ALLOWED_ATTR", "DEFAULT_ALLOWED_ATTR", "ATTRS", "CUSTOM_ELEMENT_HANDLING", "tagNameCheck", "writable", "configurable", "enumerable", "attributeNameCheck", "allowCustomizedBuiltInElements", "FORBID_TAGS", "FORBID_ATTR", "EXTRA_ELEMENT_HANDLING", "tagCheck", "attributeCheck", "ALLOW_ARIA_ATTR", "ALLOW_DATA_ATTR", "ALLOW_UNKNOWN_PROTOCOLS", "ALLOW_SELF_CLOSE_IN_ATTR", "SAFE_FOR_TEMPLATES", "SAFE_FOR_XML", "WHOLE_DOCUMENT", "SET_CONFIG", "FORCE_BODY", "RETURN_DOM", "RETURN_DOM_FRAGMENT", "RETURN_TRUSTED_TYPE", "SANITIZE_DOM", "SANITIZE_NAMED_PROPS", "SANITIZE_NAMED_PROPS_PREFIX", "KEEP_CONTENT", "IN_PLACE", "USE_PROFILES", "FORBID_CONTENTS", "DEFAULT_FORBID_CONTENTS", "DATA_URI_TAGS", "DEFAULT_DATA_URI_TAGS", "URI_SAFE_ATTRIBUTES", "DEFAULT_URI_SAFE_ATTRIBUTES", "MATHML_NAMESPACE", "SVG_NAMESPACE", "HTML_NAMESPACE", "NAMESPACE", "IS_EMPTY_INPUT", "ALLOWED_NAMESPACES", "DEFAULT_ALLOWED_NAMESPACES", "MATHML_TEXT_INTEGRATION_POINTS", "HTML_INTEGRATION_POINTS", "COMMON_SVG_AND_HTML_ELEMENTS", "PARSER_MEDIA_TYPE", "SUPPORTED_PARSER_MEDIA_TYPES", "DEFAULT_PARSER_MEDIA_TYPE", "CONFIG", "formElement", "isRegexOrFunction", "testValue", "Function", "_parseConfig", "cfg", "ADD_URI_SAFE_ATTR", "ADD_DATA_URI_TAGS", "ALLOWED_URI_REGEXP", "customElementHandling", "ADD_TAGS", "ADD_ATTR", "ADD_FORBID_CONTENTS", "table", "tbody", "TRUSTED_TYPES_POLICY", "ALL_SVG_TAGS", "ALL_MATHML_TAGS", "_checkValidNamespace", "parent", "tagName", "namespaceURI", "parentTagName", "_forceRemove", "node", "removeChild", "_removeAttribute", "name", "attribute", "getAttributeNode", "from", "removeAttribute", "setAttribute", "_initDocument", "dirty", "doc", "leadingWhitespace", "matches", "dirtyPayload", "parseFromString", "documentElement", "createDocument", "innerHTML", "body", "insertBefore", "createTextNode", "childNodes", "call", "_createNodeIterator", "SHOW_ELEMENT", "SHOW_COMMENT", "SHOW_TEXT", "SHOW_PROCESSING_INSTRUCTION", "SHOW_CDATA_SECTION", "_scrubTemplateExpressions", "normalize", "walker", "currentNode", "nextNode", "data", "expr", "_isClobbered", "nodeName", "textContent", "attributes", "hasChildNodesLine truncated
|
||||
}
|
||||
Vendored
+91
-68
@@ -1,3 +1,36 @@
|
||||
// src/utils/debugWindowHooks.js
|
||||
function isSecureBitDebugEnabled(targetWindow = globalThis.window) {
|
||||
return targetWindow?.SECUREBIT_DEBUG === true;
|
||||
}
|
||||
function installDebugWindowHooks({
|
||||
targetWindow = globalThis.window,
|
||||
webrtcManagerRef,
|
||||
onClearData,
|
||||
clearConsole = () => {
|
||||
if (typeof console.clear === "function") {
|
||||
console.clear();
|
||||
}
|
||||
}
|
||||
}) {
|
||||
if (!isSecureBitDebugEnabled(targetWindow)) {
|
||||
return () => {
|
||||
};
|
||||
}
|
||||
targetWindow.forceCleanup = () => {
|
||||
onClearData();
|
||||
if (webrtcManagerRef.current) {
|
||||
webrtcManagerRef.current.disconnect();
|
||||
}
|
||||
};
|
||||
targetWindow.clearLogs = clearConsole;
|
||||
targetWindow.webrtcManagerRef = webrtcManagerRef;
|
||||
return () => {
|
||||
delete targetWindow.forceCleanup;
|
||||
delete targetWindow.clearLogs;
|
||||
delete targetWindow.webrtcManagerRef;
|
||||
};
|
||||
}
|
||||
|
||||
// src/app.jsx
|
||||
var EnhancedCopyButton = ({ text, className = "", children }) => {
|
||||
const [copied, setCopied] = React.useState(false);
|
||||
@@ -322,9 +355,11 @@ var EnhancedConnectionSetup = ({
|
||||
markAnswerCreated,
|
||||
notificationIntegrationRef,
|
||||
isGeneratingKeys,
|
||||
setIsGeneratingKeys,
|
||||
handleCreateOffer,
|
||||
relayOnlyMode,
|
||||
setRelayOnlyMode
|
||||
setRelayOnlyMode,
|
||||
webrtcManagerRef
|
||||
}) => {
|
||||
const [mode, setMode] = React.useState("select");
|
||||
const [notificationPermissionRequested, setNotificationPermissionRequested] = React.useState(false);
|
||||
@@ -714,6 +749,7 @@ var EnhancedConnectionSetup = ({
|
||||
text: (() => {
|
||||
try {
|
||||
const min = typeof offerData === "object" ? JSON.stringify(offerData) : offerData || "";
|
||||
if (!min) return "";
|
||||
if (typeof window.encodeBinaryToPrefixed === "function") {
|
||||
return window.encodeBinaryToPrefixed(min);
|
||||
}
|
||||
@@ -1032,6 +1068,7 @@ var EnhancedConnectionSetup = ({
|
||||
text: (() => {
|
||||
try {
|
||||
const min = typeof answerData === "object" ? JSON.stringify(answerData) : answerData || "";
|
||||
if (!min) return "";
|
||||
if (typeof window.encodeBinaryToPrefixed === "function") {
|
||||
return window.encodeBinaryToPrefixed(min);
|
||||
}
|
||||
@@ -1449,7 +1486,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
const [qrCodeUrl, setQrCodeUrl] = React.useState("");
|
||||
const [showQRScanner, setShowQRScanner] = React.useState(false);
|
||||
const [showQRScannerModal, setShowQRScannerModal] = React.useState(false);
|
||||
const [isGeneratingKeys, setIsGeneratingKeys2] = React.useState(false);
|
||||
const [isGeneratingKeys, setIsGeneratingKeys] = React.useState(false);
|
||||
const [isVerified, setIsVerified] = React.useState(false);
|
||||
const [securityLevel, setSecurityLevel] = React.useState(null);
|
||||
const [sessionTimeLeft, setSessionTimeLeft] = React.useState(0);
|
||||
@@ -1474,12 +1511,9 @@ var EnhancedSecureP2PChat = () => {
|
||||
}));
|
||||
};
|
||||
const shouldPreserveAnswerData = () => {
|
||||
const now = Date.now();
|
||||
const answerAge = now - (connectionState.answerCreatedAt || 0);
|
||||
const maxPreserveTime = 3e5;
|
||||
const hasAnswerData = answerData && typeof answerData === "string" && answerData.trim().length > 0 || answerInput && answerInput.trim().length > 0;
|
||||
const hasAnswerQR = qrCodeUrl && qrCodeUrl.trim().length > 0;
|
||||
const shouldPreserve = connectionState.hasActiveAnswer && answerAge < maxPreserveTime && !connectionState.isUserInitiatedDisconnect || hasAnswerData && answerAge < maxPreserveTime && !connectionState.isUserInitiatedDisconnect || hasAnswerQR && answerAge < maxPreserveTime && !connectionState.isUserInitiatedDisconnect;
|
||||
const hasAnswerData = !!answerData || answerInput && typeof answerInput === "string" && answerInput.trim().length > 0;
|
||||
const hasAnswerQR = qrCodeUrl && typeof qrCodeUrl === "string" && qrCodeUrl.trim().length > 0;
|
||||
const shouldPreserve = connectionState.hasActiveAnswer && !connectionState.isUserInitiatedDisconnect || hasAnswerData && !connectionState.isUserInitiatedDisconnect || hasAnswerQR && !connectionState.isUserInitiatedDisconnect;
|
||||
return shouldPreserve;
|
||||
};
|
||||
const markAnswerCreated = () => {
|
||||
@@ -1488,26 +1522,15 @@ var EnhancedSecureP2PChat = () => {
|
||||
answerCreatedAt: Date.now()
|
||||
});
|
||||
};
|
||||
React.useEffect(() => {
|
||||
window.forceCleanup = () => {
|
||||
handleClearData();
|
||||
if (webrtcManagerRef2.current) {
|
||||
webrtcManagerRef2.current.disconnect();
|
||||
}
|
||||
};
|
||||
window.clearLogs = () => {
|
||||
if (typeof console.clear === "function") {
|
||||
console.clear();
|
||||
}
|
||||
};
|
||||
return () => {
|
||||
delete window.forceCleanup;
|
||||
delete window.clearLogs;
|
||||
};
|
||||
}, []);
|
||||
const webrtcManagerRef2 = React.useRef(null);
|
||||
const webrtcManagerRef = React.useRef(null);
|
||||
const notificationIntegrationRef = React.useRef(null);
|
||||
window.webrtcManagerRef = webrtcManagerRef2;
|
||||
React.useEffect(() => {
|
||||
return installDebugWindowHooks({
|
||||
targetWindow: window,
|
||||
webrtcManagerRef,
|
||||
onClearData: handleClearData
|
||||
});
|
||||
}, []);
|
||||
const addMessageWithAutoScroll = React.useCallback((message, type) => {
|
||||
const newMessage = {
|
||||
message,
|
||||
@@ -1548,7 +1571,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
}
|
||||
window.isUpdatingSecurity = true;
|
||||
try {
|
||||
if (webrtcManagerRef2.current) {
|
||||
if (webrtcManagerRef.current) {
|
||||
setSecurityLevel({
|
||||
level: "MAXIMUM",
|
||||
score: 100,
|
||||
@@ -1559,7 +1582,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
isRealData: true
|
||||
});
|
||||
if (window.DEBUG_MODE) {
|
||||
const currentLevel = webrtcManagerRef2.current.ecdhKeyPair && webrtcManagerRef2.current.ecdsaKeyPair ? await webrtcManagerRef2.current.calculateSecurityLevel() : {
|
||||
const currentLevel = webrtcManagerRef.current.ecdhKeyPair && webrtcManagerRef.current.ecdsaKeyPair ? await webrtcManagerRef.current.calculateSecurityLevel() : {
|
||||
level: "MAXIMUM",
|
||||
score: 100,
|
||||
sessionType: "premium",
|
||||
@@ -1589,8 +1612,8 @@ var EnhancedSecureP2PChat = () => {
|
||||
localStorage.setItem("securebit_relay_only_mode", String(relayOnlyMode));
|
||||
} catch {
|
||||
}
|
||||
if (webrtcManagerRef2.current?._config?.webrtc) {
|
||||
webrtcManagerRef2.current._config.webrtc.relayOnly = relayOnlyMode;
|
||||
if (webrtcManagerRef.current?._config?.webrtc) {
|
||||
webrtcManagerRef.current._setRelayOnlyMode(relayOnlyMode);
|
||||
}
|
||||
}, [relayOnlyMode]);
|
||||
React.useEffect(() => {
|
||||
@@ -1601,7 +1624,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
}
|
||||
}, [messages]);
|
||||
React.useEffect(() => {
|
||||
if (webrtcManagerRef2.current) {
|
||||
if (webrtcManagerRef.current) {
|
||||
console.log("\u26A0\uFE0F WebRTC Manager already initialized, skipping...");
|
||||
return;
|
||||
}
|
||||
@@ -1763,7 +1786,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
if (typeof console.clear === "function") {
|
||||
console.clear();
|
||||
}
|
||||
webrtcManagerRef2.current = new EnhancedSecureWebRTCManager(
|
||||
webrtcManagerRef.current = new EnhancedSecureWebRTCManager(
|
||||
handleMessage,
|
||||
handleStatusChange,
|
||||
handleKeyExchange,
|
||||
@@ -1779,7 +1802,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
);
|
||||
if (typeof Notification !== "undefined" && Notification && Notification.permission === "granted" && window.NotificationIntegration && !notificationIntegrationRef.current) {
|
||||
try {
|
||||
const integration = new window.NotificationIntegration(webrtcManagerRef2.current);
|
||||
const integration = new window.NotificationIntegration(webrtcManagerRef.current);
|
||||
integration.init().then(() => {
|
||||
notificationIntegrationRef.current = integration;
|
||||
}).catch((error) => {
|
||||
@@ -1787,12 +1810,12 @@ var EnhancedSecureP2PChat = () => {
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
handleMessage(" SecureBit.chat Enhanced Security Edition v4.8.5 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.", "system");
|
||||
handleMessage(" SecureBit.chat Enhanced Security Edition v4.8.7 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.", "system");
|
||||
const handleBeforeUnload = (event) => {
|
||||
if (event.type === "beforeunload" && !isTabSwitching) {
|
||||
if (webrtcManagerRef2.current && webrtcManagerRef2.current.isConnected()) {
|
||||
if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) {
|
||||
try {
|
||||
webrtcManagerRef2.current.sendSystemMessage({
|
||||
webrtcManagerRef.current.sendSystemMessage({
|
||||
type: "peer_disconnect",
|
||||
reason: "user_disconnect",
|
||||
timestamp: Date.now()
|
||||
@@ -1800,12 +1823,12 @@ var EnhancedSecureP2PChat = () => {
|
||||
} catch (error) {
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (webrtcManagerRef2.current) {
|
||||
webrtcManagerRef2.current.disconnect();
|
||||
if (webrtcManagerRef.current) {
|
||||
webrtcManagerRef.current.disconnect();
|
||||
}
|
||||
}, 100);
|
||||
} else if (webrtcManagerRef2.current) {
|
||||
webrtcManagerRef2.current.disconnect();
|
||||
} else if (webrtcManagerRef.current) {
|
||||
webrtcManagerRef.current.disconnect();
|
||||
}
|
||||
} else if (isTabSwitching) {
|
||||
event.preventDefault();
|
||||
@@ -1833,8 +1856,8 @@ var EnhancedSecureP2PChat = () => {
|
||||
}
|
||||
};
|
||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||
if (webrtcManagerRef2.current) {
|
||||
webrtcManagerRef2.current.setFileTransferCallbacks(
|
||||
if (webrtcManagerRef.current) {
|
||||
webrtcManagerRef.current.setFileTransferCallbacks(
|
||||
// Progress callback
|
||||
(progress) => {
|
||||
console.log("File progress:", progress);
|
||||
@@ -1886,9 +1909,9 @@ var EnhancedSecureP2PChat = () => {
|
||||
clearTimeout(tabSwitchTimeout);
|
||||
tabSwitchTimeout = null;
|
||||
}
|
||||
if (webrtcManagerRef2.current) {
|
||||
webrtcManagerRef2.current.disconnect();
|
||||
webrtcManagerRef2.current = null;
|
||||
if (webrtcManagerRef.current) {
|
||||
webrtcManagerRef.current.disconnect();
|
||||
webrtcManagerRef.current = null;
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
@@ -2553,12 +2576,12 @@ var EnhancedSecureP2PChat = () => {
|
||||
};
|
||||
const handleCreateOffer = async () => {
|
||||
try {
|
||||
setIsGeneratingKeys2(true);
|
||||
setIsGeneratingKeys(true);
|
||||
setOfferData("");
|
||||
setShowOfferStep(false);
|
||||
setShowQRCode(false);
|
||||
setQrCodeUrl("");
|
||||
const offer = await webrtcManagerRef2.current.createSecureOffer();
|
||||
const offer = await webrtcManagerRef.current.createSecureOffer();
|
||||
setOfferData(offer);
|
||||
setShowOfferStep(true);
|
||||
const offerString = typeof offer === "object" ? JSON.stringify(offer) : offer;
|
||||
@@ -2643,7 +2666,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
timestamp: Date.now()
|
||||
}]);
|
||||
} finally {
|
||||
setIsGeneratingKeys2(false);
|
||||
setIsGeneratingKeys(false);
|
||||
}
|
||||
};
|
||||
const handleCreateAnswer = async () => {
|
||||
@@ -2683,7 +2706,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
if (!isValidOfferType) {
|
||||
throw new Error("Invalid invitation type. Expected offer or enhanced_secure_offer");
|
||||
}
|
||||
const answer = await webrtcManagerRef2.current.createSecureAnswer(offer);
|
||||
const answer = await webrtcManagerRef.current.createSecureAnswer(offer);
|
||||
setAnswerData(answer);
|
||||
setShowAnswerStep(true);
|
||||
const answerString = typeof answer === "object" ? JSON.stringify(answer) : answer;
|
||||
@@ -2740,10 +2763,8 @@ var EnhancedSecureP2PChat = () => {
|
||||
} catch (e) {
|
||||
console.warn("Answer QR generation failed:", e);
|
||||
}
|
||||
if (answerInput.trim().length > 0) {
|
||||
if (typeof markAnswerCreated === "function") {
|
||||
markAnswerCreated();
|
||||
}
|
||||
if (typeof markAnswerCreated === "function") {
|
||||
markAnswerCreated();
|
||||
}
|
||||
const existingResponseMessages = messages.filter(
|
||||
(m) => m.type === "system" && (m.message.includes("Secure response created") || m.message.includes("Send the response"))
|
||||
@@ -2821,7 +2842,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
if (!answerType || answerType !== "answer" && answerType !== "enhanced_secure_answer") {
|
||||
throw new Error("Invalid response type. Expected answer or enhanced_secure_answer");
|
||||
}
|
||||
await webrtcManagerRef2.current.handleSecureAnswer(answer);
|
||||
await webrtcManagerRef.current.handleSecureAnswer(answer);
|
||||
if (pendingSession) {
|
||||
setPendingSession(null);
|
||||
setMessages((prev) => [...prev, {
|
||||
@@ -2909,11 +2930,11 @@ var EnhancedSecureP2PChat = () => {
|
||||
};
|
||||
const handleVerifyConnection = async (userCode, isValid = true) => {
|
||||
if (isValid) {
|
||||
webrtcManagerRef2.current.confirmVerification(userCode);
|
||||
webrtcManagerRef.current.confirmVerification(userCode);
|
||||
setLocalVerificationConfirmed(true);
|
||||
try {
|
||||
if (window.NotificationIntegration && webrtcManagerRef2.current && !notificationIntegrationRef.current) {
|
||||
const integration = new window.NotificationIntegration(webrtcManagerRef2.current);
|
||||
if (window.NotificationIntegration && webrtcManagerRef.current && !notificationIntegrationRef.current) {
|
||||
const integration = new window.NotificationIntegration(webrtcManagerRef.current);
|
||||
await integration.init();
|
||||
notificationIntegrationRef.current = integration;
|
||||
const status = integration.getStatus();
|
||||
@@ -2971,15 +2992,15 @@ var EnhancedSecureP2PChat = () => {
|
||||
if (!messageInput.trim()) {
|
||||
return;
|
||||
}
|
||||
if (!webrtcManagerRef2.current) {
|
||||
if (!webrtcManagerRef.current) {
|
||||
return;
|
||||
}
|
||||
if (!webrtcManagerRef2.current.isConnected()) {
|
||||
if (!webrtcManagerRef.current.isConnected()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
addMessageWithAutoScroll(messageInput.trim(), "sent");
|
||||
await webrtcManagerRef2.current.sendMessage(messageInput);
|
||||
await webrtcManagerRef.current.sendMessage(messageInput);
|
||||
setMessageInput("");
|
||||
} catch (error) {
|
||||
const msg = String(error?.message || error);
|
||||
@@ -2994,7 +3015,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
setOfferInput("");
|
||||
setAnswerInput("");
|
||||
setShowOfferStep(false);
|
||||
setIsGeneratingKeys2(false);
|
||||
setIsGeneratingKeys(false);
|
||||
if (!shouldPreserveAnswerData()) {
|
||||
setShowAnswerStep(false);
|
||||
}
|
||||
@@ -3030,8 +3051,8 @@ var EnhancedSecureP2PChat = () => {
|
||||
status: "disconnected",
|
||||
isUserInitiatedDisconnect: true
|
||||
});
|
||||
if (webrtcManagerRef2.current) {
|
||||
webrtcManagerRef2.current.disconnect();
|
||||
if (webrtcManagerRef.current) {
|
||||
webrtcManagerRef.current.disconnect();
|
||||
}
|
||||
if (notificationIntegrationRef.current) {
|
||||
notificationIntegrationRef.current.cleanup();
|
||||
@@ -3052,7 +3073,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
setAnswerInput("");
|
||||
setShowOfferStep(false);
|
||||
setShowAnswerStep(false);
|
||||
setIsGeneratingKeys2(false);
|
||||
setIsGeneratingKeys(false);
|
||||
setShowQRCode(false);
|
||||
setQrCodeUrl("");
|
||||
setShowQRScanner(false);
|
||||
@@ -3195,7 +3216,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
isConnected: isConnectedAndVerified,
|
||||
securityLevel,
|
||||
// sessionManager removed - all features enabled by default
|
||||
webrtcManager: webrtcManagerRef2.current
|
||||
webrtcManager: webrtcManagerRef.current
|
||||
}),
|
||||
React.createElement(
|
||||
"main",
|
||||
@@ -3215,7 +3236,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
isVerified,
|
||||
chatMessagesRef,
|
||||
scrollToBottom,
|
||||
webrtcManager: webrtcManagerRef2.current
|
||||
webrtcManager: webrtcManagerRef.current
|
||||
});
|
||||
})() : React.createElement(EnhancedConnectionSetup, {
|
||||
onCreateOffer: handleCreateOffer,
|
||||
@@ -3255,9 +3276,11 @@ var EnhancedSecureP2PChat = () => {
|
||||
markAnswerCreated,
|
||||
notificationIntegrationRef,
|
||||
isGeneratingKeys,
|
||||
setIsGeneratingKeys,
|
||||
handleCreateOffer,
|
||||
relayOnlyMode,
|
||||
setRelayOnlyMode
|
||||
setRelayOnlyMode,
|
||||
webrtcManagerRef
|
||||
})
|
||||
),
|
||||
// QR Scanner Modal
|
||||
|
||||
Vendored
+4
-4
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../src/app.jsx"],
|
||||
"sourcesContent": ["\n // Enhanced Copy Button with better UX\n const EnhancedCopyButton = ({ text, className = \"\", children }) => {\n const [copied, setCopied] = React.useState(false);\n \n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (error) {\n console.error('Copy failed:', error);\n // Fallback for older browsers\n const textArea = document.createElement('textarea');\n textArea.value = text;\n document.body.appendChild(textArea);\n textArea.select();\n document.execCommand('copy');\n document.body.removeChild(textArea);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n \n return React.createElement('button', {\n onClick: handleCopy,\n className: `${className} transition-all duration-200`\n }, [\n React.createElement('i', {\n key: 'icon',\n className: `${copied ? 'fas fa-check accent-green' : 'fas fa-copy text-secondary'} mr-2`\n }),\n copied ? 'Copied!' : children\n ]);\n };\n \n // Verification Component\n const VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => {\n const [sasInput, setSasInput] = React.useState('');\n const [error, setError] = React.useState('');\n const normalizedExpectedLength = (verificationCode || '').replace(/[-\\s]/g, '').length;\n const normalizedInputLength = sasInput.replace(/[-\\s]/g, '').length;\n const canConfirm = !localConfirmed && normalizedExpectedLength > 0 && normalizedInputLength === normalizedExpectedLength;\n\n React.useEffect(() => {\n setSasInput('');\n setError('');\n }, [verificationCode]);\n\n const handleConfirm = async () => {\n try {\n setError('');\n await onConfirm(sasInput);\n } catch (confirmationError) {\n setSasInput('');\n if (confirmationError?.message === 'SAS_MAX_ATTEMPTS') {\n setError('Too many incorrect attempts. Session reset for safety.');\n } else {\n setError('Incorrect code. Check it with your peer and try again.');\n }\n }\n };\n\n return React.createElement('div', {\n className: \"card-minimal rounded-xl p-6 border-purple-500/20\"\n }, [\n React.createElement('div', {\n key: 'header',\n className: \"flex items-center mb-4\"\n }, [\n React.createElement('div', {\n key: 'icon',\n className: \"w-10 h-10 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mr-3\"\n }, [\n React.createElement('i', {\n className: 'fas fa-shield-alt accent-purple'\n })\n ]),\n React.createElement('h3', {\n key: 'title',\n className: \"text-lg font-medium text-primary\"\n }, \"Security verification\")\n ]),\n React.createElement('div', {\n key: 'content',\n className: \"space-y-4\"\n }, [\n React.createElement('p', {\n key: 'description',\n className: \"text-secondary text-sm\"\n }, \"Compare this code with your peer out-of-band, then type the same code below to unlock the chat.\"),\n Line truncated
|
||||
"mappings": "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 truncated
|
||||
"names": ["setIsGeneratingKeys", "webrtcManagerRef", "offerData", "payload", "UpdateCheckerWrapper"]
|
||||
"sources": ["../src/utils/debugWindowHooks.js", "../src/app.jsx"],
|
||||
"sourcesContent": ["function isSecureBitDebugEnabled(targetWindow = globalThis.window) {\n return targetWindow?.SECUREBIT_DEBUG === true;\n}\n\nfunction installDebugWindowHooks({\n targetWindow = globalThis.window,\n webrtcManagerRef,\n onClearData,\n clearConsole = () => {\n if (typeof console.clear === 'function') {\n console.clear();\n }\n }\n}) {\n if (!isSecureBitDebugEnabled(targetWindow)) {\n return () => {};\n }\n\n targetWindow.forceCleanup = () => {\n onClearData();\n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n }\n };\n targetWindow.clearLogs = clearConsole;\n targetWindow.webrtcManagerRef = webrtcManagerRef;\n\n return () => {\n delete targetWindow.forceCleanup;\n delete targetWindow.clearLogs;\n delete targetWindow.webrtcManagerRef;\n };\n}\n\nexport { installDebugWindowHooks, isSecureBitDebugEnabled };\n", "import { installDebugWindowHooks } from './utils/debugWindowHooks.js';\n // Enhanced Copy Button with better UX\n const EnhancedCopyButton = ({ text, className = \"\", children }) => {\n const [copied, setCopied] = React.useState(false);\n \n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (error) {\n console.error('Copy failed:', error);\n // Fallback for older browsers\n const textArea = document.createElement('textarea');\n textArea.value = text;\n document.body.appendChild(textArea);\n textArea.select();\n document.execCommand('copy');\n document.body.removeChild(textArea);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n \n return React.createElement('button', {\n onClick: handleCopy,\n className: `${className} transition-all duration-200`\n }, [\n React.createElement('i', {\n key: 'icon',\n className: `${copied ? 'fas fa-check accent-green' : 'fas fa-copy text-secondary'} mr-2`\n }),\n copied ? 'Copied!' : children\n ]);\n };\n \n // Verification Component\n const VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => {\n const [sasInput, setSasInput] = React.useState('');\n const [error, setError] = React.useState('');\n const normalizedExpectedLength = (verificationCode || '').replace(/[-\\s]/g, '').length;\n const normalizedInputLength = sasInput.replace(/[-\\s]/g, '').length;\n const canConfirm = !localConfirmed && normalizedExpectedLength > 0 && normalizedInputLength === normalizedExpectedLength;\n\n React.useEffect(() => {\n setSasInput('');\n setError('');\n }, [verificationCode]);\n\n const handleConfirm = async () => {\n try {\n setError('');\n await onConfirm(sasInput);\n } catch (confirmationError) {\n setSasInput('');\n if (confirmationError?.message === 'SAS_MAX_ATTEMPTS') {\n setError('Too many incorrect attempts. Session reset for safety.');\n } else {\n setError('Incorrect code. Check it with your peer and try again.');\n }\n }\n };\n\n return React.createElement('div', {\n className: \"card-minimal rounded-xl p-6 border-purple-500/20\"\n }, [\n React.createElement('div', {\n key: 'header',\n className: \"flex items-center mb-4\"\n }, [\n React.createElement('div', {\n key: 'icon',\n className: \"w-10 h-10 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-centeLine truncated
|
||||
"mappings": "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 truncated
|
||||
"names": ["offerData", "payload", "UpdateCheckerWrapper"]
|
||||
}
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../node_modules/qrcode/lib/can-promise.js", "../node_modules/qrcode/lib/core/utils.js", "../node_modules/qrcode/lib/core/error-correction-level.js", "../node_modules/qrcode/lib/core/bit-buffer.js", "../node_modules/qrcode/lib/core/bit-matrix.js", "../node_modules/qrcode/lib/core/alignment-pattern.js", "../node_modules/qrcode/lib/core/finder-pattern.js", "../node_modules/qrcode/lib/core/mask-pattern.js", "../node_modules/qrcode/lib/core/error-correction-code.js", "../node_modules/qrcode/lib/core/galois-field.js", "../node_modules/qrcode/lib/core/polynomial.js", "../node_modules/qrcode/lib/core/reed-solomon-encoder.js", "../node_modules/qrcode/lib/core/version-check.js", "../node_modules/qrcode/lib/core/regex.js", "../node_modules/qrcode/lib/core/mode.js", "../node_modules/qrcode/lib/core/version.js", "../node_modules/qrcode/lib/core/format-info.js", "../node_modules/qrcode/lib/core/numeric-data.js", "../node_modules/qrcode/lib/core/alphanumeric-data.js", "../node_modules/qrcode/lib/core/byte-data.js", "../node_modules/qrcode/lib/core/kanji-data.js", "../node_modules/dijkstrajs/dijkstra.js", "../node_modules/qrcode/lib/core/segments.js", "../node_modules/qrcode/lib/core/qrcode.js", "../node_modules/qrcode/lib/renderer/utils.js", "../node_modules/qrcode/lib/renderer/canvas.js", "../node_modules/qrcode/lib/renderer/svg-tag.js", "../node_modules/qrcode/lib/browser.js", "../node_modules/html5-qrcode/third_party/zxing-js.umd.js", "../node_modules/cbor-js/cbor.js", "../node_modules/base64-js/index.js", "../src/scripts/qr-local.js", "../node_modules/src/core.ts", "../node_modules/src/strings.ts", "../node_modules/src/utils.ts", "../node_modules/src/zxing-html5-qrcode-decoder.ts", "../node_modules/src/native-bar-code-detector.ts", "../node_modules/src/code-decoder.ts", "../node_modules/src/camera/core-impl.ts", "../node_modules/src/camera/factories.ts", "../node_modules/src/camera/retriever.ts", "../node_modules/src/state-manager.ts", "../node_modules/src/html5-qrcode.ts", "../node_modules/src/image-assets.ts", "../node_modules/src/storage.ts", "../node_modules/src/ui.ts", "../node_modules/src/camera/permissions.ts", "../node_modules/src/ui/scanner/scan-type-selector.ts", "../node_modules/src/ui/scanner/base.ts", "../node_modules/src/ui/scanner/torch-button.ts", "../node_modules/src/ui/scanner/file-selection-ui.ts", "../node_modules/src/ui/scanner/camera-selection-ui.ts", "../node_modules/src/ui/scanner/camera-zoom-ui.ts", "../node_modules/src/html5-qrcode-scanner.ts", "../node_modules/pako/dist/pako.esm.mjs", "../src/crypto/cose-qr.js"],
|
||||
"sourcesContent": ["// can-promise has a crash in some versions of react native that dont have\n// standard global objects\n// https://github.com/soldair/node-qrcode/issues/157\n\nmodule.exports = function () {\n return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then\n}\n", "let toSJISFunction\nconst CODEWORDS_COUNT = [\n 0, // Not used\n 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,\n 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,\n 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,\n 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706\n]\n\n/**\n * Returns the QR Code size for the specified version\n *\n * @param {Number} version QR Code version\n * @return {Number} size of QR code\n */\nexports.getSymbolSize = function getSymbolSize (version) {\n if (!version) throw new Error('\"version\" cannot be null or undefined')\n if (version < 1 || version > 40) throw new Error('\"version\" should be in range from 1 to 40')\n return version * 4 + 17\n}\n\n/**\n * Returns the total number of codewords used to store data and EC information.\n *\n * @param {Number} version QR Code version\n * @return {Number} Data length in bits\n */\nexports.getSymbolTotalCodewords = function getSymbolTotalCodewords (version) {\n return CODEWORDS_COUNT[version]\n}\n\n/**\n * Encode data with Bose-Chaudhuri-Hocquenghem\n *\n * @param {Number} data Value to encode\n * @return {Number} Encoded value\n */\nexports.getBCHDigit = function (data) {\n let digit = 0\n\n while (data !== 0) {\n digit++\n data >>>= 1\n }\n\n return digit\n}\n\nexports.setToSJISFunction = function setToSJISFunction (f) {\n if (typeof f !== 'function') {\n throw new Error('\"toSJISFunc\" is not a valid function.')\n }\n\n toSJISFunction = f\n}\n\nexports.isKanjiModeEnabled = function () {\n return typeof toSJISFunction !== 'undefined'\n}\n\nexports.toSJIS = function toSJIS (kanji) {\n return toSJISFunction(kanji)\n}\n", "exports.L = { bit: 1 }\nexports.M = { bit: 0 }\nexports.Q = { bit: 3 }\nexports.H = { bit: 2 }\n\nfunction fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase()\n\n switch (lcStr) {\n case 'l':\n case 'low':\n return exports.L\n\n case 'm':\n case 'medium':\n return exports.M\n\n case 'q':\n case 'quartile':\n return exports.Q\n\n case 'h':\n case 'high':\n return exports.H\n\n default:\n throw new Error('Unknown EC Level: ' + string)\n }\n}\n\nexports.isValid = function isValid (level) {\n return level && typeof level.bit !== 'undefined' &&\n level.bit >= 0 && level.bit < 4\n}\n\nexports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n}\n", "function BitBuffer () {\n this.buffer = []\n this.length = 0\n}\n\nBitBuffer.prototype = {\n\n get: function (index) {\n const bufIndex = Math.floor(index / 8)\n return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1\n },\n\n put: function (num, length) {\n for (let i = 0; i < length; i++) {\n this.putBit(((num >>> (length - i - 1)) & 1) === 1)\n }\n },\n\n getLengthInBits: function () {\n return this.length\n },\n\n putBit: function (bit) {\n const bufIndex = Math.floor(this.length / 8)\n if (this.buffer.length <= bufIndex) {\n this.buffer.push(0)\n }\n\n if (bit) {\n this.buffer[bufIndex] |= (0x80 >>> (this.length % 8))\n }\n\n this.length++\n }\n}\n\nmodule.exports = BitBuffer\n", "/**\n * Helper class to handle QR Code symbol modules\n *\n * @param {Number} size Symbol size\n */\nfunction BitMatrix (size) {\n if (!size || size < 1) {\n throw new Error('BitMatrix size must be defined and greater than 0')\n }\n\n this.size = size\n this.data = new Uint8Array(size * size)\n this.reservedBit = new Uint8Array(size * size)\n}\n\n/**\n * Set bit value at specified location\n * If reserved flag is set, this bit will be ignored during masking process\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n * @param {Boolean} reserved\n */\nBitMatrix.prototype.set = function (row, col, value, reserved) {\n const index = row * this.size + col\n this.data[index] = value\n if (reserved) this.reservedBit[index] = true\n}\n\n/**\n * Returns bit value at specified location\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\nBitMatrix.prototype.get = function (row, col) {\n return this.data[row * this.size + col]\n}\n\n/**\n * Applies xor operator at specified location\n * (used during masking process)\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n */\nBitMatrix.prototype.xor = function (row, col, value) {\n this.data[row * this.size + col] ^= value\n}\n\n/*Line truncated
|
||||
"sourcesContent": ["// can-promise has a crash in some versions of react native that dont have\n// standard global objects\n// https://github.com/soldair/node-qrcode/issues/157\n\nmodule.exports = function () {\n return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then\n}\n", "let toSJISFunction\nconst CODEWORDS_COUNT = [\n 0, // Not used\n 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,\n 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,\n 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,\n 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706\n]\n\n/**\n * Returns the QR Code size for the specified version\n *\n * @param {Number} version QR Code version\n * @return {Number} size of QR code\n */\nexports.getSymbolSize = function getSymbolSize (version) {\n if (!version) throw new Error('\"version\" cannot be null or undefined')\n if (version < 1 || version > 40) throw new Error('\"version\" should be in range from 1 to 40')\n return version * 4 + 17\n}\n\n/**\n * Returns the total number of codewords used to store data and EC information.\n *\n * @param {Number} version QR Code version\n * @return {Number} Data length in bits\n */\nexports.getSymbolTotalCodewords = function getSymbolTotalCodewords (version) {\n return CODEWORDS_COUNT[version]\n}\n\n/**\n * Encode data with Bose-Chaudhuri-Hocquenghem\n *\n * @param {Number} data Value to encode\n * @return {Number} Encoded value\n */\nexports.getBCHDigit = function (data) {\n let digit = 0\n\n while (data !== 0) {\n digit++\n data >>>= 1\n }\n\n return digit\n}\n\nexports.setToSJISFunction = function setToSJISFunction (f) {\n if (typeof f !== 'function') {\n throw new Error('\"toSJISFunc\" is not a valid function.')\n }\n\n toSJISFunction = f\n}\n\nexports.isKanjiModeEnabled = function () {\n return typeof toSJISFunction !== 'undefined'\n}\n\nexports.toSJIS = function toSJIS (kanji) {\n return toSJISFunction(kanji)\n}\n", "exports.L = { bit: 1 }\nexports.M = { bit: 0 }\nexports.Q = { bit: 3 }\nexports.H = { bit: 2 }\n\nfunction fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase()\n\n switch (lcStr) {\n case 'l':\n case 'low':\n return exports.L\n\n case 'm':\n case 'medium':\n return exports.M\n\n case 'q':\n case 'quartile':\n return exports.Q\n\n case 'h':\n case 'high':\n return exports.H\n\n default:\n throw new Error('Unknown EC Level: ' + string)\n }\n}\n\nexports.isValid = function isValid (level) {\n return level && typeof level.bit !== 'undefined' &&\n level.bit >= 0 && level.bit < 4\n}\n\nexports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n}\n", "function BitBuffer () {\n this.buffer = []\n this.length = 0\n}\n\nBitBuffer.prototype = {\n\n get: function (index) {\n const bufIndex = Math.floor(index / 8)\n return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1\n },\n\n put: function (num, length) {\n for (let i = 0; i < length; i++) {\n this.putBit(((num >>> (length - i - 1)) & 1) === 1)\n }\n },\n\n getLengthInBits: function () {\n return this.length\n },\n\n putBit: function (bit) {\n const bufIndex = Math.floor(this.length / 8)\n if (this.buffer.length <= bufIndex) {\n this.buffer.push(0)\n }\n\n if (bit) {\n this.buffer[bufIndex] |= (0x80 >>> (this.length % 8))\n }\n\n this.length++\n }\n}\n\nmodule.exports = BitBuffer\n", "/**\n * Helper class to handle QR Code symbol modules\n *\n * @param {Number} size Symbol size\n */\nfunction BitMatrix (size) {\n if (!size || size < 1) {\n throw new Error('BitMatrix size must be defined and greater than 0')\n }\n\n this.size = size\n this.data = new Uint8Array(size * size)\n this.reservedBit = new Uint8Array(size * size)\n}\n\n/**\n * Set bit value at specified location\n * If reserved flag is set, this bit will be ignored during masking process\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n * @param {Boolean} reserved\n */\nBitMatrix.prototype.set = function (row, col, value, reserved) {\n const index = row * this.size + col\n this.data[index] = value\n if (reserved) this.reservedBit[index] = true\n}\n\n/**\n * Returns bit value at specified location\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\nBitMatrix.prototype.get = function (row, col) {\n return this.data[row * this.size + col]\n}\n\n/**\n * Applies xor operator at specified location\n * (used during masking process)\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n */\nBitMatrix.prototype.xor = function (row, col, value) {\n this.data[row * this.size + col] ^= value\n}\n\n/*Line truncated
|
||||
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAIA,WAAO,UAAU,WAAY;AAC3B,aAAO,OAAO,YAAY,cAAc,QAAQ,aAAa,QAAQ,UAAU;AAAA,IACjF;AAAA;AAAA;;;ACNA;AAAA;AAAA,QAAI;AACJ,QAAM,kBAAkB;AAAA,MACtB;AAAA;AAAA,MACA;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAC1C;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAC7C;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MACtD;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,IACxD;AAQA,YAAQ,gBAAgB,SAAS,cAAe,SAAS;AACvD,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,uCAAuC;AACrE,UAAI,UAAU,KAAK,UAAU,GAAI,OAAM,IAAI,MAAM,2CAA2C;AAC5F,aAAO,UAAU,IAAI;AAAA,IACvB;AAQA,YAAQ,0BAA0B,SAAS,wBAAyB,SAAS;AAC3E,aAAO,gBAAgB,OAAO;AAAA,IAChC;AAQA,YAAQ,cAAc,SAAU,MAAM;AACpC,UAAI,QAAQ;AAEZ,aAAO,SAAS,GAAG;AACjB;AACA,kBAAU;AAAA,MACZ;AAEA,aAAO;AAAA,IACT;AAEA,YAAQ,oBAAoB,SAAS,kBAAmB,GAAG;AACzD,UAAI,OAAO,MAAM,YAAY;AAC3B,cAAM,IAAI,MAAM,uCAAuC;AAAA,MACzD;AAEA,uBAAiB;AAAA,IACnB;AAEA,YAAQ,qBAAqB,WAAY;AACvC,aAAO,OAAO,mBAAmB;AAAA,IACnC;AAEA,YAAQ,SAAS,SAAS,OAAQ,OAAO;AACvC,aAAO,eAAe,KAAK;AAAA,IAC7B;AAAA;AAAA;;;AC9DA;AAAA;AAAA,YAAQ,IAAI,EAAE,KAAK,EAAE;AACrB,YAAQ,IAAI,EAAE,KAAK,EAAE;AACrB,YAAQ,IAAI,EAAE,KAAK,EAAE;AACrB,YAAQ,IAAI,EAAE,KAAK,EAAE;AAErB,aAAS,WAAY,QAAQ;AAC3B,UAAI,OAAO,WAAW,UAAU;AAC9B,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAEA,YAAM,QAAQ,OAAO,YAAY;AAEjC,cAAQ,OAAO;AAAA,QACb,KAAK;AAAA,QACL,KAAK;AACH,iBAAO,QAAQ;AAAA,QAEjB,KAAK;AAAA,QACL,KAAK;AACH,iBAAO,QAAQ;AAAA,QAEjB,KAAK;AAAA,QACL,KAAK;AACH,iBAAO,QAAQ;AAAA,QAEjB,KAAK;AAAA,QACL,KAAK;AACH,iBAAO,QAAQ;AAAA,QAEjB;AACE,gBAAM,IAAI,MAAM,uBAAuB,MAAM;AAAA,MACjD;AAAA,IACF;AAEA,YAAQ,UAAU,SAAS,QAAS,OAAO;AACzC,aAAO,SAAS,OAAO,MAAM,QAAQ,eACnC,MAAM,OAAO,KAAK,MAAM,MAAM;AAAA,IAClC;AAEA,YAAQ,OAAO,SAAS,KAAM,OAAO,cAAc;AACjD,UAAI,QAAQ,QAAQ,KAAK,GAAG;AAC1B,eAAO;AAAA,MACT;AAEA,UAAI;AACF,eAAO,WAAW,KAAK;AAAA,MACzB,SAAS,GAAG;AACV,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;;;ACjDA;AAAA;AAAA,aAAS,YAAa;AACpB,WAAK,SAAS,CAAC;AACf,WAAK,SAAS;AAAA,IAChB;AAEA,cAAU,YAAY;AAAA,MAEpB,KAAK,SAAU,OAAO;AACpB,cAAM,WAAW,KAAK,MAAM,QAAQ,CAAC;AACrC,gBAAS,KAAK,OAAO,QAAQ,MAAO,IAAI,QAAQ,IAAM,OAAO;AAAA,MAC/D;AAAA,MAEA,KAAK,SAAU,KAAK,QAAQ;AAC1B,iBAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,eAAK,QAAS,QAAS,SAAS,IAAI,IAAM,OAAO,CAAC;AAAA,QACpD;AAAA,MACF;AAAA,MAEA,iBAAiB,WAAY;AAC3B,eAAO,KAAK;AAAA,MACd;AAAA,MAEA,QAAQ,SAAU,KAAK;AACrB,cAAM,WAAW,KAAK,MAAM,KAAK,SAAS,CAAC;AAC3C,YAAI,KAAK,OAAO,UAAU,UAAU;AAClC,eAAK,OAAO,KAAK,CAAC;AAAA,QACpB;AAEA,YAAI,KAAK;AACP,eAAK,OAAO,QAAQ,KAAM,QAAU,KAAK,SAAS;AAAA,QACpD;AAEA,aAAK;AAAA,MACP;AAAA,IACF;AAEA,WAAO,UAAU;AAAA;AAAA;;;ACpCjB;AAAA;AAKA,aAAS,UAAW,MAAM;AACxB,UAAI,CAAC,QAAQ,OAAO,GAAG;AACrB,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACrE;AAEA,WAAK,OAAO;AACZ,WAAK,OAAO,IAAI,WAAW,OAAO,IAAI;AACtC,WAAK,cAAc,IAAI,WAAW,OAAO,IAAI;AAAA,IAC/C;AAWA,cAAU,UAAU,MAAM,SAAU,KAAK,KAAK,OAAO,UAAU;AAC7D,YAAM,QAAQ,MAAM,KAAK,OAAO;AAChC,WAAK,KAAK,KAAK,IAAI;AACnB,UAAI,SAAU,MAAK,YAAY,KAAK,IAAI;AAAA,IAC1C;AASA,cAAU,UAAU,MAAM,SAAU,KAAK,KAAK;AAC5C,aAAO,KAAK,KAAK,MAAM,KAAK,OAAO,GAAG;AAAA,IACxC;AAUA,cAAU,UAAU,MAAM,SAAU,KAAK,KAAK,OAAO;AACnD,WAAK,KAAK,MAAM,KAAK,OAAO,GAAG,KAAK;AAAA,IACtC;AASA,cAAU,UAAU,aAAa,SAAU,KAAK,KAAK;AACnD,aAAO,KAAK,YAAY,MAAM,KAAK,OAAO,GAAG;AAAA,IAC/C;AAEA,WAAO,UAAU;AAAA;AAAA;;;AChEjB;AAAA;AAUA,QAAM,gBAAgB,gBAAmB;AAgBzC,YAAQ,kBAAkB,SAAS,gBAAiB,SAAS;AAC3D,UAAI,YAAY,EAAG,QAAO,CAAC;AAE3B,YAAM,WAAW,KAAK,MAAM,UAAU,CAAC,IAAI;AAC3C,YAAM,OAAO,cAAc,OAAO;AAClC,YAAM,YAAY,SAAS,MAAM,KAAK,KAAK,MAAM,OAAO,OAAO,IAAI,WAAW,EAAE,IAAI;AACpF,YAAM,YAAY,CAAC,OAAO,CAAC;AAE3B,eAAS,IAAI,GAAG,IAAI,WAAW,GAAG,KAAK;AACrC,kBAAU,CAAC,IAAI,UAAU,IAAI,CAAC,IAAI;AAAA,MACpC;AAEA,gBAAU,KAAK,CAAC;AAEhB,aAAO,UAAU,QAAQ;AAAA,IAC3B;AAsBA,YAAQ,eAAe,SAAS,aAAc,SAAS;AACrD,YAAM,SAAS,CAAC;AAChB,YAAM,MAAM,QAAQ,gBAAgB,OAAO;AAC3C,YAAM,YAAY,IAAI;AAEtB,eAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,iBAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAElC,cAAK,MAAM,KAAK,MAAM;AAAA,UACjB,MAAM,KAAK,MAAM,YAAY;AAAA,UAC7B,MAAM,YAAY,KAAK,MAAM,GAAI;AACpC;AAAA,UACF;AAEA,iBAAO,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAAA,QAC9B;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;;;AClFA;AAAA;AAAA,QAAM,gBAAgB,gBAAmB;AACzC,QAAM,sBAAsB;AAS5B,YAAQ,eAAe,SAAS,aAAc,SAAS;AACrD,YAAM,OAAO,cAAc,OAAO;AAElC,aAAO;AAAA;AAAA,QAEL,CAAC,GAAG,CAAC;AAAA;AAAA,QAEL,CAAC,OAAO,qBAAqB,CAAC;AAAA;AAAA,QAE9B,CAAC,GAAG,OAAO,mBAAmB;AAAA,MAChC;AAAA,IACF;AAAA;AAAA;;;ACrBA;AAAA;AAIA,YAAQ,WAAW;AAAA,MACjB,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,IACd;AAMA,QAAM,gBAAgB;AAAA,MACpB,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAQA,YAAQ,UAAU,SAAS,QAAS,MAAM;AACxC,aAAO,QAAQ,QAAQ,SAAS,MAAM,CAAC,MAAM,IAAI,KAAK,QAAQ,KAAK,QAAQ;AAAA,IAC7E;AASA,YAAQ,OAAO,SAAS,KAAM,OAAO;AACnC,aAAO,QAAQ,QAAQ,KAAK,IAAI,SAAS,OAAO,EAAE,IAAI;AAAA,IACxD;AASA,YAAQ,eAAe,SAAS,aAAc,MAAM;AAClD,YAAM,OAAO,KAAK;AAClB,UAAI,SAAS;AACb,UAAI,eAAe;AACnB,UAAI,eAAe;AACnB,UAAI,UAAU;AACd,UAAI,UAAU;AAEd,eAAS,MAAM,GAAG,MAAM,MAAM,OAAO;AACnC,uBAAe,eAAe;AAC9B,kBAAU,UALine truncated
|
||||
"names": ["module", "encode", "toString", "require_utils", "QRCode", "global", "exports", "isNullOrUndefined", "__extends", "CustomError", "BinaryBitmap", "DecodeHintType", "CharacterSetValueIdentifiers", "localLuminances", "HybridBinarizer", "HTMLCanvasElementLuminanceSource", "__awaiter", "err", "BarcodeFormat", "ResultMetadataType", "Table", "cx", "cy", "resultPoint", "numeric", "value", "Mode", "ErrorCorrectionLevelValues", "DataMaskValues", "ModeValues", "column", "MultiFormatReader", "EncodeHintType", "QRCode", "SHIFT_TABLE", "CHAR_MAP", "add", "global", "undefined", "encode", "i", "value", "dataView", "decode", "toByteArray", "fromByteArray", "len", "i", "len2", "Html5QrcodeSupportedFormats", "DecodedTextType", "Html5QrcodeScanType", "Html5QrcodeConstants", "QrcodeResultFormat", "Html5QrcodeResultFactory", "Html5QrcodeErrorTypes", "Html5QrcodeErrorFactory", "BaseLoggger", "Html5QrcodeStrings", "Html5QrcodeScannerStrings", "LibraryInfoStrings", "VideoConstraintsUtil", "ZXingHtml5QrcodeDecoder", "BarcodeDetectorDelegate", "Html5QrcodeShim", "AbstractCameraCapability", "AbstractRangeCameraCapability", "ZoomFeatureImpl", "TorchFeatureImpl", "CameraCapabilitiesImpl", "RenderedCameraImpl", "CameraImpl", "CameraFactory", "CameraRetriever", "_i", "Html5QrcodeScannerState", "StateManagerImpl", "StateManagerProxy", "StateManagerFactory", "__extends", "Constants", "InternalHtml5QrcodeConfig", "Html5Qrcode", "PersistedDataFactory", "PersistedDataManager", "LibraryInfoDiv", "LibraryInfoIcon", "LibraryInfoContainer", "CameraPermissions", "ScanTypeSelector", "PublicUiElementIdAndClasses", "BaseUiElementFactory", "TorchController", "TorchButton", "__awaiter", "FileSelectionUi", "CameraSelectionUi", "CameraZoomUi", "Html5QrcodeScannerStatus", "Html5QrcodeScanner", "cameraId", "_", "rank", "cbor", "compressed", "payload"]
|
||||
}
|
||||
+6
-5
@@ -113,7 +113,7 @@
|
||||
|
||||
|
||||
<!-- GitHub Pages SEO -->
|
||||
<meta name="description" content="SecureBit.chat v4.4.18 — P2P messenger with ECDH + DTLS + SAS security and 18-layer military-grade cryptography">
|
||||
<meta name="description" content="SecureBit.chat v4.8.7 — P2P messenger with ECDH + DTLS + SAS security and 18-layer military-grade cryptography">
|
||||
<meta name="keywords" content="P2P messenger, ECDH, DTLS, SAS, encryption, WebRTC, privacy, ASN.1 validation, military-grade security, 18-layer defense, MITM protection, PFS">
|
||||
<meta name="author" content="Volodymyr">
|
||||
<link rel="canonical" href="https://github.com/SecureBitChat/securebit-chat/">
|
||||
@@ -131,6 +131,7 @@
|
||||
<meta name="twitter:description" content="P2P messenger with military-grade cryptography">
|
||||
|
||||
<title>SecureBit.chat - Enhanced Security Edition</title>
|
||||
<script src="config/ice-servers.js"></script>
|
||||
<script src="libs/react/react.production.min.js"></script>
|
||||
<script src="libs/react-dom/react-dom.production.min.js"></script>
|
||||
<link rel="stylesheet" href="assets/tailwind.css">
|
||||
@@ -147,13 +148,13 @@
|
||||
<!-- Update Manager - система принудительного обновления -->
|
||||
<script src="src/utils/updateManager.js"></script>
|
||||
<script type="module" src="src/components/UpdateChecker.jsx"></script>
|
||||
<script type="module" src="dist/qr-local.js?v=1779043608721"></script>
|
||||
<script type="module" src="src/components/QRScanner.js?v=1779043608721"></script>
|
||||
<script type="module" src="dist/qr-local.js?v=1779198538664"></script>
|
||||
<script type="module" src="src/components/QRScanner.js?v=1779198538664"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="dist/app-boot.js?v=1779043608721"></script>
|
||||
<script type="module" src="dist/app.js?v=1779043608721"></script>
|
||||
<script type="module" src="dist/app-boot.js?v=1779198538664"></script>
|
||||
<script type="module" src="dist/app.js?v=1779198538664"></script>
|
||||
|
||||
<script src="src/scripts/pwa-register.js"></script>
|
||||
<script src="./src/pwa/install-prompt.js" type="module"></script>
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "SecureBit.chat v4.8.6 - ECDH + DTLS + SAS",
|
||||
"name": "SecureBit.chat v4.8.7 - ECDH + DTLS + SAS",
|
||||
"short_name": "SecureBit",
|
||||
"description": "P2P messenger with ECDH + DTLS + SAS security, military-grade cryptography and Lightning Network payments",
|
||||
"start_url": "./",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"version": "1779043608721",
|
||||
"buildVersion": "1779043608721",
|
||||
"appVersion": "4.8.5",
|
||||
"buildTime": "2026-05-17T18:46:48.763Z",
|
||||
"buildId": "1779043608721-4b8c882",
|
||||
"gitHash": "4b8c882",
|
||||
"version": "1779198538664",
|
||||
"buildVersion": "1779198538664",
|
||||
"appVersion": "4.8.7",
|
||||
"buildTime": "2026-05-19T13:48:58.703Z",
|
||||
"buildId": "1779198538664-1cc8732",
|
||||
"gitHash": "1cc8732",
|
||||
"generated": true,
|
||||
"generatedAt": "2026-05-17T18:46:48.764Z"
|
||||
"generatedAt": "2026-05-19T13:48:58.704Z"
|
||||
}
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "securebit-chat",
|
||||
"version": "4.8.6",
|
||||
"version": "4.8.7",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "securebit-chat",
|
||||
"version": "4.8.6",
|
||||
"version": "4.8.7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "1.5.1",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "securebit-chat",
|
||||
"version": "4.8.6",
|
||||
"version": "4.8.7",
|
||||
"description": "Secure P2P Communication Application with End-to-End Encryption",
|
||||
"main": "index.html",
|
||||
"scripts": {
|
||||
|
||||
+1
-1
@@ -2005,7 +2005,7 @@ import { installDebugWindowHooks } from './utils/debugWindowHooks.js';
|
||||
}
|
||||
}
|
||||
|
||||
handleMessage(' SecureBit.chat Enhanced Security Edition v4.8.5 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.', 'system');
|
||||
handleMessage(' SecureBit.chat Enhanced Security Edition v4.8.7 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.', 'system');
|
||||
|
||||
const handleBeforeUnload = (event) => {
|
||||
if (event.type === 'beforeunload' && !isTabSwitching) {
|
||||
|
||||
@@ -257,6 +257,7 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
this.sequenceNumber = 0;
|
||||
this.expectedSequenceNumber = 0;
|
||||
this.sessionSalt = null;
|
||||
this._pendingOfferContext = null;
|
||||
|
||||
// Anti-Replay and Message Ordering Protection
|
||||
this.replayWindowSize = 64; // Sliding window for replay protection
|
||||
@@ -1023,6 +1024,83 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
return summary;
|
||||
}
|
||||
|
||||
_describeIceCandidatesInSDP(sdp) {
|
||||
if (typeof sdp !== 'string') return [];
|
||||
|
||||
return (sdp.match(/^a=candidate:.*$/gm) || []).map((line) => {
|
||||
const parts = line.slice('a=candidate:'.length).trim().split(/\s+/);
|
||||
const typIndex = parts.findIndex(part => part.toLowerCase() === 'typ');
|
||||
const address = parts[4] || '';
|
||||
const port = parts[5] || '';
|
||||
const candidateType = typIndex >= 0 ? parts[typIndex + 1] || 'unknown' : 'unknown';
|
||||
const protocol = (parts[2] || 'unknown').toLowerCase();
|
||||
|
||||
let addressKind = 'unknown';
|
||||
if (/\.local$/i.test(address)) {
|
||||
addressKind = 'mdns';
|
||||
} else if (/^(10\.|192\.168\.|172\.(1[6-9]|2\d|3[0-1])\.)/.test(address)) {
|
||||
addressKind = 'private-ipv4';
|
||||
} else if (/^\d{1,3}(\.\d{1,3}){3}$/.test(address)) {
|
||||
addressKind = 'public-ipv4';
|
||||
} else if (address.includes(':')) {
|
||||
addressKind = 'ipv6';
|
||||
}
|
||||
|
||||
return {
|
||||
candidateType,
|
||||
protocol,
|
||||
addressKind,
|
||||
portPresent: !!port,
|
||||
tcpType: (() => {
|
||||
const tcpIndex = parts.findIndex(part => part.toLowerCase() === 'tcptype');
|
||||
return tcpIndex >= 0 ? parts[tcpIndex + 1] || null : null;
|
||||
})()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
_logIceCandidateDiagnostics(label, sdp, extra = {}) {
|
||||
const candidateSummary = this._summarizeIceCandidatesInSDP(sdp);
|
||||
const candidateDetails = this._describeIceCandidatesInSDP(sdp);
|
||||
console.info(`[SecureBit ICE] ${label}`, {
|
||||
candidateSummary,
|
||||
candidateDetails,
|
||||
candidateDetailsJson: JSON.stringify(candidateDetails),
|
||||
...extra
|
||||
});
|
||||
return { candidateSummary, candidateDetails };
|
||||
}
|
||||
|
||||
_hasOnlyMdnsHostCandidates(sdp) {
|
||||
const summary = this._summarizeIceCandidatesInSDP(sdp);
|
||||
const details = this._describeIceCandidatesInSDP(sdp);
|
||||
|
||||
return summary.total > 0 &&
|
||||
summary.srflx === 0 &&
|
||||
summary.relay === 0 &&
|
||||
summary.prflx === 0 &&
|
||||
details.every(candidate =>
|
||||
candidate.candidateType === 'host' &&
|
||||
candidate.addressKind === 'mdns'
|
||||
);
|
||||
}
|
||||
|
||||
_warnIfRemoteCandidatesNeedRelay(context, sdp) {
|
||||
if (!this._hasOnlyMdnsHostCandidates(sdp)) return false;
|
||||
|
||||
const message = context === 'answer'
|
||||
? 'Connection warning: the response contains only browser-masked mDNS host candidates and no server-reflexive or TURN relay candidates. This network/browser combination may not connect until TURN is configured.'
|
||||
: 'Connection warning: the invitation contains only browser-masked mDNS host candidates and no server-reflexive or TURN relay candidates. This network/browser combination may not connect until TURN is configured.';
|
||||
|
||||
this._secureLog('warn', 'Remote ICE candidates require TURN or usable non-mDNS candidates', {
|
||||
context,
|
||||
candidateSummary: this._summarizeIceCandidatesInSDP(sdp),
|
||||
candidateDetails: this._describeIceCandidatesInSDP(sdp)
|
||||
});
|
||||
this.deliverMessageToUI(message, 'system');
|
||||
return true;
|
||||
}
|
||||
|
||||
async _collectIceFailureDiagnostics() {
|
||||
if (!this.peerConnection?.getStats) return null;
|
||||
|
||||
@@ -1073,6 +1151,50 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
}
|
||||
}
|
||||
|
||||
_storePendingOfferContext() {
|
||||
this._pendingOfferContext = {
|
||||
sessionSalt: Array.isArray(this.sessionSalt) ? [...this.sessionSalt] : null,
|
||||
sessionId: this.sessionId || null,
|
||||
connectionId: this.connectionId || null,
|
||||
keyFingerprint: this.keyFingerprint || null,
|
||||
createdAt: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
_restorePendingOfferContextIfNeeded() {
|
||||
const saltIsValid = Array.isArray(this.sessionSalt) && this.sessionSalt.length === 64;
|
||||
if (saltIsValid) return true;
|
||||
|
||||
const pendingSalt = this._pendingOfferContext?.sessionSalt;
|
||||
if (!Array.isArray(pendingSalt) || pendingSalt.length !== 64) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.sessionSalt = [...pendingSalt];
|
||||
if (!this.sessionId && this._pendingOfferContext.sessionId) {
|
||||
this.sessionId = this._pendingOfferContext.sessionId;
|
||||
}
|
||||
if (!this.connectionId && this._pendingOfferContext.connectionId) {
|
||||
this.connectionId = this._pendingOfferContext.connectionId;
|
||||
}
|
||||
if (!this.keyFingerprint && this._pendingOfferContext.keyFingerprint) {
|
||||
this.keyFingerprint = this._pendingOfferContext.keyFingerprint;
|
||||
}
|
||||
|
||||
this._secureLog('warn', 'Restored pending offer context before applying answer', {
|
||||
pendingContextAgeMs: Date.now() - (this._pendingOfferContext.createdAt || Date.now())
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_clearPendingOfferContext() {
|
||||
if (this._pendingOfferContext?.sessionSalt) {
|
||||
this._secureWipeMemory(this._pendingOfferContext.sessionSalt, 'pendingOfferContext.sessionSalt');
|
||||
}
|
||||
this._pendingOfferContext = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute all maintenance tasks in a single cycle
|
||||
*/
|
||||
@@ -3066,6 +3188,8 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
this._secureWipeMemory(this.connectionId, 'connectionId');
|
||||
this.connectionId = null;
|
||||
}
|
||||
|
||||
this._clearPendingOfferContext();
|
||||
|
||||
this._secureLog('info', '🔒 Cryptographic materials securely cleaned up');
|
||||
|
||||
@@ -7389,6 +7513,33 @@ async processMessage(data) {
|
||||
return config;
|
||||
}
|
||||
|
||||
_summarizeIceServerConfig(iceServers = []) {
|
||||
const summary = {
|
||||
serverCount: 0,
|
||||
stun: 0,
|
||||
turn: 0,
|
||||
turns: 0,
|
||||
hasCredentials: false
|
||||
};
|
||||
|
||||
for (const server of iceServers || []) {
|
||||
summary.serverCount += 1;
|
||||
if (server?.username || server?.credential) {
|
||||
summary.hasCredentials = true;
|
||||
}
|
||||
|
||||
const urls = Array.isArray(server?.urls) ? server.urls : [server?.urls];
|
||||
for (const rawUrl of urls) {
|
||||
const url = String(rawUrl || '').toLowerCase();
|
||||
if (url.startsWith('stun:')) summary.stun += 1;
|
||||
if (url.startsWith('turn:')) summary.turn += 1;
|
||||
if (url.startsWith('turns:')) summary.turns += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
_isRelayOnlyMode() {
|
||||
return this._config.webrtc.privacyMode === 'relay-only';
|
||||
}
|
||||
@@ -7423,6 +7574,7 @@ async processMessage(data) {
|
||||
this._sessionAlive = true;
|
||||
const config = this._buildPeerConnectionConfig();
|
||||
this._warnIfTurnMissing();
|
||||
console.info('[SecureBit ICE] peer connection config', this._summarizeIceServerConfig(config.iceServers));
|
||||
|
||||
this.peerConnection = new RTCPeerConnection(config);
|
||||
|
||||
@@ -9679,8 +9831,7 @@ async processMessage(data) {
|
||||
iceGatheringDurationMs: Date.now() - offerIceGatheringStartedAt,
|
||||
iceGatheringCompleted: offerIceGatheringCompleted
|
||||
});
|
||||
console.info('[SecureBit ICE] offer export', {
|
||||
candidateSummary: offerCandidateSummary,
|
||||
this._logIceCandidateDiagnostics('offer export', this.peerConnection.localDescription?.sdp, {
|
||||
iceGatheringState: this.peerConnection.iceGatheringState,
|
||||
iceGatheringDurationMs: Date.now() - offerIceGatheringStartedAt,
|
||||
iceGatheringCompleted: offerIceGatheringCompleted
|
||||
@@ -9736,6 +9887,7 @@ async processMessage(data) {
|
||||
// Generate connection ID for AAD
|
||||
this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8)))
|
||||
.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
this._storePendingOfferContext();
|
||||
|
||||
// ============================================
|
||||
// PHASE 11: SECURITY LEVEL CALCULATION
|
||||
@@ -10322,10 +10474,10 @@ async processMessage(data) {
|
||||
type: 'offer',
|
||||
sdp: offerData.s || offerData.sdp
|
||||
}));
|
||||
console.info('[SecureBit ICE] remote offer applied', {
|
||||
candidateSummary: this._summarizeIceCandidatesInSDP(this.peerConnection.remoteDescription?.sdp),
|
||||
this._logIceCandidateDiagnostics('remote offer applied', this.peerConnection.remoteDescription?.sdp, {
|
||||
signalingState: this.peerConnection.signalingState
|
||||
});
|
||||
this._warnIfRemoteCandidatesNeedRelay('offer', this.peerConnection.remoteDescription?.sdp);
|
||||
|
||||
this._secureLog('debug', 'Remote description set successfully', {
|
||||
operationId: operationId,
|
||||
@@ -10418,8 +10570,7 @@ async processMessage(data) {
|
||||
iceGatheringDurationMs: Date.now() - answerIceGatheringStartedAt,
|
||||
iceGatheringCompleted: answerIceGatheringCompleted
|
||||
});
|
||||
console.info('[SecureBit ICE] answer export', {
|
||||
candidateSummary: answerCandidateSummary,
|
||||
this._logIceCandidateDiagnostics('answer export', this.peerConnection.localDescription?.sdp, {
|
||||
iceGatheringState: this.peerConnection.iceGatheringState,
|
||||
iceGatheringDurationMs: Date.now() - answerIceGatheringStartedAt,
|
||||
iceGatheringCompleted: answerIceGatheringCompleted
|
||||
@@ -10676,6 +10827,7 @@ async processMessage(data) {
|
||||
_cleanupFailedAnswerCreation() {
|
||||
try {
|
||||
// Secure wipe of cryptographic materials
|
||||
this._clearPendingOfferContext();
|
||||
this._secureCleanupCryptographicMaterials();
|
||||
|
||||
// Secure wipe of PFS key versions
|
||||
@@ -10930,11 +11082,12 @@ async processMessage(data) {
|
||||
);
|
||||
|
||||
// Additional MITM protection: Verify session salt integrity
|
||||
this._restorePendingOfferContextIfNeeded();
|
||||
if (!this.sessionSalt || this.sessionSalt.length !== 64) {
|
||||
window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Invalid session salt detected - possible session hijacking', {
|
||||
saltLength: this.sessionSalt ? this.sessionSalt.length : 0
|
||||
});
|
||||
throw new Error('Invalid session salt – possible session hijacking attempt');
|
||||
throw new Error('Missing pending offer context. Apply the response in the original creator window that generated the invitation.');
|
||||
}
|
||||
|
||||
// Verify that the session salt hasn't been tampered with
|
||||
@@ -11101,10 +11254,10 @@ async processMessage(data) {
|
||||
type: 'answer',
|
||||
sdp: sdpData
|
||||
});
|
||||
console.info('[SecureBit ICE] remote answer applied', {
|
||||
candidateSummary: this._summarizeIceCandidatesInSDP(this.peerConnection.remoteDescription?.sdp),
|
||||
this._logIceCandidateDiagnostics('remote answer applied', this.peerConnection.remoteDescription?.sdp, {
|
||||
signalingState: this.peerConnection.signalingState
|
||||
});
|
||||
this._warnIfRemoteCandidatesNeedRelay('answer', this.peerConnection.remoteDescription?.sdp);
|
||||
|
||||
this._secureLog('debug', 'Remote description set successfully from answer', {
|
||||
signalingState: this.peerConnection.signalingState
|
||||
|
||||
@@ -333,6 +333,105 @@ function createVerificationReadinessManager({
|
||||
);
|
||||
}
|
||||
|
||||
// ICE candidate details are redacted but still expose routing-relevant classes.
|
||||
{
|
||||
const sdp = [
|
||||
'v=0',
|
||||
'a=candidate:1 1 UDP 2122252543 192.168.1.2 54400 typ host',
|
||||
'a=candidate:2 1 UDP 1686052607 203.0.113.10 40000 typ srflx',
|
||||
'a=candidate:3 1 TCP 1518280447 abcdef.local 9 typ host tcptype passive'
|
||||
].join('\r\n');
|
||||
|
||||
assert.deepEqual(
|
||||
EnhancedSecureWebRTCManager.prototype._describeIceCandidatesInSDP.call(createSASManager(), sdp),
|
||||
[
|
||||
{ candidateType: 'host', protocol: 'udp', addressKind: 'private-ipv4', portPresent: true, tcpType: null },
|
||||
{ candidateType: 'srflx', protocol: 'udp', addressKind: 'public-ipv4', portPresent: true, tcpType: null },
|
||||
{ candidateType: 'host', protocol: 'tcp', addressKind: 'mdns', portPresent: true, tcpType: 'passive' }
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// ICE diagnostics include a copyable JSON string so browser logs do not hide
|
||||
// candidate details behind collapsed DevTools objects.
|
||||
{
|
||||
const logs = [];
|
||||
const originalConsoleInfo = console.info;
|
||||
console.info = (...args) => logs.push(args);
|
||||
try {
|
||||
const manager = {
|
||||
_summarizeIceCandidatesInSDP: EnhancedSecureWebRTCManager.prototype._summarizeIceCandidatesInSDP,
|
||||
_describeIceCandidatesInSDP: EnhancedSecureWebRTCManager.prototype._describeIceCandidatesInSDP,
|
||||
_logIceCandidateDiagnostics: EnhancedSecureWebRTCManager.prototype._logIceCandidateDiagnostics
|
||||
};
|
||||
manager._logIceCandidateDiagnostics('test candidates', 'a=candidate:1 1 UDP 1 192.168.1.2 5000 typ host', {
|
||||
signalingState: 'stable'
|
||||
});
|
||||
|
||||
assert.equal(logs[0][0], '[SecureBit ICE] test candidates');
|
||||
assert.equal(typeof logs[0][1].candidateDetailsJson, 'string');
|
||||
assert.match(logs[0][1].candidateDetailsJson, /private-ipv4/);
|
||||
assert.equal(logs[0][1].signalingState, 'stable');
|
||||
} finally {
|
||||
console.info = originalConsoleInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// Remote mDNS-only candidates are surfaced as a user-visible TURN warning.
|
||||
{
|
||||
const messages = [];
|
||||
const manager = {
|
||||
_secureLog() {},
|
||||
deliverMessageToUI(message, type) {
|
||||
messages.push({ message, type });
|
||||
},
|
||||
_summarizeIceCandidatesInSDP: EnhancedSecureWebRTCManager.prototype._summarizeIceCandidatesInSDP,
|
||||
_describeIceCandidatesInSDP: EnhancedSecureWebRTCManager.prototype._describeIceCandidatesInSDP,
|
||||
_hasOnlyMdnsHostCandidates: EnhancedSecureWebRTCManager.prototype._hasOnlyMdnsHostCandidates,
|
||||
_warnIfRemoteCandidatesNeedRelay: EnhancedSecureWebRTCManager.prototype._warnIfRemoteCandidatesNeedRelay
|
||||
};
|
||||
const mdnsOnlySdp = 'a=candidate:1 1 UDP 1 abcdef.local 5000 typ host';
|
||||
const srflxSdp = 'a=candidate:1 1 UDP 1 203.0.113.10 5000 typ srflx';
|
||||
|
||||
assert.equal(manager._hasOnlyMdnsHostCandidates(mdnsOnlySdp), true);
|
||||
assert.equal(manager._warnIfRemoteCandidatesNeedRelay('answer', mdnsOnlySdp), true);
|
||||
assert.equal(messages[0].type, 'system');
|
||||
assert.match(messages[0].message, /TURN is configured/i);
|
||||
assert.equal(manager._hasOnlyMdnsHostCandidates(srflxSdp), false);
|
||||
}
|
||||
|
||||
// Pending offer context preserves the creator's manual-exchange salt until the
|
||||
// answer is applied, even if transient ICE/UI state temporarily loses it.
|
||||
{
|
||||
const manager = {
|
||||
sessionSalt: Array.from({ length: 64 }, (_, index) => index),
|
||||
sessionId: 'session-a',
|
||||
connectionId: 'connection-a',
|
||||
keyFingerprint: 'AA:BB',
|
||||
_secureLog() {},
|
||||
_secureWipeMemory() {},
|
||||
_storePendingOfferContext: EnhancedSecureWebRTCManager.prototype._storePendingOfferContext,
|
||||
_restorePendingOfferContextIfNeeded: EnhancedSecureWebRTCManager.prototype._restorePendingOfferContextIfNeeded,
|
||||
_clearPendingOfferContext: EnhancedSecureWebRTCManager.prototype._clearPendingOfferContext
|
||||
};
|
||||
|
||||
manager._storePendingOfferContext();
|
||||
manager.sessionSalt = null;
|
||||
manager.sessionId = null;
|
||||
manager.connectionId = null;
|
||||
manager.keyFingerprint = null;
|
||||
|
||||
assert.equal(manager._restorePendingOfferContextIfNeeded(), true);
|
||||
assert.equal(manager.sessionSalt.length, 64);
|
||||
assert.equal(manager.sessionId, 'session-a');
|
||||
assert.equal(manager.connectionId, 'connection-a');
|
||||
assert.equal(manager.keyFingerprint, 'AA:BB');
|
||||
|
||||
manager._clearPendingOfferContext();
|
||||
manager.sessionSalt = null;
|
||||
assert.equal(manager._restorePendingOfferContextIfNeeded(), false);
|
||||
}
|
||||
|
||||
// Joining with an offer and generating an answer does not open verification
|
||||
// before the answer has been applied by the creator and the channel opens.
|
||||
{
|
||||
|
||||
@@ -112,4 +112,30 @@ function fake(config = {}) {
|
||||
assert.equal(config.iceServers, overrideServers);
|
||||
}
|
||||
|
||||
// ICE config diagnostics reveal whether TURN credentials were loaded without
|
||||
// printing sensitive usernames or passwords.
|
||||
{
|
||||
const manager = fake({
|
||||
iceServers: [
|
||||
{ urls: 'stun:stun.example.test:3478' },
|
||||
{
|
||||
urls: ['turn:turn.example.test:3478?transport=udp', 'turns:turn.example.test:443?transport=tcp'],
|
||||
username: 'user',
|
||||
credential: 'secret'
|
||||
}
|
||||
]
|
||||
});
|
||||
const summary = EnhancedSecureWebRTCManager.prototype._summarizeIceServerConfig.call(
|
||||
manager,
|
||||
manager._config.webrtc.iceServers
|
||||
);
|
||||
assert.deepEqual(summary, {
|
||||
serverCount: 2,
|
||||
stun: 1,
|
||||
turn: 1,
|
||||
turns: 1,
|
||||
hasCredentials: true
|
||||
});
|
||||
}
|
||||
|
||||
console.log('WebRTC privacy mode tests passed');
|
||||
Reference in new issue
Block a user