diff --git a/README.md b/README.md index 66465926dd..254a66c2bc 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,8 @@ You can use SimpleX with your own servers and still communicate with people usin Recent and important updates: +[Nov 25, 2023. SimpleX Chat v5.4 released: link mobile and desktop apps via quantum resistant protocol, and much better groups](./blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md). + [Sep 25, 2023. SimpleX Chat v5.3 released: desktop app, local file encryption, improved groups and directory service](./blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md). [Jul 22, 2023. SimpleX Chat: v5.2 released with message delivery receipts](./blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md). @@ -366,13 +368,13 @@ Please also join [#simplex-devs](https://simplex.chat/contact#/?v=1-2&smp=smp%3A - ✅ Message delivery confirmation (with sender opt-out per contact). - ✅ Desktop client. - ✅ Encryption of local files stored in the app. -- 🏗 Using mobile profiles from the desktop app. +- ✅ Using mobile profiles from the desktop app. +- 🏗 Improve experience for the new users. +- 🏗 Post-quantum resistant key exchange in double ratchet protocol. +- 🏗 Large groups, communities and public channels. - Message delivery relay for senders (to conceal IP address from the recipients' servers and to reduce the traffic). -- Post-quantum resistant key exchange in double ratchet protocol. -- Large groups, communities and public channels. - Privacy & security slider - a simple way to set all settings at once. - Improve sending videos (including encryption of locally stored videos). -- Improve experience for the new users. - SMP queue redundancy and rotation (manual is supported). - Include optional message into connection request sent via contact address. - Improved navigation and search in the conversation (expand and scroll to quoted message, scroll to search results, etc.). diff --git a/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift b/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift index 1f120860e2..e934bbc89a 100644 --- a/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift +++ b/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift @@ -208,7 +208,7 @@ struct ConnectDesktopView: View { Section("Found desktop") { Text("Waiting for desktop...").italic() Button { - disconnectDesktop(.dismiss) + disconnectDesktop() } label: { Label("Scan QR code", systemImage: "qrcode") } diff --git a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff index 29f5dd4e3f..75f70f7ad1 100644 --- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff +++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff @@ -1196,6 +1196,7 @@ Connect automatically + Automatisch verbinden No comment provided by engineer. @@ -1914,6 +1915,7 @@ Das kann nicht rückgängig gemacht werden! Discover via local network + Lokales Netzwerk durchsuchen No comment provided by engineer. @@ -2558,6 +2560,7 @@ Das kann nicht rückgängig gemacht werden! Found desktop + Gefundener Desktop No comment provided by engineer. @@ -3527,6 +3530,7 @@ Das ist Ihr Link für die Gruppe %@! Not compatible! + Nicht kompatibel! No comment provided by engineer. @@ -5501,6 +5505,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Waiting for desktop... + Es wird auf den Desktop gewartet... No comment provided by engineer. @@ -6050,6 +6055,7 @@ SimpleX-Server können Ihr Profil nicht einsehen. author + Autor member role diff --git a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff index af54b7ceb9..153d98be3c 100644 --- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff +++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff @@ -1196,6 +1196,7 @@ Connect automatically + Connexion automatique No comment provided by engineer. @@ -1914,6 +1915,7 @@ Cette opération ne peut être annulée ! Discover via local network + Rechercher sur le réseau No comment provided by engineer. @@ -2558,6 +2560,7 @@ Cette opération ne peut être annulée ! Found desktop + Bureau trouvé No comment provided by engineer. @@ -3527,6 +3530,7 @@ Voici votre lien pour le groupe %@ ! Not compatible! + Non compatible ! No comment provided by engineer. @@ -5501,6 +5505,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Waiting for desktop... + En attente du bureau... No comment provided by engineer. @@ -6050,6 +6055,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. author + auteur member role diff --git a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff index d2be34ec6c..094a30677a 100644 --- a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff +++ b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff @@ -1196,6 +1196,7 @@ Connect automatically + Automatisch verbinden No comment provided by engineer. @@ -1914,6 +1915,7 @@ Dit kan niet ongedaan gemaakt worden! Discover via local network + Ontdek via het lokale netwerk No comment provided by engineer. @@ -2558,6 +2560,7 @@ Dit kan niet ongedaan gemaakt worden! Found desktop + Desktop gevonden No comment provided by engineer. @@ -3527,6 +3530,7 @@ Dit is jouw link voor groep %@! Not compatible! + Niet compatibel! No comment provided by engineer. @@ -5501,6 +5505,7 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Waiting for desktop... + Wachten op desktop... No comment provided by engineer. @@ -6050,6 +6055,7 @@ SimpleX servers kunnen uw profiel niet zien. author + auteur member role diff --git a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff index 61147d7f98..ad1924f4c4 100644 --- a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff +++ b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff @@ -299,10 +299,12 @@ (new) + (nowy) No comment provided by engineer. (this device v%@) + (to urządzenie v%@) No comment provided by engineer. @@ -397,6 +399,9 @@ - optionally notify deleted contacts. - profile names with spaces. - and more! + - opcjonalnie powiadamiaj usunięte kontakty. +- nazwy profili ze spacją. +- i wiele więcej! No comment provided by engineer. @@ -885,6 +890,7 @@ Bad desktop address + Zły adres komputera No comment provided by engineer. @@ -899,6 +905,7 @@ Better groups + Lepsze grupy No comment provided by engineer. @@ -913,6 +920,7 @@ Block group members + Blokuj członków grupy No comment provided by engineer. @@ -1188,6 +1196,7 @@ Connect automatically + Łącz automatycznie No comment provided by engineer. @@ -1197,6 +1206,7 @@ Connect to desktop + Połącz do komputera No comment provided by engineer. @@ -1245,10 +1255,12 @@ To jest twój jednorazowy link! Connected desktop + Połączony komputer No comment provided by engineer. Connected to desktop + Połączony do komputera No comment provided by engineer. @@ -1263,6 +1275,7 @@ To jest twój jednorazowy link! Connecting to desktop + Łączenie z komputerem No comment provided by engineer. @@ -1287,6 +1300,7 @@ To jest twój jednorazowy link! Connection terminated + Połączenie zakończone No comment provided by engineer. @@ -1371,6 +1385,7 @@ To jest twój jednorazowy link! Create a group using a random profile. + Utwórz grupę używając losowego profilu. No comment provided by engineer. @@ -1785,14 +1800,17 @@ To nie może być cofnięte! Desktop address + Adres komputera No comment provided by engineer. Desktop app version %@ is not compatible with this app. + Wersja aplikacji komputerowej %@ nie jest kompatybilna z tą aplikacją. No comment provided by engineer. Desktop devices + Urządzenia komputerowe No comment provided by engineer. @@ -1887,6 +1905,7 @@ To nie może być cofnięte! Disconnect desktop? + Rozłączyć komputer? No comment provided by engineer. @@ -1896,6 +1915,7 @@ To nie może być cofnięte! Discover via local network + Odkryj przez sieć lokalną No comment provided by engineer. @@ -2070,10 +2090,12 @@ To nie może być cofnięte! Encryption re-negotiation error + Błąd renegocjacji szyfrowania message decrypt error item Encryption re-negotiation failed. + Renegocjacja szyfrowania nie powiodła się. No comment provided by engineer. @@ -2108,6 +2130,7 @@ To nie może być cofnięte! Enter this device name… + Podaj nazwę urządzenia… No comment provided by engineer. @@ -2437,6 +2460,7 @@ To nie może być cofnięte! Faster joining and more reliable messages. + Szybsze dołączenie i bardziej niezawodne wiadomości. No comment provided by engineer. @@ -2536,6 +2560,7 @@ To nie może być cofnięte! Found desktop + Znaleziono komputer No comment provided by engineer. @@ -2865,6 +2890,7 @@ To nie może być cofnięte! Incognito groups + Grupy incognito No comment provided by engineer. @@ -2899,6 +2925,7 @@ To nie może być cofnięte! Incompatible version + Niekompatybilna wersja No comment provided by engineer. @@ -3073,6 +3100,7 @@ To jest twój link do grupy %@! Keep the app open to use it from desktop + Zostaw aplikację otwartą i używaj ją z komputera No comment provided by engineer. @@ -3137,14 +3165,17 @@ To jest twój link do grupy %@! Link mobile and desktop apps! 🔗 + Połącz mobile i komputerowe aplikacje! 🔗 No comment provided by engineer. Linked desktop options + Połączone opcje komputera No comment provided by engineer. Linked desktops + Połączone komputery No comment provided by engineer. @@ -3499,6 +3530,7 @@ To jest twój link do grupy %@! Not compatible! + Nie kompatybilny! No comment provided by engineer. @@ -3722,6 +3754,7 @@ To jest twój link do grupy %@! Paste desktop address + Wklej adres komputera No comment provided by engineer. @@ -4321,6 +4354,7 @@ To jest twój link do grupy %@! Scan QR code from desktop + Zeskanuj kod QR z komputera No comment provided by engineer. @@ -4545,6 +4579,7 @@ To jest twój link do grupy %@! Session code + Kod sesji No comment provided by engineer. @@ -5046,6 +5081,7 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom This device name + Nazwa tego urządzenia No comment provided by engineer. @@ -5085,6 +5121,7 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom To hide unwanted messages. + Aby ukryć niechciane wiadomości. No comment provided by engineer. @@ -5248,10 +5285,12 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Unlink + Odłącz No comment provided by engineer. Unlink desktop? + Odłączyć komputer? No comment provided by engineer. @@ -5346,6 +5385,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Use from desktop + Użyj z komputera No comment provided by engineer. @@ -5380,10 +5420,12 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Verify code with desktop + Zweryfikuj kod z komputera No comment provided by engineer. Verify connection + Zweryfikuj połączenie No comment provided by engineer. @@ -5393,6 +5435,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Verify connections + Zweryfikuj połączenia No comment provided by engineer. @@ -5407,6 +5450,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Via secure quantum resistant protocol. + Dzięki bezpiecznemu protokołowi odpornego kwantowo. No comment provided by engineer. @@ -5461,6 +5505,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Waiting for desktop... + Oczekiwanie na komputer... No comment provided by engineer. @@ -6010,6 +6055,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. author + autor member role @@ -6596,6 +6642,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. v%@ + v%@ No comment provided by engineer. @@ -6737,6 +6784,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. SimpleX uses local network access to allow using user chat profile via desktop app on the same network. + SimpleX używa sieci lokalnej aby pozwolić na dostęp profilom czatu użytkownika przez aplikację komputerową na tej samej sieci. Privacy - Local Network Usage Description diff --git a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff index abd3d01d87..f4970446ae 100644 --- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff +++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff @@ -1196,6 +1196,7 @@ Connect automatically + Соединяться автоматически No comment provided by engineer. @@ -1914,6 +1915,7 @@ This cannot be undone! Discover via local network + Обнаружение по локальной сети No comment provided by engineer. @@ -2558,6 +2560,7 @@ This cannot be undone! Found desktop + Компьютер найден No comment provided by engineer. @@ -3527,6 +3530,7 @@ This is your link for group %@! Not compatible! + Несовместимая версия! No comment provided by engineer. @@ -5501,6 +5505,7 @@ To connect, please ask your contact to create another connection link and check Waiting for desktop... + Ожидается подключение компьютера... No comment provided by engineer. @@ -6050,6 +6055,7 @@ SimpleX серверы не могут получить доступ к Ваше author + автор member role diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 47769ac2db..8612370b00 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -120,6 +120,11 @@ 5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */; }; 5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD67B8D2B0E858A00C510B1 /* hs_init.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5CD67B902B0E858A00C510B1 /* hs_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 5CD67B8E2B0E858A00C510B1 /* hs_init.c */; }; + 5CD67BA02B120ADF00C510B1 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CD67B9B2B120ADF00C510B1 /* libgmp.a */; }; + 5CD67BA12B120ADF00C510B1 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CD67B9C2B120ADF00C510B1 /* libgmpxx.a */; }; + 5CD67BA22B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CD67B9D2B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u.a */; }; + 5CD67BA32B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CD67B9E2B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u-ghc8.10.7.a */; }; + 5CD67BA42B120ADF00C510B1 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CD67B9F2B120ADF00C510B1 /* libffi.a */; }; 5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; }; 5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; }; 5CE2BA712845308900EC33A6 /* SimpleXChat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -145,11 +150,6 @@ 5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */; }; 5CEBD7462A5C0A8F00665FE2 /* KeyboardPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */; }; 5CEBD7482A5F115D00665FE2 /* SetDeliveryReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */; }; - 5CF077FB2B0D60C100105111 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF077F62B0D60C000105111 /* libgmpxx.a */; }; - 5CF077FC2B0D60C100105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF077F72B0D60C000105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2.a */; }; - 5CF077FD2B0D60C100105111 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF077F82B0D60C000105111 /* libgmp.a */; }; - 5CF077FE2B0D60C100105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF077F92B0D60C100105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2-ghc9.6.3.a */; }; - 5CF077FF2B0D60C100105111 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF077FA2B0D60C100105111 /* libffi.a */; }; 5CFA59C42860BC6200863A68 /* MigrateToAppGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */; }; 5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */; }; 5CFE0921282EEAF60002594B /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */; }; @@ -408,6 +408,11 @@ 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanToConnectView.swift; sourceTree = ""; }; 5CD67B8D2B0E858A00C510B1 /* hs_init.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hs_init.h; sourceTree = ""; }; 5CD67B8E2B0E858A00C510B1 /* hs_init.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hs_init.c; sourceTree = ""; }; + 5CD67B9B2B120ADF00C510B1 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; + 5CD67B9C2B120ADF00C510B1 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; + 5CD67B9D2B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u.a"; sourceTree = ""; }; + 5CD67B9E2B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u-ghc8.10.7.a"; sourceTree = ""; }; + 5CD67B9F2B120ADF00C510B1 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; 5CDCAD452818589900503DA2 /* SimpleX NSE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX NSE.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 5CDCAD472818589900503DA2 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; 5CDCAD492818589900503DA2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -434,11 +439,6 @@ 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MsgContentView.swift; sourceTree = ""; }; 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardPadding.swift; sourceTree = ""; }; 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetDeliveryReceiptsView.swift; sourceTree = ""; }; - 5CF077F62B0D60C000105111 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; - 5CF077F72B0D60C000105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2.a"; sourceTree = ""; }; - 5CF077F82B0D60C000105111 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; - 5CF077F92B0D60C100105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2-ghc9.6.3.a"; sourceTree = ""; }; - 5CF077FA2B0D60C100105111 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrateToAppGroupView.swift; sourceTree = ""; }; 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatArchiveView.swift; sourceTree = ""; }; 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ZoomableScrollView.swift; path = Shared/Views/ZoomableScrollView.swift; sourceTree = SOURCE_ROOT; }; @@ -521,12 +521,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5CF077FB2B0D60C100105111 /* libgmpxx.a in Frameworks */, - 5CF077FD2B0D60C100105111 /* libgmp.a in Frameworks */, - 5CF077FE2B0D60C100105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2-ghc9.6.3.a in Frameworks */, + 5CD67BA12B120ADF00C510B1 /* libgmpxx.a in Frameworks */, + 5CD67BA22B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, - 5CF077FF2B0D60C100105111 /* libffi.a in Frameworks */, - 5CF077FC2B0D60C100105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2.a in Frameworks */, + 5CD67BA02B120ADF00C510B1 /* libgmp.a in Frameworks */, + 5CD67BA42B120ADF00C510B1 /* libffi.a in Frameworks */, + 5CD67BA32B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u-ghc8.10.7.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -589,11 +589,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - 5CF077FA2B0D60C100105111 /* libffi.a */, - 5CF077F82B0D60C000105111 /* libgmp.a */, - 5CF077F62B0D60C000105111 /* libgmpxx.a */, - 5CF077F92B0D60C100105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2-ghc9.6.3.a */, - 5CF077F72B0D60C000105111 /* libHSsimplex-chat-5.4.0.5-AEaxUB19STC3bOtqr9BLL2.a */, + 5CD67B9F2B120ADF00C510B1 /* libffi.a */, + 5CD67B9B2B120ADF00C510B1 /* libgmp.a */, + 5CD67B9C2B120ADF00C510B1 /* libgmpxx.a */, + 5CD67B9E2B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u-ghc8.10.7.a */, + 5CD67B9D2B120ADF00C510B1 /* libHSsimplex-chat-5.4.0.6-9DfazyElTA72omjHp0C93u.a */, ); path = Libraries; sourceTree = ""; @@ -1512,7 +1512,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 182; + CURRENT_PROJECT_VERSION = 184; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_PREVIEWS = YES; @@ -1555,7 +1555,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 182; + CURRENT_PROJECT_VERSION = 184; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_PREVIEWS = YES; @@ -1636,7 +1636,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 182; + CURRENT_PROJECT_VERSION = 184; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GENERATE_INFOPLIST_FILE = YES; @@ -1668,7 +1668,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 182; + CURRENT_PROJECT_VERSION = 184; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GENERATE_INFOPLIST_FILE = YES; @@ -1700,7 +1700,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 182; + CURRENT_PROJECT_VERSION = 184; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1746,7 +1746,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 182; + CURRENT_PROJECT_VERSION = 184; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; diff --git a/apps/ios/de.lproj/Localizable.strings b/apps/ios/de.lproj/Localizable.strings index c860a24998..febd4c06a5 100644 --- a/apps/ios/de.lproj/Localizable.strings +++ b/apps/ios/de.lproj/Localizable.strings @@ -545,6 +545,9 @@ /* No comment provided by engineer. */ "Authentication unavailable" = "Authentifizierung nicht verfügbar"; +/* member role */ +"author" = "Autor"; + /* No comment provided by engineer. */ "Auto-accept" = "Automatisch akzeptieren"; @@ -786,6 +789,9 @@ /* server test step */ "Connect" = "Verbinden"; +/* No comment provided by engineer. */ +"Connect automatically" = "Automatisch verbinden"; + /* No comment provided by engineer. */ "Connect incognito" = "Inkognito verbinden"; @@ -1287,6 +1293,9 @@ /* No comment provided by engineer. */ "Discover and join groups" = "Gruppen entdecken und ihnen beitreten"; +/* No comment provided by engineer. */ +"Discover via local network" = "Lokales Netzwerk durchsuchen"; + /* No comment provided by engineer. */ "Do it later" = "Später wiederholen"; @@ -1722,6 +1731,9 @@ /* No comment provided by engineer. */ "For console" = "Für Konsole"; +/* No comment provided by engineer. */ +"Found desktop" = "Gefundener Desktop"; + /* No comment provided by engineer. */ "French interface" = "Französische Bedienoberfläche"; @@ -2397,6 +2409,9 @@ /* copied message info in history */ "no text" = "Kein Text"; +/* No comment provided by engineer. */ +"Not compatible!" = "Nicht kompatibel!"; + /* No comment provided by engineer. */ "Notifications" = "Benachrichtigungen"; @@ -3671,6 +3686,9 @@ /* No comment provided by engineer. */ "waiting for confirmation…" = "Warten auf Bestätigung…"; +/* No comment provided by engineer. */ +"Waiting for desktop..." = "Es wird auf den Desktop gewartet..."; + /* No comment provided by engineer. */ "Waiting for file" = "Warte auf Datei"; diff --git a/apps/ios/fr.lproj/Localizable.strings b/apps/ios/fr.lproj/Localizable.strings index b71d510e72..470e23b4fc 100644 --- a/apps/ios/fr.lproj/Localizable.strings +++ b/apps/ios/fr.lproj/Localizable.strings @@ -545,6 +545,9 @@ /* No comment provided by engineer. */ "Authentication unavailable" = "Authentification indisponible"; +/* member role */ +"author" = "auteur"; + /* No comment provided by engineer. */ "Auto-accept" = "Auto-accepter"; @@ -786,6 +789,9 @@ /* server test step */ "Connect" = "Se connecter"; +/* No comment provided by engineer. */ +"Connect automatically" = "Connexion automatique"; + /* No comment provided by engineer. */ "Connect incognito" = "Se connecter incognito"; @@ -1287,6 +1293,9 @@ /* No comment provided by engineer. */ "Discover and join groups" = "Découvrir et rejoindre des groupes"; +/* No comment provided by engineer. */ +"Discover via local network" = "Rechercher sur le réseau"; + /* No comment provided by engineer. */ "Do it later" = "Faites-le plus tard"; @@ -1722,6 +1731,9 @@ /* No comment provided by engineer. */ "For console" = "Pour la console"; +/* No comment provided by engineer. */ +"Found desktop" = "Bureau trouvé"; + /* No comment provided by engineer. */ "French interface" = "Interface en français"; @@ -2397,6 +2409,9 @@ /* copied message info in history */ "no text" = "aucun texte"; +/* No comment provided by engineer. */ +"Not compatible!" = "Non compatible !"; + /* No comment provided by engineer. */ "Notifications" = "Notifications"; @@ -3671,6 +3686,9 @@ /* No comment provided by engineer. */ "waiting for confirmation…" = "en attente de confirmation…"; +/* No comment provided by engineer. */ +"Waiting for desktop..." = "En attente du bureau..."; + /* No comment provided by engineer. */ "Waiting for file" = "En attente du fichier"; diff --git a/apps/ios/nl.lproj/Localizable.strings b/apps/ios/nl.lproj/Localizable.strings index ac1f8b03d3..784acf1a9b 100644 --- a/apps/ios/nl.lproj/Localizable.strings +++ b/apps/ios/nl.lproj/Localizable.strings @@ -545,6 +545,9 @@ /* No comment provided by engineer. */ "Authentication unavailable" = "Verificatie niet beschikbaar"; +/* member role */ +"author" = "auteur"; + /* No comment provided by engineer. */ "Auto-accept" = "Automatisch accepteren"; @@ -786,6 +789,9 @@ /* server test step */ "Connect" = "Verbind"; +/* No comment provided by engineer. */ +"Connect automatically" = "Automatisch verbinden"; + /* No comment provided by engineer. */ "Connect incognito" = "Verbind incognito"; @@ -1287,6 +1293,9 @@ /* No comment provided by engineer. */ "Discover and join groups" = "Ontdek en sluit je aan bij groepen"; +/* No comment provided by engineer. */ +"Discover via local network" = "Ontdek via het lokale netwerk"; + /* No comment provided by engineer. */ "Do it later" = "Doe het later"; @@ -1722,6 +1731,9 @@ /* No comment provided by engineer. */ "For console" = "Voor console"; +/* No comment provided by engineer. */ +"Found desktop" = "Desktop gevonden"; + /* No comment provided by engineer. */ "French interface" = "Franse interface"; @@ -2397,6 +2409,9 @@ /* copied message info in history */ "no text" = "geen tekst"; +/* No comment provided by engineer. */ +"Not compatible!" = "Niet compatibel!"; + /* No comment provided by engineer. */ "Notifications" = "Meldingen"; @@ -3671,6 +3686,9 @@ /* No comment provided by engineer. */ "waiting for confirmation…" = "Wachten op bevestiging…"; +/* No comment provided by engineer. */ +"Waiting for desktop..." = "Wachten op desktop..."; + /* No comment provided by engineer. */ "Waiting for file" = "Wachten op bestand"; diff --git a/apps/ios/pl.lproj/Localizable.strings b/apps/ios/pl.lproj/Localizable.strings index 3eb86d2a12..e0f4c4dee0 100644 --- a/apps/ios/pl.lproj/Localizable.strings +++ b/apps/ios/pl.lproj/Localizable.strings @@ -25,6 +25,9 @@ /* No comment provided by engineer. */ "- more stable message delivery.\n- a bit better groups.\n- and more!" = "- bardziej stabilne dostarczanie wiadomości.\n- nieco lepsze grupy.\n- i więcej!"; +/* No comment provided by engineer. */ +"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- opcjonalnie powiadamiaj usunięte kontakty.\n- nazwy profili ze spacją.\n- i wiele więcej!"; + /* No comment provided by engineer. */ "- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- wiadomości głosowe do 5 minut.\n- niestandardowy czas zniknięcia.\n- historia edycji."; @@ -43,6 +46,12 @@ /* No comment provided by engineer. */ "(" = "("; +/* No comment provided by engineer. */ +"(new)" = "(nowy)"; + +/* No comment provided by engineer. */ +"(this device v%@)" = "(to urządzenie v%@)"; + /* No comment provided by engineer. */ ")" = ")"; @@ -536,6 +545,9 @@ /* No comment provided by engineer. */ "Authentication unavailable" = "Uwierzytelnianie niedostępne"; +/* member role */ +"author" = "autor"; + /* No comment provided by engineer. */ "Auto-accept" = "Automatycznie akceptuj"; @@ -548,6 +560,9 @@ /* No comment provided by engineer. */ "Back" = "Wstecz"; +/* No comment provided by engineer. */ +"Bad desktop address" = "Zły adres komputera"; + /* integrity error chat item */ "bad message hash" = "zły hash wiadomości"; @@ -560,12 +575,18 @@ /* No comment provided by engineer. */ "Bad message ID" = "Zły identyfikator wiadomości"; +/* No comment provided by engineer. */ +"Better groups" = "Lepsze grupy"; + /* No comment provided by engineer. */ "Better messages" = "Lepsze wiadomości"; /* No comment provided by engineer. */ "Block" = "Zablokuj"; +/* No comment provided by engineer. */ +"Block group members" = "Blokuj członków grupy"; + /* No comment provided by engineer. */ "Block member" = "Zablokuj członka"; @@ -768,9 +789,15 @@ /* server test step */ "Connect" = "Połącz"; +/* No comment provided by engineer. */ +"Connect automatically" = "Łącz automatycznie"; + /* No comment provided by engineer. */ "Connect incognito" = "Połącz incognito"; +/* No comment provided by engineer. */ +"Connect to desktop" = "Połącz do komputera"; + /* No comment provided by engineer. */ "connect to SimpleX Chat developers." = "połącz się z deweloperami SimpleX Chat."; @@ -801,9 +828,15 @@ /* No comment provided by engineer. */ "connected" = "połączony"; +/* No comment provided by engineer. */ +"Connected desktop" = "Połączony komputer"; + /* rcv group event chat item */ "connected directly" = "połącz bezpośrednio"; +/* No comment provided by engineer. */ +"Connected to desktop" = "Połączony do komputera"; + /* No comment provided by engineer. */ "connecting" = "łączenie"; @@ -828,6 +861,9 @@ /* No comment provided by engineer. */ "Connecting server… (error: %@)" = "Łączenie z serwerem... (błąd: %@)"; +/* No comment provided by engineer. */ +"Connecting to desktop" = "Łączenie z komputerem"; + /* chat list item title */ "connecting…" = "łączenie…"; @@ -846,6 +882,9 @@ /* No comment provided by engineer. */ "Connection request sent!" = "Prośba o połączenie wysłana!"; +/* No comment provided by engineer. */ +"Connection terminated" = "Połączenie zakończone"; + /* No comment provided by engineer. */ "Connection timeout" = "Czas połączenia minął"; @@ -900,6 +939,9 @@ /* No comment provided by engineer. */ "Create" = "Utwórz"; +/* No comment provided by engineer. */ +"Create a group using a random profile." = "Utwórz grupę używając losowego profilu."; + /* No comment provided by engineer. */ "Create an address to let people connect with you." = "Utwórz adres, aby ludzie mogli się z Tobą połączyć."; @@ -1173,6 +1215,15 @@ /* No comment provided by engineer. */ "Description" = "Opis"; +/* No comment provided by engineer. */ +"Desktop address" = "Adres komputera"; + +/* No comment provided by engineer. */ +"Desktop app version %@ is not compatible with this app." = "Wersja aplikacji komputerowej %@ nie jest kompatybilna z tą aplikacją."; + +/* No comment provided by engineer. */ +"Desktop devices" = "Urządzenia komputerowe"; + /* No comment provided by engineer. */ "Develop" = "Deweloperskie"; @@ -1236,9 +1287,15 @@ /* server test step */ "Disconnect" = "Rozłącz"; +/* No comment provided by engineer. */ +"Disconnect desktop?" = "Rozłączyć komputer?"; + /* No comment provided by engineer. */ "Discover and join groups" = "Odkrywaj i dołączaj do grup"; +/* No comment provided by engineer. */ +"Discover via local network" = "Odkryj przez sieć lokalną"; + /* No comment provided by engineer. */ "Do it later" = "Zrób to później"; @@ -1374,6 +1431,12 @@ /* chat item text */ "encryption re-negotiation allowed for %@" = "renegocjacja szyfrowania dozwolona dla %@"; +/* message decrypt error item */ +"Encryption re-negotiation error" = "Błąd renegocjacji szyfrowania"; + +/* No comment provided by engineer. */ +"Encryption re-negotiation failed." = "Renegocjacja szyfrowania nie powiodła się."; + /* chat item text */ "encryption re-negotiation required" = "renegocjacja szyfrowania wymagana"; @@ -1404,6 +1467,9 @@ /* No comment provided by engineer. */ "Enter server manually" = "Wprowadź serwer ręcznie"; +/* No comment provided by engineer. */ +"Enter this device name…" = "Podaj nazwę urządzenia…"; + /* placeholder */ "Enter welcome message…" = "Wpisz wiadomość powitalną…"; @@ -1605,6 +1671,9 @@ /* No comment provided by engineer. */ "Fast and no wait until the sender is online!" = "Szybko i bez czekania aż nadawca będzie online!"; +/* No comment provided by engineer. */ +"Faster joining and more reliable messages." = "Szybsze dołączenie i bardziej niezawodne wiadomości."; + /* No comment provided by engineer. */ "Favorite" = "Ulubione"; @@ -1662,6 +1731,9 @@ /* No comment provided by engineer. */ "For console" = "Dla konsoli"; +/* No comment provided by engineer. */ +"Found desktop" = "Znaleziono komputer"; + /* No comment provided by engineer. */ "French interface" = "Francuski interfejs"; @@ -1866,6 +1938,9 @@ /* No comment provided by engineer. */ "Incognito" = "Incognito"; +/* No comment provided by engineer. */ +"Incognito groups" = "Grupy incognito"; + /* No comment provided by engineer. */ "Incognito mode" = "Tryb incognito"; @@ -1893,6 +1968,9 @@ /* No comment provided by engineer. */ "Incompatible database version" = "Niekompatybilna wersja bazy danych"; +/* No comment provided by engineer. */ +"Incompatible version" = "Niekompatybilna wersja"; + /* PIN entry */ "Incorrect passcode" = "Nieprawidłowy pin"; @@ -2028,6 +2106,9 @@ /* No comment provided by engineer. */ "Joining group" = "Dołączanie do grupy"; +/* No comment provided by engineer. */ +"Keep the app open to use it from desktop" = "Zostaw aplikację otwartą i używaj ją z komputera"; + /* No comment provided by engineer. */ "Keep your connections" = "Zachowaj swoje połączenia"; @@ -2064,6 +2145,15 @@ /* No comment provided by engineer. */ "Limitations" = "Ograniczenia"; +/* No comment provided by engineer. */ +"Link mobile and desktop apps! 🔗" = "Połącz mobile i komputerowe aplikacje! 🔗"; + +/* No comment provided by engineer. */ +"Linked desktop options" = "Połączone opcje komputera"; + +/* No comment provided by engineer. */ +"Linked desktops" = "Połączone komputery"; + /* No comment provided by engineer. */ "LIVE" = "NA ŻYWO"; @@ -2319,6 +2409,9 @@ /* copied message info in history */ "no text" = "brak tekstu"; +/* No comment provided by engineer. */ +"Not compatible!" = "Nie kompatybilny!"; + /* No comment provided by engineer. */ "Notifications" = "Powiadomienia"; @@ -2462,6 +2555,9 @@ /* No comment provided by engineer. */ "Paste" = "Wklej"; +/* No comment provided by engineer. */ +"Paste desktop address" = "Wklej adres komputera"; + /* No comment provided by engineer. */ "Paste image" = "Wklej obraz"; @@ -2846,6 +2942,9 @@ /* No comment provided by engineer. */ "Scan QR code" = "Zeskanuj kod QR"; +/* No comment provided by engineer. */ +"Scan QR code from desktop" = "Zeskanuj kod QR z komputera"; + /* No comment provided by engineer. */ "Scan security code from your contact's app." = "Zeskanuj kod bezpieczeństwa z aplikacji Twojego kontaktu."; @@ -2990,6 +3089,9 @@ /* No comment provided by engineer. */ "Servers" = "Serwery"; +/* No comment provided by engineer. */ +"Session code" = "Kod sesji"; + /* No comment provided by engineer. */ "Set 1 day" = "Ustaw 1 dzień"; @@ -3299,6 +3401,9 @@ /* notification title */ "this contact" = "ten kontakt"; +/* No comment provided by engineer. */ +"This device name" = "Nazwa tego urządzenia"; + /* No comment provided by engineer. */ "This group has over %lld members, delivery receipts are not sent." = "Ta grupa ma ponad %lld członków, potwierdzenia dostawy nie są wysyłane."; @@ -3320,6 +3425,9 @@ /* No comment provided by engineer. */ "To connect, your contact can scan QR code or use the link in the app." = "Aby się połączyć, Twój kontakt może zeskanować kod QR lub skorzystać z linku w aplikacji."; +/* No comment provided by engineer. */ +"To hide unwanted messages." = "Aby ukryć niechciane wiadomości."; + /* No comment provided by engineer. */ "To make a new connection" = "Aby nawiązać nowe połączenie"; @@ -3416,6 +3524,12 @@ /* No comment provided by engineer. */ "Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection." = "O ile Twój kontakt nie usunął połączenia lub ten link był już użyty, może to być błąd - zgłoś go.\nAby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połączenia i sprawdź, czy masz stabilne połączenie z siecią."; +/* No comment provided by engineer. */ +"Unlink" = "Odłącz"; + +/* No comment provided by engineer. */ +"Unlink desktop?" = "Odłączyć komputer?"; + /* No comment provided by engineer. */ "Unlock" = "Odblokuj"; @@ -3470,6 +3584,9 @@ /* No comment provided by engineer. */ "Use for new connections" = "Użyj dla nowych połączeń"; +/* No comment provided by engineer. */ +"Use from desktop" = "Użyj z komputera"; + /* No comment provided by engineer. */ "Use iOS call interface" = "Użyj interfejsu połączeń iOS"; @@ -3491,12 +3608,24 @@ /* No comment provided by engineer. */ "Using SimpleX Chat servers." = "Używanie serwerów SimpleX Chat."; +/* No comment provided by engineer. */ +"v%@" = "v%@"; + /* No comment provided by engineer. */ "v%@ (%@)" = "v%@ (%@)"; +/* No comment provided by engineer. */ +"Verify code with desktop" = "Zweryfikuj kod z komputera"; + +/* No comment provided by engineer. */ +"Verify connection" = "Zweryfikuj połączenie"; + /* No comment provided by engineer. */ "Verify connection security" = "Weryfikuj bezpieczeństwo połączenia"; +/* No comment provided by engineer. */ +"Verify connections" = "Zweryfikuj połączenia"; + /* No comment provided by engineer. */ "Verify security code" = "Weryfikuj kod bezpieczeństwa"; @@ -3515,6 +3644,9 @@ /* No comment provided by engineer. */ "via relay" = "przez przekaźnik"; +/* No comment provided by engineer. */ +"Via secure quantum resistant protocol." = "Dzięki bezpiecznemu protokołowi odpornego kwantowo."; + /* No comment provided by engineer. */ "Video call" = "Połączenie wideo"; @@ -3554,6 +3686,9 @@ /* No comment provided by engineer. */ "waiting for confirmation…" = "oczekiwanie na potwierdzenie…"; +/* No comment provided by engineer. */ +"Waiting for desktop..." = "Oczekiwanie na komputer..."; + /* No comment provided by engineer. */ "Waiting for file" = "Oczekiwanie na plik"; diff --git a/apps/ios/pl.lproj/SimpleX--iOS--InfoPlist.strings b/apps/ios/pl.lproj/SimpleX--iOS--InfoPlist.strings index 92f6ba7764..8c0f71f744 100644 --- a/apps/ios/pl.lproj/SimpleX--iOS--InfoPlist.strings +++ b/apps/ios/pl.lproj/SimpleX--iOS--InfoPlist.strings @@ -7,6 +7,9 @@ /* Privacy - Face ID Usage Description */ "NSFaceIDUsageDescription" = "SimpleX używa Face ID do lokalnego uwierzytelniania"; +/* Privacy - Local Network Usage Description */ +"NSLocalNetworkUsageDescription" = "SimpleX używa sieci lokalnej aby pozwolić na dostęp profilom czatu użytkownika przez aplikację komputerową na tej samej sieci."; + /* Privacy - Microphone Usage Description */ "NSMicrophoneUsageDescription" = "SimpleX potrzebuje dostępu do mikrofonu, w celu połączeń audio i wideo oraz nagrywania wiadomości głosowych."; diff --git a/apps/ios/ru.lproj/Localizable.strings b/apps/ios/ru.lproj/Localizable.strings index 7d094fcf20..03e4c4c508 100644 --- a/apps/ios/ru.lproj/Localizable.strings +++ b/apps/ios/ru.lproj/Localizable.strings @@ -545,6 +545,9 @@ /* No comment provided by engineer. */ "Authentication unavailable" = "Аутентификация недоступна"; +/* member role */ +"author" = "автор"; + /* No comment provided by engineer. */ "Auto-accept" = "Автоприем"; @@ -786,6 +789,9 @@ /* server test step */ "Connect" = "Соединиться"; +/* No comment provided by engineer. */ +"Connect automatically" = "Соединяться автоматически"; + /* No comment provided by engineer. */ "Connect incognito" = "Соединиться Инкогнито"; @@ -1287,6 +1293,9 @@ /* No comment provided by engineer. */ "Discover and join groups" = "Найдите и вступите в группы"; +/* No comment provided by engineer. */ +"Discover via local network" = "Обнаружение по локальной сети"; + /* No comment provided by engineer. */ "Do it later" = "Отложить"; @@ -1722,6 +1731,9 @@ /* No comment provided by engineer. */ "For console" = "Для консоли"; +/* No comment provided by engineer. */ +"Found desktop" = "Компьютер найден"; + /* No comment provided by engineer. */ "French interface" = "Французский интерфейс"; @@ -2397,6 +2409,9 @@ /* copied message info in history */ "no text" = "нет текста"; +/* No comment provided by engineer. */ +"Not compatible!" = "Несовместимая версия!"; + /* No comment provided by engineer. */ "Notifications" = "Уведомления"; @@ -3671,6 +3686,9 @@ /* No comment provided by engineer. */ "waiting for confirmation…" = "ожидается подтверждение…"; +/* No comment provided by engineer. */ +"Waiting for desktop..." = "Ожидается подключение компьютера..."; + /* No comment provided by engineer. */ "Waiting for file" = "Ожидается прием файла"; diff --git a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c index 54478425f1..4fd62524de 100644 --- a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c +++ b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c @@ -49,6 +49,13 @@ Java_chat_simplex_common_platform_CoreKt_initHS(__unused JNIEnv *env, __unused j // from simplex-chat typedef long* chat_ctrl; +/* + When you start using any new function from Haskell libraries, + you have to add the function name to the file libsimplex.dll.def in the root directory. + And do the same by adding it into flake.nix file in the root directory, + Otherwise, Windows and Android libraries cannot be built. +*/ + extern char *chat_migrate_init(const char *path, const char *key, const char *confirm, chat_ctrl *ctrl); extern char *chat_send_cmd(chat_ctrl ctrl, const char *cmd); extern char *chat_send_remote_cmd(chat_ctrl ctrl, const int rhId, const char *cmd); diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c index e2cd7ed55c..fb561dc38d 100644 --- a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c @@ -8,8 +8,13 @@ void hs_init_with_rtsopts(int * argc, char **argv[]); JNIEXPORT void JNICALL Java_chat_simplex_common_platform_CoreKt_initHS(JNIEnv *env, jclass clazz) { +#ifdef _WIN32 + int argc = 4; + char *argv[] = {"simplex", "+RTS", "-A16m", "-H64m", NULL}; // non-moving GC is broken on windows with GHC 9.4-9.6.3 +#else int argc = 5; char *argv[] = {"simplex", "+RTS", "-A16m", "-H64m", "-xn", NULL}; // see android/simplex-api.c for details +#endif char **pargv = argv; hs_init_with_rtsopts(&argc, &pargv); } @@ -17,6 +22,13 @@ Java_chat_simplex_common_platform_CoreKt_initHS(JNIEnv *env, jclass clazz) { // from simplex-chat typedef long* chat_ctrl; +/* + When you start using any new function from Haskell libraries, + you have to add the function name to the file libsimplex.dll.def in the root directory. + And do the same by adding it into flake.nix file in the root directory, + Otherwise, Windows and Android libraries cannot be built. +*/ + extern char *chat_migrate_init(const char *path, const char *key, const char *confirm, chat_ctrl *ctrl); extern char *chat_send_cmd(chat_ctrl ctrl, const char *cmd); extern char *chat_send_remote_cmd(chat_ctrl ctrl, const int rhId, const char *cmd); diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt index ec6d4e196e..401c3afedd 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt @@ -21,14 +21,13 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import chat.simplex.common.model.* -import chat.simplex.common.platform.chatPasswordHash +import chat.simplex.common.platform.* import chat.simplex.common.ui.theme.* import chat.simplex.common.views.chat.item.ItemAction import chat.simplex.common.views.chatlist.UserProfilePickerItem import chat.simplex.common.views.chatlist.UserProfileRow import chat.simplex.common.views.database.PassphraseField import chat.simplex.common.views.helpers.* -import chat.simplex.common.platform.appPlatform import chat.simplex.common.views.CreateProfile import chat.simplex.res.MR import dev.icerock.moko.resources.StringResource @@ -138,6 +137,9 @@ fun UserProfilesView(m: ChatModel, search: MutableState, profileHidden: } } ) + KeyChangeEffect(remember { m.currentRemoteHost }.value) { + ModalManager.start.closeModal() + } } @Composable @@ -169,7 +171,7 @@ private fun UserProfilesLayout( } SectionSpacer() } - AppBarTitle(stringResource(MR.strings.your_chat_profiles)) + AppBarTitle(stringResource(MR.strings.your_chat_profiles), hostDevice(remember { chatModel.remoteHostId() })) SectionView { for (user in filteredUsers) { diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml index 82217745f7..a9d315f680 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml @@ -1519,4 +1519,9 @@ Veuillez patienter le temps que le fichier soit chargé depuis le mobile lié. La version de l\'application de bureau %s n\'est pas compatible avec cette application. Vérifier la connexion + Connexion automatique + En attente du bureau… + Bureau trouvé + Non compatible ! + Accessible via le réseau local \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml index eb28386e5d..21a56d7e99 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml @@ -356,4 +356,116 @@ Adatbázis downgrade? Chat kiürítése Adatbázis titkosítási jelmondat meg lesz változtatva. + Kapcsolódás automatikusan + Adatbázis hiba + Adatbázis titkosítási jelmondat frissül és eltárolásra kerül a beállításokban. + Adatbázis ID + Adatbázis ID: %d + Adatbázis azonosítók és \"Transport Isolation\" opciók. + Az adatbázis titkosítás jelmondata megváltoztatásra és elmentésre kerül a Keystore-ban. + Az adatbázis titkosításra kerül és a jelmondat eltárolásra a beállításokban. + Szerver törlése + Eszközhitelesítés kikapcsolva. SimpleX zár kikapcsolása. + Letiltás + Letiltás minden csoportnak + Engedélyezve minden csoportnak + engedélyezve az ismerősnek + Eltűnő üzenetek tiltottak ebben a csoportban. + Azonosító törlés + %d hét + PC címe + %ds + Kézbesítési izagolások! + Eszközhitelesítés nincs bekapcsolva. Bekapcsolhatod a SimpleX zárat a Beállításokon keresztük, miután bekapcsoltad az eszközhitelesítést. + Titkosítás visszafejtési hiba + Eltűnik ekkor: %s + szerkesztve + Törlés + %d óra + %d hónap + Azonosító törlése? + Igazolások letiltása? + Az adatbázis jelmondat eltérő a Keystore-ba elmentettől. + Közvetlen üzenetek + E-mail + Letiltás mindenkinek + Fejlesztői eszközök + Adatbázis jelmondat + %d napok + Szétkapcsolva + Az adatbázis egy véletlenszerű jelmondattal van titkosítva, lecserélheted. + %dó + %dhét + Felfedezés helyi hálózatomn keresztül + Helyi csoportok felfedezése és csatolakozás + %d üzenet moderálva %s által + Eltűnő üzenet + Ne hozz létre azonosítót + Ne mutasd ismét + SimpleX Zár kikapcsolása + e2e titkosított + ESZKÖZ + e2e titkosított videóhívás + közvetlen + PC + %d perc + %d ismerős(-ök) kiválasztva + Engedélyez + %dhónap + A közvetlen üzenetek tagok között titltottak ebben a csoportban. + %d perc + Az adatbázis egy véletlenszerű jelmondattal van titkosítva. Kérlek cseréld le exportálás előtt! + Igazolások letiltása csoportoknak? + nap + %d nap + Chat archív törlése? + Duplikálódott megjelenítési név! + Letiltás(felülírások megtartásával) + "Adatbázis upgrade" + %d üzenet blokkolva + Eltűnik ekkor + %d hét + engedélyezve számodra + Eltűnő üzenetek + Törlés + Törlés és ismerős értesítése + letiltva + %d másodperc + Minden fájl törlése + Az adatbázis titkosításra kerül. + Adatbázis jelmondat és exportálás + Az adatbázis titkosításra kerül és a jelmondat eltárolásra a Keystore-ban. + Automatikus üzenet törlés engedélyezve? + Törlés + az adatbázis verzió újabb, mint az app, de nincs lefelé migráció eddig: %s + Leírás + %d óra + %dp + Szétkapcsolás + Szerkesztés + Letiltás(csoport felülírások megtartásával) + %d csoportesemény + %d hónap + Csoport profil szerkesztése + e2e titkosított hanghívás + %d s + Decentralizált + Dekódolási hiba + Kép szerkesztése + Értesítéásek letiltása + Eszközök + Látható helyi hálózaton + Ne engedélyezd + Archívum törlése + Eltűnő üzenetek tiltottak ebben a chatben. + alap (%s) + duplikálódott üzenet + Számítógép leválasztása? + A számítógépes app verzió %s inem kompatibilis ezzel az appal. + Kézbesítés + %d fájl %s összméretben + Adatbázis jelmondat szükséges chat megnyitásához. + %dn + Engedélyeve mindenki számára + Kézbesítési izagolások kikapcsolva! \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml index e61f040a89..a9549080a8 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml @@ -1461,4 +1461,67 @@ Pokaż konsolę w nowym oknie Błąd renegocjacji szyfrowania Renegocjacja szyfrowania nie powiodła się. + Blokuj członków grupy + Utwórz grupę używając losowego profilu. + Połączony komputer + Łącz automatycznie + Adres komputera + Lepsze grupy + Komputer + Połączony do komputera + Łączenie z komputerem + Połączony telefon + Połączenie zakończone + Połącz do komputera + autor + Połączony do telefonu + Zły adres komputera + Aplikacja komputerowa %s nie jest kompatybilna z tą aplikacją. + Nowy urządzenie mobilne + Tylko jedno urządzenie może działać w tym samym czasie + Połącz mobile i komputerowe aplikacje! 🔗 + Dzięki bezpiecznemu protokołowi odpornego kwantowo. + Użyj z komputera w aplikacji mobilnej i zeskanuj kod QR.]]> + Aby ukryć niechciane wiadomości. + Niekompatybilna wersja + (nowy)]]> + Odłączyć komputer? + Połączone opcje komputera + Połączone komputery + Odkryj przez sieć lokalną + Grupy incognito + To urządzenie + %s został rozłączony]]> + Oczekiwanie na komputer… + Szybsze dołączenie i bardziej niezawodne wiadomości. + Połączone telefony + Nazwa tego urządzenia + %s]]> + Ładowanie pliku + Znaleziono komputer + Urządzenia komputerowe + Nie kompatybilny! + Połącz z telefonem + Użyj z komputera + Kod sesji + (to urządzenie v%s)]]> + Odłącz + Nazwa urządzenia zostanie udostępniona z połączonym klientem mobilnym. + Zweryfikuj kod na telefonie + Podaj nazwę urządzenia… + Błąd + Rozłącz + Wklej adres komputera + Zweryfikuj kod z komputera + Zeskanuj kod QR z komputera + Urządzenia + Odkrywane przez sieć lokalna + - opcjonalnie powiadamiaj usunięte kontakty. +\n- nazwy profili ze spacją. +\n- i wiele więcej! + Zeskanuj z telefonu + Zweryfikuj połączenia + Rozłączyć komputer? + Proszę poczekać na załadowanie pliku z połączonego telefonu + Zweryfikuj połączenie \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml index 6f13b3cf5d..dc5771316c 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml @@ -1507,7 +1507,7 @@ Свяжите мобильное и настольное приложения! 🔗 %d сообщений помечено удалёнными Группа уже существует! - Использовать с компьютера в мобильном приложении и сосканируйте QR код]]> + Использовать с компьютера в мобильном приложении и сосканируйте QR код.]]> Уже соединяется! Несовместимая версия (новое)]]> @@ -1520,7 +1520,7 @@ Инкогнито группы Вступление в группу уже начато! %d сообщений модерировано членом %s - %s]]> + %s был отключен]]> Быстрое вступление и надежная доставка сообщений. Соединиться с самим собой? Связанные мобильные @@ -1575,7 +1575,7 @@ Чтобы скрыть нежелательные сообщения. Забыть компьютер? Видео невозможно декодировать. Пожалуйста, попробуйте другое видео или свяжитесь с разработчиками. - %@ соединен(а) + %s соединен(а) %s, %s и %d членов группы Это устройство Разблокировать члена группы @@ -1599,4 +1599,11 @@ Показывать консоль в новом окне Проверять соединения Проверить соединение + Соединяться автоматически + Ожидается подключение… + %s]]> + Компьютер найден + Несовместимая версия! + автор + Найти через локальную сеть \ No newline at end of file diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties index 9c817f08f4..570e982e22 100644 --- a/apps/multiplatform/gradle.properties +++ b/apps/multiplatform/gradle.properties @@ -25,11 +25,11 @@ android.nonTransitiveRClass=true android.enableJetifier=true kotlin.mpp.androidSourceSetLayoutVersion=2 -android.version_name=5.4-beta.4 -android.version_code=161 +android.version_name=5.4 +android.version_code=162 -desktop.version_name=5.4-beta.4 -desktop.version_code=17 +desktop.version_name=5.4 +desktop.version_code=18 kotlin.version=1.8.20 gradle.plugin.version=7.4.2 diff --git a/apps/simplex-directory-service/src/Directory/Events.hs b/apps/simplex-directory-service/src/Directory/Events.hs index dab9ceb77e..89231e4db1 100644 --- a/apps/simplex-directory-service/src/Directory/Events.hs +++ b/apps/simplex-directory-service/src/Directory/Events.hs @@ -14,6 +14,7 @@ module Directory.Events DirectoryRole (..), SDirectoryRole (..), crDirectoryEvent, + viewName, ) where @@ -158,4 +159,13 @@ directoryCmdP = DCListLastGroups_ -> DCListLastGroups <$> (A.space *> A.decimal <|> pure 10) DCExecuteCommand_ -> DCExecuteCommand . T.unpack <$> (A.space *> A.takeText) where - gc f = f <$> (A.space *> A.decimal <* A.char ':') <*> A.takeTill (== ' ') + gc f = f <$> (A.space *> A.decimal <* A.char ':') <*> displayNameP + displayNameP = quoted '\'' <|> takeNameTill (== ' ') + takeNameTill p = + A.peekChar' >>= \c -> + if refChar c then A.takeTill p else fail "invalid first character in display name" + quoted c = A.char c *> takeNameTill (== c) <* A.char c + refChar c = c > ' ' && c /= '#' && c /= '@' + +viewName :: String -> String +viewName n = if ' ' `elem` n then "'" <> n <> "'" else n diff --git a/apps/simplex-directory-service/src/Directory/Service.hs b/apps/simplex-directory-service/src/Directory/Service.hs index 5a53e1a368..291457591f 100644 --- a/apps/simplex-directory-service/src/Directory/Service.hs +++ b/apps/simplex-directory-service/src/Directory/Service.hs @@ -156,7 +156,7 @@ directoryService st DirectoryOpts {superUsers, serviceName, testing} user@User { askConfirmation = do ugrId <- addGroupReg st ct g GRSPendingConfirmation sendMessage cc ct $ T.unpack $ "The group " <> displayName <> " (" <> fullName <> ") is already submitted to the directory.\nTo confirm the registration, please send:" - sendMessage cc ct $ "/confirm " <> show ugrId <> ":" <> T.unpack displayName + sendMessage cc ct $ "/confirm " <> show ugrId <> ":" <> viewName (T.unpack displayName) badRolesMsg :: GroupRolesStatus -> Maybe String badRolesMsg = \case @@ -301,7 +301,7 @@ directoryService st DirectoryOpts {superUsers, serviceName, testing} user@User { msg = maybe (MCText text) (\image -> MCImage {text, image}) image' withSuperUsers $ \cId -> do sendComposedMessage' cc cId Nothing msg - sendMessage' cc cId $ "/approve " <> show dbGroupId <> ":" <> T.unpack displayName <> " " <> show gaId + sendMessage' cc cId $ "/approve " <> show dbGroupId <> ":" <> viewName (T.unpack displayName) <> " " <> show gaId deContactRoleChanged :: GroupInfo -> ContactId -> GroupMemberRole -> IO () deContactRoleChanged g@GroupInfo {membership = GroupMember {memberRole = serviceRole}} ctId contactRole = diff --git a/blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md b/blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md index aef4dddf64..4fbfc400ad 100644 --- a/blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md +++ b/blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md @@ -2,48 +2,128 @@ layout: layouts/article.html title: "SimpleX Chat v5.4 - link mobile and desktop apps via quantum resistant protocol, and much better groups." date: 2023-11-25 -preview: SimpleX Chat v5.4 - link mobile and desktop apps via quantum resistant protocol, and much better groups. -# image: images/20231125-remote-desktop.jpg -draft: true -imageWide: true -permalink: "/blog/20231125-simplex-chat-v5-4-quantum-resistant-mobile-from-desktop-better-groups.html" +previewBody: blog_previews/20231125.html +image: images/20231125-mobile2.png +permalink: "/blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.html" --- -TODO stub for release announcement - # SimpleX Chat v5.4 - link mobile and desktop apps via quantum resistant protocol, and much better groups. **Published:** Nov 25, 2023 -- [Quick start: control SimpleX Chat mobile app from CLI](#⚡️-quick-start-use-profiles-in-SimpleX-Chat-mobile-from-desktop-app) -- [What's the problem](#whats-the-problem) -- [Why didn't we use some existing solution?](#why-didnt-we-use-some-existing-solution) +**What's new in v5.4:** +- [Link mobile and desktop apps via secure quantum-resistant protocol](#link-mobile-and-desktop-apps-via-secure-quantum-resistant-protocol). + - ⚡️ Quick start - how to use it. + - How does it work? + - 🤖 Connecting to remote CLI. +- [Better groups](#better-groups). + - [Faster to join and more reliable](#faster-to-join-with-more-reliable-message-delivery). + - [New group features](#new-group-features): + - create groups with incognito profile, + - block group members to reduce noise, + - prohibit files and media in a group. +- [Better calls](#better-calls): faster to connect, with screen sharing on desktop. -## ⚡️ Quick start: use profiles in SimpleX Chat mobile from desktop app +There are many [other improvements](#other-improvements) and fixes in this release: + - profile names now allow spaces. + - when you delete contacts, they are optionally notified. + - previously used and your own SimpleX links are recognized by the app. + - and more - see the [release notes](https://github.com/simplex-chat/simplex-chat/releases/tag/v5.4.0). -## What's the problem? +## Link mobile and desktop apps via secure quantum-resistant protocol -Currently you cannot use the same SimpleX Chat profile on mobile and desktop devices. Even though you can use small groups instead of direct conversations as a workaround, it is quite inconvenient – read status and delivery receipts become much less useful. +This release allows to use chat profiles you have in mobile app from desktop app. -So, we need a way to use the same profile on desktop as we use on mobile. +This is only possible when both devices are connected to the same local network. To send and receive messages mobile app has to be connected to the Internet. -If SimpleX Chat profile was stored on the server, the problem would have been simpler - you can just connect to it from another device. But even in this case, accessing the conversation history without compromising the security of double ratchet end-to-end encryption is not really possible. +### ⚡️ Quick start - how to use it -So we decided to implement the solution that is similar to what WhatsApp and WeChat did in early days - allowing a desktop device access profile on mobile via network. Unlike these big apps, we don't use the server to connect to mobile, but instead use the connection over the local network. +**On desktop** -The downside of this approach is that mobile device has to be with you and connected to the same local network (and in case of iOS, the app has to be in the foreground as well). But the upside is that we the connection can be secure, and that you do not have to have a copy of your profiles on the desktop, which usually has lower security. +If you don't have desktop app installed yet, [download it](https://simplex.chat/downloads/) and create any chat profile - you don't need to use it, and when you create it there are no server requests sent and no accounts are created. Think about it as about user profile on your computer. -## Why didn't we use some existing solution? +Then in desktop app settings choose *Link a mobile* - it will show a QR code. -While there are several existing protocols for remote access, all of them are vulnerable to spoofing and man + - in many cases support of sending files and images is not very good, and sending videos and large files is simply impossible. There are currently these problems: +**On mobile** -- the sender has to be online for file transfer to complete, once it was confirmed by the recipient. -- when the file is sent to the group, the sender will have to transfer it separately to each member, creating a lot of traffic. -- the file transfer is slow, as it is sent in small chunks - approximately 16kb per message. +In mobile app settings choose *Use from desktop*, scan the QR code and verify session code when it appears on both devices - it should be the same. Verifying session code confirms that the devices are connected directly via a secure encrypted connection. There is an option to verify this code on subsequent connections too, but by default it is only required once. -As a result, we limited the supported size of files in the app to 8mb. Even for supported files, it is quite inefficient for sending any files to large groups. + + +The devices are now paired, and you can continue using all mobile profiles from desktop. + +If it is an Android app, you can move the app to background, but iOS app has to remain open. In both cases, while you are using mobile profiles from desktop, you won't be able to use mobile app. + +The subsequent connections happen much faster - by default, the desktop app broadcasts its session address to the network, in encrypted form, and mobile app connects to it once you choose *Use from desktop* in mobile app settings. + +### How does it work? + +The way we designed this solution avoided any security compromises, and the end-to-end encryption remained as secure as it was - it uses [double-ratchet algorithm](../docs/GLOSSARY.md#double-ratchet-algorithm), with [perfect forward secrecy](../docs/GLOSSARY.md#forward-secrecy), [post-compromise security](../docs/GLOSSARY.md#post-compromise-security) and deniability. + +This solution is similar to WhatsApp and WeChat. But unlike these apps, no server is involved in the connection between mobile and desktop. The connection itself uses a new SimpleX Remote Control Protocol (XRCP) based on secure TLS 1.3 and additional quantum-resistant encryption inside TLS. You can read XRCP protocol specification and threat model in [this document](https://github.com/simplex-chat/simplexmq/blob/master/rfcs/2023-10-25-remote-control.md). We will soon be [augmenting double ratchet](https://github.com/simplex-chat/simplex-chat/blob/master/docs/rfcs/2023-09-30-pq-double-ratchet.md) to be resistant to quantum computers as well. + +The downside of this approach is that mobile device has to be connected to the same local network as desktop. But the upside is that the connection is secure, and you do not need to have a copy of all your data on desktop, which usually has lower security than mobile. + +Please note, that the files you send, save or play from desktop app, and also images you view are automatically saved on your desktop device (encrypted by default except videos). To remove all these files you can unlink the paired mobile device from the desktop app settings – there will be an option soon allowing to remove the files without unlinking the mobile. + +### 🤖 Connecting to remote SimpleX CLI + +*Warning*: this section is for technically advanced users! + +If you run SimpleX CLI on a computer in another network - e.g., in the cloud VM or on a Raspberry Pi at home while you are at work, you can also use if from desktop via SSH tunnel. Below assumes that you have remote machine connected via SSH and CLI running there - you can use `tmux` for it to keep running when you are not connected via ssh. + +Follow these steps to use remote CLI from desktop app: +1. On the remote machine add the IP address of your desktop to the firewall rules, so that when CLI tries to connect to this address, it connects to `localhost` instead: `iptables -t nat -A OUTPUT -p all -d 192.168.1.100 -j DNAT --to-destination 127.0.0.1` (replace `192.168.1.100` with the actual address of your desktop, and make sure it is not needed for something else on your remote machine). +2. Also on the remote machine, run Simplex CLI with the option `--device-name 'SimpleX CLI'`, or any other name you like. You can also use the command `/set device name ` to set it for the CLI. +3. Choose *Link a mobile* in desktop app settings, note the port it shows under the QR code, and click "Share link". +4. Run ssh port forwarding on desktop computer to let your remote machine connect to desktop app: `ssh -R 12345:127.0.0.1:12345 -N user@example.com` where `12345` is the port on which desktop app is listening for the connections from step 3, `example.com` is the hostname or IP address of your remote machine, and `user` is some username on remote machine. You can run port forwarding in the background by adding `-f` option. +5. On the remote machine, run CLI command `/connect remote ctrl `, where `` is the desktop session address copied in step 3. You should run this command within 1 minute from choosing *Link a mobile*. +6. If the connection is successful, the CLI will ask you to verify the session code (you need to copy and paste the command) with the one shown in desktop app. Once you use `/verify remote ctrl ` command, CLI can be used from desktop app. +7. To stop remote session use `/stop remote ctrl` command. + +## Better groups + +### Faster to join, with more reliable message delivery + +We improved the protocols for groups, by making joining groups much faster, and also by adding message forwarding. Previously, the problem was that until a new member connects directly with each existing group member, they did not see each other messages in the group. The problem is explained in detail in [this video](https://www.youtube.com/watch?v=7yjQFmhAftE&t=1104s) at 18:23. + +With v5.4, the admin who added members to the group forwards messages to and from the new members until they connect to the existing members. So you should no longer miss any messages and be surprised with replies to messages you have never seen once you and new group members upgrade. + +### New group features + + + +**Create groups with incognito profile** + +Previously, you could only create groups with your main profile. This version allows creating groups with incognito profile directly. You will not be able to add your contacts, they can only join via group link. + +**Block group members to reduce noise** + +You now can block messages from group members that send too many messages, or the messages you don't won't to see. Blocked members won't know that you blocked their messages. When they send messages they will appear in the conversation as one line, showing how many messages were blocked. You can reveal them, or delete all sequential blocked messages at once. + +**Prohibit files and media in a group** + +Group owners now have an option to prohibit sending files and media. This can be useful if you don't won't any images shared, and only want to allow text messages. + +## Better calls + +Calls in SimpleX Chat still require a lot of work to become stable, but this version improved the speed of connecting calls, and they should work for more users. + +We also added screen sharing in video calls to desktop app. + +## Other improvements + +This version also has many small and large improvements to make the app more usable and reliable. + +The new users and group profiles now allow spaces in the names, to make them more readable. To message these contacts in CLI you need to use quotes, for example, `@'John Doe' Hello!`. + +When you delete contacts, you can notify them - to let them know they can't message you. + +When you try to connect to the same contact or join the same group, or connect via your own link, the app will recognize it and warn you, or simply open the correct conversation. + +You can find the full list of fixed bugs and small improvements in the [release notes](https://github.com/simplex-chat/simplex-chat/releases/tag/v5.4.0). ## SimpleX platform diff --git a/blog/README.md b/blog/README.md index 129ba2c80d..815009139f 100644 --- a/blog/README.md +++ b/blog/README.md @@ -1,5 +1,27 @@ # Blog +Nov 25, 2023 [SimpleX Chat v5.4 released](./20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md) + +- Link mobile and desktop apps via secure quantum-resistant protocol. 🔗 +- Better groups: + - faster to join and more reliable. + - create groups with incognito profile. + - block group members to reduce noise. + - prohibit files and media in a group. +- Better calls: faster to connect, with screen sharing on desktop. +- Many other improvements. + +--- + +Sep 25, 2023 [SimpleX Chat v5.3 released](./20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md) + +- new desktop app! 💻 +- directory service and other group improvements. +- encrypted local files and media with forward secrecy. +- simplified incognito mode. + +--- + July 22, 2023 [SimpleX Chat v5.2 released](./20230722-simplex-chat-v5-2-message-delivery-receipts.md) **What's new in v5.2:** diff --git a/blog/images/20231125-block.png b/blog/images/20231125-block.png new file mode 100644 index 0000000000..1928b7a6fd Binary files /dev/null and b/blog/images/20231125-block.png differ diff --git a/blog/images/20231125-desktop1.png b/blog/images/20231125-desktop1.png new file mode 100644 index 0000000000..bfbf975216 Binary files /dev/null and b/blog/images/20231125-desktop1.png differ diff --git a/blog/images/20231125-desktop2.png b/blog/images/20231125-desktop2.png new file mode 100644 index 0000000000..cd7df13a9d Binary files /dev/null and b/blog/images/20231125-desktop2.png differ diff --git a/blog/images/20231125-desktop3.png b/blog/images/20231125-desktop3.png new file mode 100644 index 0000000000..2005983415 Binary files /dev/null and b/blog/images/20231125-desktop3.png differ diff --git a/blog/images/20231125-desktop4.png b/blog/images/20231125-desktop4.png new file mode 100644 index 0000000000..ef0f7d6606 Binary files /dev/null and b/blog/images/20231125-desktop4.png differ diff --git a/blog/images/20231125-group1.png b/blog/images/20231125-group1.png new file mode 100644 index 0000000000..e9c67dce99 Binary files /dev/null and b/blog/images/20231125-group1.png differ diff --git a/blog/images/20231125-group2.png b/blog/images/20231125-group2.png new file mode 100644 index 0000000000..740c9a49a8 Binary files /dev/null and b/blog/images/20231125-group2.png differ diff --git a/blog/images/20231125-mobile1.png b/blog/images/20231125-mobile1.png new file mode 100644 index 0000000000..8b9be68616 Binary files /dev/null and b/blog/images/20231125-mobile1.png differ diff --git a/blog/images/20231125-mobile1a.png b/blog/images/20231125-mobile1a.png new file mode 100644 index 0000000000..a68a11e0e6 Binary files /dev/null and b/blog/images/20231125-mobile1a.png differ diff --git a/blog/images/20231125-mobile2.png b/blog/images/20231125-mobile2.png new file mode 100644 index 0000000000..fdbf3331e4 Binary files /dev/null and b/blog/images/20231125-mobile2.png differ diff --git a/blog/images/20231125-mobile3.png b/blog/images/20231125-mobile3.png new file mode 100644 index 0000000000..9a88413940 Binary files /dev/null and b/blog/images/20231125-mobile3.png differ diff --git a/blog/images/20231125-mobile4.png b/blog/images/20231125-mobile4.png new file mode 100644 index 0000000000..5ae2253ed2 Binary files /dev/null and b/blog/images/20231125-mobile4.png differ diff --git a/blog/images/arrow.png b/blog/images/arrow.png new file mode 100644 index 0000000000..8d9061f1cb Binary files /dev/null and b/blog/images/arrow.png differ diff --git a/docs/DOWNLOADS.md b/docs/DOWNLOADS.md index a1576c355e..a43a694097 100644 --- a/docs/DOWNLOADS.md +++ b/docs/DOWNLOADS.md @@ -1,13 +1,13 @@ --- title: Download SimpleX apps permalink: /downloads/index.html -revision: 01.10.2023 +revision: 25.11.2023 --- -| Updated 01.10.2023 | Languages: EN | +| Updated 25.11.2023 | Languages: EN | # Download SimpleX apps -The latest stable version is v5.3.2. +The latest stable version is v5.4.0. You can get the latest beta releases from [GitHub](https://github.com/simplex-chat/simplex-chat/releases). @@ -21,24 +21,24 @@ You can get the latest beta releases from [GitHub](https://github.com/simplex-ch Using the same profile as on mobile device is not yet supported – you need to create a separate profile to use desktop apps. -**Linux**: [AppImage](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex-desktop-x86_64.AppImage) (most Linux distros), [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex-desktop-ubuntu-20_04-x86_64.deb) (and Debian-based distros), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex-desktop-ubuntu-22_04-x86_64.deb). +**Linux**: [AppImage](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-x86_64.AppImage) (most Linux distros), [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-ubuntu-20_04-x86_64.deb) (and Debian-based distros), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-ubuntu-22_04-x86_64.deb). -**Mac**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex-desktop-macos-x86_64.dmg) (Intel), [aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.1/simplex-desktop-macos-aarch64.dmg) (Apple Silicon). +**Mac**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-macos-x86_64.dmg) (Intel), [aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-macos-aarch64.dmg) (Apple Silicon). -**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0-beta.3/simplex-desktop-windows-x86-64.msi) (BETA). +**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-windows-x86_64.msi). ## Mobile apps **iOS**: [App store](https://apps.apple.com/us/app/simplex-chat/id1605771084), [TestFlight](https://testflight.apple.com/join/DWuT2LQu). -**Android**: [Play store](https://play.google.com/store/apps/details?id=chat.simplex.app), [F-Droid](https://simplex.chat/fdroid/), [APK aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex.apk), [APK armv7](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex-armv7a.apk). +**Android**: [Play store](https://play.google.com/store/apps/details?id=chat.simplex.app), [F-Droid](https://simplex.chat/fdroid/), [APK aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex.apk), [APK armv7](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-armv7a.apk). ## Terminal (console) app See [Using terminal app](/docs/CLI.md). -**Linux**: [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex-chat-ubuntu-20_04-x86-64), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex-chat-ubuntu-22_04-x86-64). +**Linux**: [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-chat-ubuntu-20_04-x86-64), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-chat-ubuntu-22_04-x86-64). -**Mac** [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex-chat-macos-x86-64), aarch64 - [compile from source](./CLI.md#). +**Mac** [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-chat-macos-x86-64), aarch64 - [compile from source](./CLI.md#). -**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.2/simplex-chat-windows-x86-64). +**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-chat-windows-x86-64). diff --git a/docs/guide/app-settings.md b/docs/guide/app-settings.md index 26817a20f2..5482a1297f 100644 --- a/docs/guide/app-settings.md +++ b/docs/guide/app-settings.md @@ -8,7 +8,7 @@ title: App settings To open app settings: - Open the app. -- Tap on your user profile image in the upper right-hand of the screen. +- Tap on your user profile image in the upper left-hand of the screen. - If you have more than one profile, tap the current profile again or choose Settings. ## Your profile settings diff --git a/docs/rfcs/2023-09-30-pq-double-ratchet.md b/docs/rfcs/2023-09-30-pq-double-ratchet.md new file mode 100644 index 0000000000..255051320d --- /dev/null +++ b/docs/rfcs/2023-09-30-pq-double-ratchet.md @@ -0,0 +1,224 @@ +# Post-quantum resistant augmented double ratchet algorithm + +- [Overview](#overview) +- [Problem](#problem) +- [Comparison of the proposed solutions](#comparison-of-the-proposed-solutions) + - [PQXDH for post-quantum key agreement](#pqxdh-for-post-quantum-key-agreement) (Signal) + - [Hybrid Signal protocol for post-quantum encryption](#hybrid-signal-protocol-for-post-quantum-encryption) (Tutanota) + - [Problems with ML-KEM / Kyber](#problems-with-ml-kem--kyber) +- [Proposed solution: augmented double ratchet algorithm](#proposed-solution-augmented-double-ratchet-algorithm) +- [Double ratchet with encrypted headers augmented with double PQ KEM](#double-ratchet-with-encrypted-headers-augmented-with-double-pq-kem) + - [Initialization](#initialization) + - [Encrypting messages](#encrypting-messages) + - [Decrypting messages](#decrypting-messages) +- [Alternative approach: CTIDH](#alternative-approach-ctidh) +- [Implementation considerations for SimpleX Chat](#implementation-considerations-for-simplex-chat) +- [Summary](#summary) +- [Notes](#notes) + +## 1. Overview + +Currently SimpleX Chat uses [double-ratchet with header encryption](https://signal.org/docs/specifications/doubleratchet/#double-ratchet-with-header-encryption) to provide end-to-end encryption to messages and files. This document proposes a way to augment this algorithm with post-quantum key encapsulation mechanism (KEM) to make it resistant to quantum computers. + +This document is purposefully written in an informal style to make it understandable for general audience with some technical, but without mathematical background. It does not compromise on the technical accuracy though. + +## 2. Problem + +It is a reasonable assumption that "record-now-decrypt-later" attacks are ongoing, so the users want to use cryptographic schemes for end-to-end encryption that are augmented with some post-quantum algorithm that is believed to be resistant to quantum computers. + +Double-ratchet algorithm is a state of the art solution for end to end encryption offering a set of qualities that is unmatched by any other algorithm: + +- perfect forward secrecy, i.e. compromise of session or long term keys does not lead to the ability to decrypt any of the past messages. +- deniability (also known as repudiation), i.e. the fact that the recipient of the message cannot prove to a third party that the sender actually sent this message [1]. +- break-in recovery [2] (also know as post-compromise security or future secrecy), i.e. the ability of the end-to-end encryption security to recover from the compromise of the long term keys. This is achieved by generating a new random key pair whenever a new DH key is received (DH ratchet step). + +It is desirable to preserve all these qualities when augmenting the algorithm with a post-quantum algorithm, and having these qualities resistant (or "believed to be" resistant [3]) to both conventional and quantum computers. + +## Comparison of the proposed solutions + +### PQXDH for post-quantum key agreement + +[The solution](https://signal.org/docs/specifications/pqxdh/) recently [introduced by Signal](https://signal.org/blog/pqxdh/) augments the initial key agreement ([X3DH](https://signal.org/docs/specifications/x3dh/)) that is made prior to double ratchet algorithm. This is believed to provide protection from "record-now-decrypt-later" attack, but if the attacker at any point obtains long term keys from any of the devices, the break-in recovery will not be post-quantum resistant, and the attacker would be able to decrypt all the subsequent messages. + +In addition to that, the authentication of parties in the proposed scheme is also not post-quantum resistant, although this is not part of double ratchet algorithm. + +### Hybrid Signal protocol for post-quantum encryption + +[The solution](https://eprint.iacr.org/2021/875.pdf) [proposed by Tutanota](https://tutanota.com/blog/posts/pqmail-update/) aims to preserve the break-in recovery property of double ratchet, but in doing so it: +- replaces rather than augments DH key agreement with post-quantum KEM mechanism, making it potentially vulnerable to conventional computers. +- adds signature to the DH ratchet step, to compensate for not keeping DH key agreement, but losing the deniability property for some of the messages. + +### Problems with ML-KEM / Kyber + +ML-KEM / Kyber used in both Signal and Tutanota schemes is the chosen algorithm by NIST, but its standardisation process raised some concerns amongst the experts: + +- hashing of random numbers that was present in the original submission was removed from the standardised version of the algorithm. See lines 304-314 in the published spec (https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf) and also the linked discussion on the subject: https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/WFRDl8DqYQ4. This decision polarised the experts, with some of them saying that it effectively created a backdoor. +- calculation of security levels of Kyber appears to have been done incorrectly, and overall, the chosen Kyber seems worse than rejected NTRU according to [the analysis by Daniel Bernstein](https://blog.cr.yp.to/20231003-countcorrectly.html). + +## Proposed solution: augmented double ratchet algorithm + +We will augment the double ratchet algorithm with post-quantum KEM mechanism, preserving all properties of the double ratchet algorithm. + +It is possible, because although double ratchet uses DH (which is a non-interactive key exchange [4]), it uses it "interactively", when the new DH keys are generated by both parties in turns. Parties of double-ratchet encrypted communication can run one or two post-quantum key encapsulation mechanisms in parallel with DH key agreement on each DH ratchet step, making break-in recovery of double ratchet algorithm post-quantum resistant (unlike Signal PQXDH scheme), without losing deniability or resistance to conventional computers (unlike Tutanota scheme). + +Specifically, it is proposed to augment [double ratchet with encrypted headers](https://signal.org/docs/specifications/doubleratchet/#double-ratchet-with-header-encryption) with some post-quantum key encapsulation mechanism (KEM) as described below. A possible algorithm for PQ KEM is [NTRU-prime](https://ntruprime.cr.yp.to), that is currently adopted in SSH and has available implementations. It is important though that the proposed scheme can be used with any PQ KEM algorithm. + +The downside of the proposed scheme is its substantial size overhead, as the encapsulation key and/or encapsulated shared secret are added to the header of each message. For the scheme described below, when both the encapsulation key and encapsulated secret are added to each message header, NTRU-prime adds ~2-4kb to each message (depending on the key size and the chosen variant). See [this table](https://ntruprime.cr.yp.to/security.html) for key and ciphertext sizes and the assessment of the security level for various key sizes. + +## Double ratchet with encrypted headers augmented with double PQ KEM + +Algorithm below assumes that in addition to shared secret from the initial key agreement, there will be an encapsulation key available from the party that published its keys (Bob). + +### Initialization + +The double ratchet initialization is defined in pseudocode as follows: + +``` +// Alice obtained Bob's keys and initializes ratchet first +def RatchetInitAlicePQ2HE(state, SK, bob_dh_public_key, shared_hka, shared_nhkb, bob_pq_kem_encapsulation_key): + state.DHRs = GENERATE_DH() + state.DHRr = bob_dh_public_key + // below added for post-quantum KEM + state.PQRs = GENERATE_PQKEM() + state.PQRr = bob_pq_kem_encapsulation_key + state.PQRss = random // shared secret for KEM + state.PQRenc_ss = PQKEM-ENC(state.PQRr.encaps, state.PQRss) // encapsulated additional shared secret + // above added for KEM + // below augments DH key agreement with PQ shared secret + state.RK, state.CKs, state.NHKs = KDF_RK_HE(SK, DH(state.DHRs, state.DHRr) || state.PQRss) + state.CKr = None + state.Ns = 0 + state.Nr = 0 + state.PN = 0 + state.MKSKIPPED = {} + state.HKs = shared_hka + state.HKr = None + state.NHKr = shared_nhkb + +// Bob initializes ratchet second, having received Alice's connection request +def RatchetInitBobPQ2HE(state, SK, bob_dh_key_pair, shared_hka, shared_nhkb, bob_pq_kem_key_pair): + state.DHRs = bob_dh_key_pair + state.DHRr = None + // below added for KEM + state.PQRs = bob_pq_kem_key_pair + state.PQRr = None + state.PQRss = None + state.PQRenc_ss = None + // above added for KEM + state.RK = SK + state.CKs = None + state.CKr = None + state.Ns = 0 + state.Nr = 0 + state.PN = 0 + state.MKSKIPPED = {} + state.HKs = None + state.NHKs = shared_nhkb + state.HKr = None + state.NHKr = shared_hka +``` + +`GENERATE_PQKEM` generates decapsulation/encapsulation key pair. + +`PQKEM-ENC` is key encapsulation algorithm. + +Other than commented lines, the above adds parameters `bob_pq_kem_encapsulation_key` and `bob_pq_kem_key_pair` to the ratchet intialization. Otherwise it is identical to the original double ratchet initialization. + +### Encrypting messages + +``` +def RatchetEncryptPQ2HE(state, plaintext, AD): + state.CKs, mk = KDF_CK(state.CKs) + // encapsulation key from PQRs and encapsulated shared secret is added to header + header = HEADER_PQ2( + dh = state.DHRs.public, + pn = state.PN, + n = state.Ns, + encaps = state.PQRs.encaps, // added for KEM #1 + enc_ss = state.PQRenc_ss // added for KEM #2 + ) + enc_header = HENCRYPT(state.HKs, header) + state.Ns += 1 + return enc_header, ENCRYPT(mk, plaintext, CONCAT(AD, enc_header)) +``` + +Other than adding encapsulation key and encapsulated shared secret into the header, the above is identical to the original double ratchet message encryption step. + +As an optimization, to save space, it might be possible to add encapsulation key and encapsulated secret only when they change. The downside of this optimization would be that it will be impossible to decrypt the message when the message that has them is skipped or lost, compromising the ability of double ratchet to manage skipped messages. + +### Decrypting messages + +``` +def RatchetDecryptPQ2HE(state, enc_header, ciphertext, AD): + plaintext = TrySkippedMessageKeysHE(state, enc_header, ciphertext, AD) + if plaintext != None: + return plaintext + header, dh_ratchet = DecryptHeader(state, enc_header) // DecryptHeader is the same as in double ratchet specification + if dh_ratchet: + SkipMessageKeysHE(state, header.pn) // SkipMessageKeysHE is the same as in double ratchet specification + DHRatchetPQ2HE(state, header) + SkipMessageKeysHE(state, header.n) + state.CKr, mk = KDF_CK(state.CKr) + state.Nr += 1 + return DECRYPT(mk, ciphertext, CONCAT(AD, enc_header)) + +def DHRatchetPQ2HE(state, header): + state.PN = state.Ns + state.Ns = 0 + state.Nr = 0 + state.HKs = state.NHKs + state.HKr = state.NHKr + state.DHRr = header.dh + // save new encapsulation key from header + state.PQRr = header.encaps + // decapsulate shared secret from header - KEM #2 + ss = PQKEM-DEC(state.PQRs.decaps, header.enc_ss) + // use decapsulated shared secret with receiving ratchet + state.RK, state.CKr, state.NHKr = KDF_RK_HE(state.RK, DH(state.DHRs, state.DHRr) || ss) + state.DHRs = GENERATE_DH() + // below is added for KEM + state.PQRs = GENERATE_PQKEM() // generate new PQ key pair + state.PQRss = random // shared secret for KEM + state.PQRenc_ss = PQKEM-ENC(state.PQRr.encaps, state.PQRss) // encapsulated additional shared secret KEM #1 + // above is added for KEM + // use new shared secret with sending ratchet + state.RK, state.CKs, state.NHKs = KDF_RK_HE(state.RK, DH(state.DHRs, state.DHRr) || state.PQRss) +``` + +`PQKEM-DEC` is key decapsulation algorithm. + +`DHRatchetPQ2HE` augments both DH agreements with decapsulated shared secret from the received header and with the new shared secret, respectively. The new shared secret together with the new encapsulation key are saved in the state and will be added to the header in the next sent message. + +Other than augmenting DH key agreements with the shared secrets from KEM, the above is identical to the original double ratchet DH ratchet step. + +It is worth noting that while DH agreements work as ping-pong, when the new received DH key is used for both DH agreements (and only the sent DH key is updated for the second DH key agreement), PQ KEM agreements in the proposed scheme work as a "parallel ping-pong", with two balls in play all the time (two KEM agreements run in parallel). + +## Alternative approach: CTIDH + +Instead of using KEM, we can consider using [CTIDH](https://ctidh.isogeny.org). The advantage is a smaller key size, and also as CTIDH is non-interactive [4], there is no need to run two key agreements in parallel, the PQ keys would simply augment DH keys and would be used in the same way. + +The main downside is the absense of performance-efficient implementation for aarch64 architecture. + +## Implementation considerations for SimpleX Chat + +As SimpleX Chat pads messages to a fixed size, using 16kb transport blocks, the size increase introduced by this scheme will not cause additional traffic in most cases. For large texts it may require additional messages to be sent. Similarly, for media previews it may require either reducing the preview size (and quality) or sending additional messages. + +That might be the primary reason why this scheme was not adopted by Signal, as it would have resulted in substantial traffic growth – to the best of our knowledge, Signal messages are not padded to a fixed size. + +Sharing the initial keys in case of SimpleX Chat it is equivalent to sharing the invitation link. As encapsulation key is large, it may be inconvenient to share it in the link in some contexts. + +It is possible to postpone sharing the encapsulation key until the first message from Alice (confirmation message in SMP protocol), the party sending connection request. The upside here is that the invitation link size would not increase. The downside is that the user profile shared in this confirmation will not be encrypted with PQ-resistant algorithm. To mitigate it, the hadnshake protocol can be modified to postpone sending the user profile until the second message from Alice (HELLO message in SMP protocol). + +## Summary + +If chosen PQ KEM proves secure against quantum computer attacks, then the proposed augmented double ratchet will also be secure against quantum computer attack, including break-in recovery property, while keeping deniability and forward secrecy, because the [same proof](https://eprint.iacr.org/2016/1013.pdf) as for double ratchet algorithm would hold here, provided KEM is secure. + +## Notes + +[1] This is often misunderstood to mean that the recipient cannot prove that the sender sent the message at all, which is incorrect, as the recipient has the proof that either themselves or the sender encrypted the message, and as they know that the recipient themselves did not encrypt it, therefore the sender did. So the communication is secure and authenticated for the parties, without providing a proof to a third party. + +[2] The term "break-in recovery" is used in this document, consistent with the terminology of the double ratchet algorithm specification, and also because it can be used to mean both the quality of being able to recover from the compromise and the actual process used to recover. + +[3] This is important to remember that no existing post-quantum algorithms are proven to be resistant to quantum or even conventional computers, therefore the correct approach is to augment rather than replace existing algorithms with the post-quantum ones. + +[4] Non-interactive key exchange is a type of key agreement that allows both parties to generate key pairs independently, without input from another parties, and then use the public keys from each other to compute the same shared secret. diff --git a/libsimplex.dll.def b/libsimplex.dll.def index 2d6e813d77..4255f4409c 100644 --- a/libsimplex.dll.def +++ b/libsimplex.dll.def @@ -1,6 +1,7 @@ LIBRARY libsimplex EXPORTS hs_init + hs_init_with_rtsopts chat_migrate_init chat_send_cmd chat_send_remote_cmd diff --git a/tests/Bots/DirectoryTests.hs b/tests/Bots/DirectoryTests.hs index 730e516a14..3038f0849d 100644 --- a/tests/Bots/DirectoryTests.hs +++ b/tests/Bots/DirectoryTests.hs @@ -10,6 +10,7 @@ import ChatTests.Utils import Control.Concurrent (forkIO, killThread, threadDelay) import Control.Exception (finally) import Control.Monad (forM_) +import Directory.Events (viewName) import Directory.Options import Directory.Service import Directory.Store @@ -27,6 +28,7 @@ directoryServiceTests = do it "should register group" testDirectoryService it "should suspend and resume group" testSuspendResume it "should join found group via link" testJoinGroup + it "should support group names with spaces" testGroupNameWithSpaces describe "de-listing the group" $ do it "should de-list if owner leaves the group" testDelistedOwnerLeaves it "should de-list if owner is removed from the group" testDelistedOwnerRemoved @@ -242,6 +244,24 @@ testJoinGroup tmp = cath <## "#privacy: new member dan is connected" ] +testGroupNameWithSpaces :: HasCallStack => FilePath -> IO () +testGroupNameWithSpaces tmp = + withDirectoryService tmp $ \superUser dsLink -> + withNewTestChat tmp "bob" bobProfile $ \bob -> do + bob `connectVia` dsLink + registerGroup superUser bob "Privacy & Security" "" + groupFound bob "Privacy & Security" + superUser #> "@SimpleX-Directory /suspend 1:'Privacy & Security'" + superUser <# "SimpleX-Directory> > /suspend 1:'Privacy & Security'" + superUser <## " Group suspended!" + bob <# "SimpleX-Directory> The group ID 1 (Privacy & Security) is suspended and hidden from directory. Please contact the administrators." + groupNotFound bob "privacy" + superUser #> "@SimpleX-Directory /resume 1:'Privacy & Security'" + superUser <# "SimpleX-Directory> > /resume 1:'Privacy & Security'" + superUser <## " Group listing resumed!" + bob <# "SimpleX-Directory> The group ID 1 (Privacy & Security) is listed in the directory again!" + groupFound bob "Privacy & Security" + testDelistedOwnerLeaves :: HasCallStack => FilePath -> IO () testDelistedOwnerLeaves tmp = withDirectoryServiceCfg tmp testCfgCreateGroupDirect $ \superUser dsLink -> @@ -839,16 +859,16 @@ registerGroupId su u n fn gId ugId = do submitGroup :: TestCC -> String -> String -> IO () submitGroup u n fn = do - u ##> ("/g " <> n <> " " <> fn) - u <## ("group #" <> n <> " (" <> fn <> ") is created") - u <## ("to add members use /a " <> n <> " or /create link #" <> n) - u ##> ("/a " <> n <> " SimpleX-Directory admin") - u <## ("invitation to join the group #" <> n <> " sent to SimpleX-Directory") + u ##> ("/g " <> viewName n <> if null fn then "" else " " <> fn) + u <## ("group #" <> viewName n <> (if null fn then "" else " (" <> fn <> ")") <> " is created") + u <## ("to add members use /a " <> viewName n <> " or /create link #" <> viewName n) + u ##> ("/a " <> viewName n <> " SimpleX-Directory admin") + u <## ("invitation to join the group #" <> viewName n <> " sent to SimpleX-Directory") groupAccepted :: TestCC -> String -> IO String groupAccepted u n = do u <# ("SimpleX-Directory> Joining the group " <> n <> "…") - u <## ("#" <> n <> ": SimpleX-Directory joined the group") + u <## ("#" <> viewName n <> ": SimpleX-Directory joined the group") u <# ("SimpleX-Directory> Joined the group " <> n <> ", creating the link…") u <# "SimpleX-Directory> Created the public link to join the group via this directory service that is always online." u <## "" @@ -868,7 +888,7 @@ completeRegistrationId su u n fn welcomeWithLink gId ugId = do updateProfileWithLink :: TestCC -> String -> String -> Int -> IO () updateProfileWithLink u n welcomeWithLink ugId = do - u ##> ("/set welcome " <> n <> " " <> welcomeWithLink) + u ##> ("/set welcome " <> viewName n <> " " <> welcomeWithLink) u <## "description changed to:" u <## welcomeWithLink u <# ("SimpleX-Directory> Thank you! The group link for ID " <> show ugId <> " (" <> n <> ") is added to the welcome message.") @@ -878,13 +898,13 @@ notifySuperUser :: TestCC -> TestCC -> String -> String -> String -> Int -> IO ( notifySuperUser su u n fn welcomeWithLink gId = do uName <- userName u su <# ("SimpleX-Directory> " <> uName <> " submitted the group ID " <> show gId <> ":") - su <## (n <> " (" <> fn <> ")") + su <## (n <> if null fn then "" else " (" <> fn <> ")") su <## "Welcome message:" su <## welcomeWithLink su .<## "members" su <## "" su <## "To approve send:" - let approve = "/approve " <> show gId <> ":" <> n <> " 1" + let approve = "/approve " <> show gId <> ":" <> viewName n <> " 1" su <# ("SimpleX-Directory> " <> approve) approveRegistration :: TestCC -> TestCC -> String -> Int -> IO () @@ -893,7 +913,7 @@ approveRegistration su u n gId = approveRegistrationId :: TestCC -> TestCC -> String -> Int -> Int -> IO () approveRegistrationId su u n gId ugId = do - let approve = "/approve " <> show gId <> ":" <> n <> " 1" + let approve = "/approve " <> show gId <> ":" <> viewName n <> " 1" su #> ("@SimpleX-Directory " <> approve) su <# ("SimpleX-Directory> > " <> approve) su <## " Group approved!" @@ -947,7 +967,7 @@ groupFoundN count u name = do u #> ("@SimpleX-Directory " <> name) u <# ("SimpleX-Directory> > " <> name) u <## " Found 1 group(s)" - u <#. ("SimpleX-Directory> " <> name <> " (") + u <#. ("SimpleX-Directory> " <> name) u <## "Welcome message:" u <##. "Link to join the group " u <## (show count <> " members") diff --git a/website/src/_includes/blog_previews/20231125.html b/website/src/_includes/blog_previews/20231125.html new file mode 100644 index 0000000000..964a5ae983 --- /dev/null +++ b/website/src/_includes/blog_previews/20231125.html @@ -0,0 +1,15 @@ +

v5.4 is released:

+ +
    +
  • Link mobile and desktop apps via secure quantum-resistant protocol. 🔗
  • +
  • Better groups:

    +
      +
    • faster to join and more reliable.
    • +
    • create groups with incognito profile.
    • +
    • block group members to reduce noise.
    • +
    • prohibit files and media in a group.
    • +
    +
  • +
  • Better calls: faster to connect, with screen sharing on desktop.
  • +
  • Many other improvements.
  • +