From 17e8aa43fb5c576134490abed0c35b6f30587a90 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 29 Feb 2020 08:21:50 +0000 Subject: [PATCH 01/14] Fixed link to group chat. closes #3624 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f668a919d..6e935c15c 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,7 @@ FCM (Google Push) allows an app to wake up from *Doze* which is (as the name sug #### Conversations doesn’t work for me. Where can I get help? -You can join our conference room on `conversations@conference.siacs.eu`. +You can join our conference room on [`conversations@conference.siacs.eu`](https://conversations.im/j/conversations@conference.siacs.eu). A lot of people in there are able to answer basic questions about the usage of Conversations or can provide you with tips on running your own XMPP server. If you found a bug or your app crashes please read the Developer / Report Bugs From 5dd666257d1211662fa30f05222f8c2fa486ec1a Mon Sep 17 00:00:00 2001 From: genofire Date: Sat, 29 Feb 2020 10:14:52 +0100 Subject: [PATCH 02/14] [BUGFIX] crash on resolve.toString if hostname is null (#3635) --- src/main/java/eu/siacs/conversations/utils/Resolver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/utils/Resolver.java b/src/main/java/eu/siacs/conversations/utils/Resolver.java index 8ba1c4cd7..a7072e8bc 100644 --- a/src/main/java/eu/siacs/conversations/utils/Resolver.java +++ b/src/main/java/eu/siacs/conversations/utils/Resolver.java @@ -368,7 +368,7 @@ public class Resolver { public String toString() { return "Result{" + "ip='" + (ip == null ? null : ip.getHostAddress()) + '\'' + - ", hostame='" + hostname.toString() + '\'' + + ", hostame='" + (hostname == null ? null : hostname.toString()) + '\'' + ", port=" + port + ", directTls=" + directTls + ", authenticated=" + authenticated + From 0f40e7e73b0dbec2382201b6f8ace2a522797b62 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 29 Feb 2020 12:52:39 +0100 Subject: [PATCH 03/14] fixed typo in resolver that cause hostnames not to be marked as authenticated (with DNSSec) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit usually this wasn’t a problem as this is only the fallback after no IPs have been discovered. this also isn‘t a security issue as worst case is the hostname doesn’t get accepeted as fallback in cert validation. thanks @genofire for spotting this --- .../conversations/crypto/axolotl/AxolotlService.java | 2 +- src/main/java/eu/siacs/conversations/utils/Resolver.java | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 018a86b5d..e67755586 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -651,7 +651,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { final boolean wipe, final boolean firstAttempt) { final Bundle publishOptions = account.getXmppConnection().getFeatures().pepPublishOptions() ? PublishOptions.openAccess() : null; - IqPacket publish = mXmppConnectionService.getIqGenerator().publishBundles( + final IqPacket publish = mXmppConnectionService.getIqGenerator().publishBundles( signedPreKeyRecord, axolotlStore.getIdentityKeyPair().getPublicKey(), preKeyRecords, getOwnDeviceId(), publishOptions); Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + ": Bundle " + getOwnDeviceId() + " in PEP not current. Publishing..."); diff --git a/src/main/java/eu/siacs/conversations/utils/Resolver.java b/src/main/java/eu/siacs/conversations/utils/Resolver.java index a7072e8bc..247e77fae 100644 --- a/src/main/java/eu/siacs/conversations/utils/Resolver.java +++ b/src/main/java/eu/siacs/conversations/utils/Resolver.java @@ -61,7 +61,9 @@ public class Resolver { final Field dnsClientField = ReliableDNSClient.class.getDeclaredField("dnsClient"); dnsClientField.setAccessible(true); final DNSClient dnsClient = (DNSClient) dnsClientField.get(reliableDNSClient); - dnsClient.getDataSource().setTimeout(3000); + if (dnsClient != null) { + dnsClient.getDataSource().setTimeout(3000); + } final Field useHardcodedDnsServers = DNSClient.class.getDeclaredField("useHardcodedDnsServers"); useHardcodedDnsServers.setAccessible(true); useHardcodedDnsServers.setBoolean(dnsClient, false); @@ -176,7 +178,7 @@ public class Resolver { final List ipv4s = resolveIp(record, A.class, result.isAuthenticData(), directTls); if (ipv4s.size() == 0) { Result resolverResult = Result.fromRecord(record, directTls); - resolverResult.authenticated = resolverResult.isAuthenticated(); + resolverResult.authenticated = result.isAuthenticData(); ipv4s.add(resolverResult); } synchronized (results) { @@ -210,7 +212,7 @@ public class Resolver { ResolverResult results = resolveWithFallback(srv.name, type, authenticated); for (D record : results.getAnswersOrEmptySet()) { Result resolverResult = Result.fromRecord(srv, directTls); - resolverResult.authenticated = results.isAuthenticData() && authenticated; + resolverResult.authenticated = results.isAuthenticData() && authenticated; //TODO technically it doesn’t matter if the IP was authenticated resolverResult.ip = record.getInetAddress(); list.add(resolverResult); } From d35337276846310c6764abee9748ad4a2348d2a7 Mon Sep 17 00:00:00 2001 From: genofire Date: Sat, 29 Feb 2020 15:02:36 +0100 Subject: [PATCH 04/14] fix typo (#3646) sorry, this makes me crazy --- src/main/java/eu/siacs/conversations/utils/Resolver.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/utils/Resolver.java b/src/main/java/eu/siacs/conversations/utils/Resolver.java index 247e77fae..b7e866a80 100644 --- a/src/main/java/eu/siacs/conversations/utils/Resolver.java +++ b/src/main/java/eu/siacs/conversations/utils/Resolver.java @@ -40,7 +40,7 @@ public class Resolver { public static final int DEFAULT_PORT_XMPP = 5222; private static final String DIRECT_TLS_SERVICE = "_xmpps-client"; - private static final String STARTTLS_SERICE = "_xmpp-client"; + private static final String STARTTLS_SERVICE = "_xmpp-client"; private static XmppConnectionService SERVICE = null; @@ -166,7 +166,7 @@ public class Resolver { } private static List resolveSrv(String domain, final boolean directTls) throws IOException { - DNSName dnsName = DNSName.from((directTls ? DIRECT_TLS_SERVICE : STARTTLS_SERICE) + "._tcp." + domain); + DNSName dnsName = DNSName.from((directTls ? DIRECT_TLS_SERVICE : STARTTLS_SERVICE) + "._tcp." + domain); ResolverResult result = resolveWithFallback(dnsName, SRV.class); final List results = new ArrayList<>(); final List threads = new ArrayList<>(); From 08bc3ca0d522e05ea4d8cc8bb4eed798aefe5a17 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 2 Mar 2020 11:10:38 +0100 Subject: [PATCH 05/14] do not merge oob messages --- src/main/java/eu/siacs/conversations/entities/Message.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 360103aa0..e44d2a2c0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -613,6 +613,8 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable this.getBody().length() + message.getBody().length() <= Config.MAX_DISPLAY_MESSAGE_CHARS && !message.isGeoUri() && !this.isGeoUri() && + !message.isOOb() && + !this.isOOb() && !message.treatAsDownloadable() && !this.treatAsDownloadable() && !message.getBody().startsWith(ME_COMMAND) && From 7b5d0e034e14b040d1697f32190d790f9f5ef091 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 2 Mar 2020 11:11:23 +0100 Subject: [PATCH 06/14] when setting moderated also set non standard field to not make users participants by default --- .../services/XmppConnectionService.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 4280e6f00..63d6a1911 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1838,7 +1838,7 @@ public class XmppConnectionService extends Service { private void markFileDeleted(final String path) { synchronized (FILENAMES_TO_IGNORE_DELETION) { if (FILENAMES_TO_IGNORE_DELETION.remove(path)) { - Log.d(Config.LOGTAG,"ignored deletion of "+path); + Log.d(Config.LOGTAG, "ignored deletion of " + path); return; } } @@ -1854,7 +1854,7 @@ public class XmppConnectionService extends Service { for (Conversation conversation : getConversations()) { deleted |= conversation.markAsDeleted(uuids); } - for(final String uuid : uuids) { + for (final String uuid : uuids) { evictPreview(uuid); } if (deleted) { @@ -3172,16 +3172,20 @@ public class XmppConnectionService extends Service { conversation.setAttribute("accept_non_anonymous", true); updateConversation(conversation); } - IqPacket request = new IqPacket(IqPacket.TYPE.GET); + if (options.containsKey("muc#roomconfig_moderatedroom")) { + final boolean moderated = "1".equals(options.getString("muc#roomconfig_moderatedroom")); + options.putString("members_by_default", moderated ? "0" : "1"); + } + final IqPacket request = new IqPacket(IqPacket.TYPE.GET); request.setTo(conversation.getJid().asBareJid()); request.query("http://jabber.org/protocol/muc#owner"); sendIqPacket(conversation.getAccount(), request, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { if (packet.getType() == IqPacket.TYPE.RESULT) { - Data data = Data.parse(packet.query().findChild("x", Namespace.DATA)); + final Data data = Data.parse(packet.query().findChild("x", Namespace.DATA)); data.submit(options); - IqPacket set = new IqPacket(IqPacket.TYPE.SET); + final IqPacket set = new IqPacket(IqPacket.TYPE.SET); set.setTo(conversation.getJid().asBareJid()); set.query("http://jabber.org/protocol/muc#owner").addChild(data); sendIqPacket(account, set, new OnIqPacketReceived() { @@ -4580,7 +4584,7 @@ public class XmppConnectionService extends Service { public void evictPreview(String uuid) { if (mBitmapCache.remove(uuid) != null) { - Log.d(Config.LOGTAG,"deleted cached preview"); + Log.d(Config.LOGTAG, "deleted cached preview"); } } From b2e9a954abcc8c1824e8f0115cf022f07571751a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 5 Mar 2020 13:17:18 +0100 Subject: [PATCH 07/14] avoid bundled source selection that comes with ImageCropper on Android 10 --- ...ublishGroupChatProfilePictureActivity.java | 18 ++++---- .../ui/PublishProfilePictureActivity.java | 43 ++++++++++++++----- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java index 4c7b77276..898f607c4 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java @@ -49,6 +49,8 @@ import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.ui.interfaces.OnAvatarPublication; import eu.siacs.conversations.ui.util.PendingItem; +import static eu.siacs.conversations.ui.PublishProfilePictureActivity.REQUEST_CHOOSE_PICTURE; + public class PublishGroupChatProfilePictureActivity extends XmppActivity implements OnAvatarPublication { private final PendingItem pendingConversationUuid = new PendingItem<>(); private ActivityPublishProfilePictureBinding binding; @@ -93,7 +95,7 @@ public class PublishGroupChatProfilePictureActivity extends XmppActivity impleme configureActionBar(getSupportActionBar()); this.binding.cancelButton.setOnClickListener((v) -> this.finish()); this.binding.secondaryHint.setVisibility(View.GONE); - this.binding.accountImage.setOnClickListener((v) -> this.chooseAvatar()); + this.binding.accountImage.setOnClickListener((v) -> PublishProfilePictureActivity.chooseAvatar(this)); Intent intent = getIntent(); String uuid = intent == null ? null : intent.getStringExtra("uuid"); if (uuid != null) { @@ -113,7 +115,7 @@ public class PublishGroupChatProfilePictureActivity extends XmppActivity impleme @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) { - CropImage.ActivityResult result = CropImage.getActivityResult(data); + final CropImage.ActivityResult result = CropImage.getActivityResult(data); if (resultCode == RESULT_OK) { this.uri = result.getUri(); if (xmppConnectionServiceBound) { @@ -125,17 +127,13 @@ public class PublishGroupChatProfilePictureActivity extends XmppActivity impleme Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show(); } } + } else if (requestCode == REQUEST_CHOOSE_PICTURE) { + if (resultCode == RESULT_OK) { + PublishProfilePictureActivity.cropUri(this, data.getData()); + } } } - private void chooseAvatar() { - CropImage.activity() - .setOutputCompressFormat(Bitmap.CompressFormat.PNG) - .setAspectRatio(1, 1) - .setMinCropResultSize(Config.AVATAR_SIZE, Config.AVATAR_SIZE) - .start(this); - } - @Override public void onAvatarPublicationSucceeded() { runOnUiThread(() -> { diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index 8f91ffdc1..db05cc8bf 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -1,8 +1,10 @@ package eu.siacs.conversations.ui; +import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.support.annotation.StringRes; import android.util.Log; @@ -26,6 +28,8 @@ import eu.siacs.conversations.utils.PhoneHelper; public class PublishProfilePictureActivity extends XmppActivity implements XmppConnectionService.OnAccountUpdate, OnAvatarPublication { + public static final int REQUEST_CHOOSE_PICTURE = 0x1337; + private ImageView avatar; private TextView hintOrWarning; private TextView secondaryHint; @@ -106,7 +110,7 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC } finish(); }); - this.avatar.setOnClickListener(v -> chooseAvatar()); + this.avatar.setOnClickListener(v -> chooseAvatar(this)); this.defaultUri = PhoneHelper.getProfilePictureUri(getApplicationContext()); if (savedInstanceState != null) { this.avatarUri = savedInstanceState.getParcelable("uri"); @@ -139,15 +143,28 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show(); } } + } else if (requestCode == REQUEST_CHOOSE_PICTURE) { + if (resultCode == RESULT_OK) { + cropUri(this, data.getData()); + } } } - private void chooseAvatar() { - CropImage.activity() - .setOutputCompressFormat(Bitmap.CompressFormat.PNG) - .setAspectRatio(1, 1) - .setMinCropResultSize(Config.AVATAR_SIZE, Config.AVATAR_SIZE) - .start(this); + public static void chooseAvatar(final Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("image/*"); + activity.startActivityForResult( + Intent.createChooser(intent, activity.getString(R.string.attach_choose_picture)), + REQUEST_CHOOSE_PICTURE + ); + } else { + CropImage.activity() + .setOutputCompressFormat(Bitmap.CompressFormat.PNG) + .setAspectRatio(1, 1) + .setMinCropResultSize(Config.AVATAR_SIZE, Config.AVATAR_SIZE) + .start(activity); + } } @Override @@ -181,10 +198,7 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC final Uri uri = intent != null ? intent.getData() : null; if (uri != null && handledExternalUri.compareAndSet(false,true)) { - CropImage.activity(uri).setOutputCompressFormat(Bitmap.CompressFormat.PNG) - .setAspectRatio(1, 1) - .setMinCropResultSize(Config.AVATAR_SIZE, Config.AVATAR_SIZE) - .start(this); + cropUri(this, uri); return; } @@ -194,6 +208,13 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC configureActionBar(getSupportActionBar(), !this.mInitialAccountSetup && !handledExternalUri.get()); } + public static void cropUri(final Activity activity, final Uri uri) { + CropImage.activity(uri).setOutputCompressFormat(Bitmap.CompressFormat.PNG) + .setAspectRatio(1, 1) + .setMinCropResultSize(Config.AVATAR_SIZE, Config.AVATAR_SIZE) + .start(activity); + } + protected void loadImageIntoPreview(Uri uri) { Bitmap bm = null; From 788b0f7f2de48aa802c4ae50066ee1a620843279 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 7 Mar 2020 18:33:22 +0100 Subject: [PATCH 08/14] momentarily go back to 16 byte IVs The Crypto provider used from Android P onwards (conscrypt) has a weird bug that when 12 bytes IVs are used it will decrypt or encrypt the entire file in RAM instead of streaming it. That will cause OOM for 'larger' files on http upload. (both downloads and uploads are effected) It is currently unclear why this is happening and why Conscrypt is put into a different mode. We are only observing that Android versions below P are fine and using 16 bytes is fine on all Android versions. --- src/main/java/eu/siacs/conversations/Config.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 294e62539..e131a4a32 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -100,7 +100,7 @@ public final class Config { public static final boolean REMOVE_BROKEN_DEVICES = false; public static final boolean OMEMO_PADDING = false; public static final boolean PUT_AUTH_TAG_INTO_KEY = true; - public static final boolean TWELVE_BYTE_IV = true; + public static final boolean TWELVE_BYTE_IV = false; public static final boolean USE_BOOKMARKS2 = false; From 3be7c3bca2a64bb245e5824be7397212b2fcd49e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 7 Mar 2020 18:57:24 +0100 Subject: [PATCH 09/14] pulled translations from transifex --- src/conversations/res/values-gl/strings.xml | 6 +-- src/main/res/values-hu/strings.xml | 2 + src/main/res/values-it/strings.xml | 1 + src/main/res/values-pl/strings.xml | 1 + src/main/res/values-sv/strings.xml | 53 +++++++++++++++++++++ src/quicksy/res/values-gl/strings.xml | 28 +++++------ 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/conversations/res/values-gl/strings.xml b/src/conversations/res/values-gl/strings.xml index 932e7f9c1..4a889ed51 100644 --- a/src/conversations/res/values-gl/strings.xml +++ b/src/conversations/res/values-gl/strings.xml @@ -1,10 +1,10 @@ - Escolla o seu provedor XMPP + Escolle o teu provedor XMPP Utilizar conversations.im Crear nova conta - Xa posúe unha conta XMPP? Este pode ser o caso se xa está a utilizar outro cliente XMPP ou utilizou Conversations previamente. Se non é así pode crear unha nova conta agora mesmo.\nTruco: Algúns provedores de correo tamén proporcionan contas XMPP. - XMPP é unha rede de mensaxería independente do provedor. Pode utilizar este cliente con calquer provedor XMPP da súa elección.\nMais para a súa conveniencia fixemos que fose doado crear unha conta en conversations.im¹; un provedor especialmente axeitado para utilizar con Conversations. + Xa posúes unha conta XMPP? Este pode ser o caso se xa estás a utilizar outro cliente XMPP ou utilizaches Conversations previamente. Se non é así podes crear unha nova conta agora mesmo.\nTruco: Algúns provedores de correo tamén proporcionan contas XMPP. + XMPP é unha rede de mensaxería independente do provedor. Podes utilizar este cliente con calquera provedor XMPP da túa elección.\nMais para a tua conveniencia fixemos que fose doado crear unha conta en conversations.im¹; un provedor especialmente axeitado para utilizar con Conversations. Convidáronte a %1$s. Guiarémoste no proceso para crear unha conta.\nAo escoller %1$s como provedor poderás comunicarte con usuarias de outros provedores cando lles deas o teu enderezo XMPP completo. Convidáronte a %1$s. Escollemos un nome de usuaria por ti. Guiarémoste no proceso de crear unha conta.\nPoderás comunicarte con usuarias de outros provedores cando lles digas o teu enderezo XMPP completo. O convite do teu servidor diff --git a/src/main/res/values-hu/strings.xml b/src/main/res/values-hu/strings.xml index bd4f0e3b3..d22157e4f 100644 --- a/src/main/res/values-hu/strings.xml +++ b/src/main/res/values-hu/strings.xml @@ -292,6 +292,7 @@ A csoportos csevegés le lett állítva Többé már nincs ebben a csoportos csevegésben használt fiók: %s + kiszolgálva itt: %s %s ellenőrzése a HTTP gépen Nincs kapcsolódva. Próbálja meg később újra %s méretének ellenőrzése @@ -556,6 +557,7 @@ Adatvédelem Téma Színpaletta kiválasztása + Automatikus Világos téma Sötét téma Zöld háttér diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index 82343123e..115a22285 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -292,6 +292,7 @@ La chat di gruppo è stata chiusa Non sei più in questa chat di gruppo usando l’account %s + ospitato su %s Controllo %s su host HTTP Non sei connesso. Riprova più tardi Controlla dimensione %s diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index a8ed931ae..c20fff766 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -292,6 +292,7 @@ Konferencja została zamknięta Nie uczestniczysz już w tej konferencji używając konta %s + udostępnione na %s Sprawdzanie %s na hoście HTTP Brak połączenia. Spróbuj ponownie później Sprawdź rozmiar %s diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index d9cf1e430..91ad60332 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -151,6 +151,7 @@ Användarnamn används redan Registrering klar Servern stödjer inte registrering + TLS-förhandling misslyckades Kränkning av policy Inkompatibel server Strömningsfel @@ -322,6 +323,7 @@ Regenerera OMEMO-nyckel Rensa enheter Är du säker på att du vill rensa alla andra enheter från OMEMO-annonsering? Nästa gång dina enheter ansluter kommer de att återannonsera sig, men de kanske inte tar emot enheter under tiden. + Något gick fel Hämtar historik från server Ingen mer historik på server Uppdaterar… @@ -350,6 +352,7 @@ Du deltar ej Aldrig Tills vidare + Läsmarkera Input Skicka med enter Använd enter-knappen för att skicka meddelande @@ -493,6 +496,7 @@ Privatliv Tema Välj färgschema + Automatisk Ljust tema Mörkt tema Grön bakgrund @@ -545,6 +549,8 @@ Jag följde denna länk från en trovärdig källa Du håller på att verifiera OMEMO-nyckeln för %1$s efter att du följt en länk. Detta är endast säkert om du följde länken från en trovärdig källa där endast %2$s kan ha publiserat denna länk. Verifiera OMEMO-nycklar + Visa inaktiva + Dölj inaktiva Lita ej på enhet Är du säker på att du vill ta bort verifieringen av denna enhet?\nDenna enhet och meddelanden som kommer från enheten kommer att markeras som ej pålitliga. @@ -588,27 +594,74 @@ Sessionsfel Idag Igår + Bekräfta värdnamn med DNSSEC Certifikatet innehåller ej en XMPP-adress Spela in video Meddelande Godkänn okänt certifikat? + Servercertifikatet är inte signerat av en känd certifikatutfärdare. + Vill du ansluta ändå? + Certifikatdetaljer: Utkast: + Skapa genväg + Liten + Mellan + Stor + Kopiera plats + Dela plats Dela plats Visa plats Dela + Var god dröj... + Conversations behöver tillgång till mikrofonen + GIF Kopiera XMPP-adress + Smeknamn + Namn + Att ange ett namn är valfritt Gruppchattens namn + Kan inte spara inspelning Deltagare + Mellan (360p) + Hög (720p) Välj ett land telefonnummer Bekräfta ditt telefonnummer + Ja + Nej + Bekräftar... + Okänt nätverksfel. + För många försök + Du använder en föråldrad version av denna app. + Ditt namn + Skriv in ditt namn + Avslå begäran + Installera Orbot + Starta Orbot + e-bok + Öppna med... + Välj konto Skapa gruppchatt Skapa sluten gruppchatt Kanalnamn + XMPP-adress Vänligen ange ett namn på kanalen + Ange en XMPP-adress + Detta är en XMPP-adress. Ange ett namn. Denna kanal finns redan Du har gått med i en befintlig kanal + XMPP-adresser är synliga för administratörer. + XMPP-adresser är synliga för alla. Denna slutna gruppchatt har inga deltagare. + Hantera rättigheter + För stor fil + Bifoga Upptäck kanaler + Jag har redan ett konto + Lägg till befintligt konto + Skapa nytt konto + Detta verkar vara ett domännamn + Lägg till ändå Detta ser ut som en kanaladress + Om diff --git a/src/quicksy/res/values-gl/strings.xml b/src/quicksy/res/values-gl/strings.xml index b1675f6e0..9641086fe 100644 --- a/src/quicksy/res/values-gl/strings.xml +++ b/src/quicksy/res/values-gl/strings.xml @@ -1,26 +1,26 @@ Quicksy fallou - Ao enviar lotes de rexistro está a axudar no desenvolvemento de Quicksy\nAviso: vai utilizar a súa conta XMPP para enviar o rexistro ao equipo de desenvolvemento. - Quicksy utiliza unha app de terceiros chamada OpenKeychain para cifrar e descifrar as mensaxes e xestionar a súas chaves públicas.\n\nOpenKeychain en licenza GPLv3 e está dispoñible en F-Droid e Google Play.\n\n(Por favor, reinicie Quicksy ao rematar). - Quicksy non pode cifrar as súas mensaxes porque os seu contacto non publicou as sua chave pública.\n\nPor favor, solicite ao contacto configure OpenPGP. - Quicksy non pode cifrar as súas mensaxes porque os seus contactos non están a publicar a súa chave pública.\n\nPor favor, pídalle aos seus contactos que configuren OpenPGP. + Ao enviar lotes de rexistro estás a axudar no desenvolvemento de Quicksy\nAviso: vas utilizar a tua conta XMPP para enviar o rexistro ao equipo de desenvolvemento. + Quicksy utiliza unha app de terceiros chamada OpenKeychain para cifrar e descifrar as mensaxes e xestionar a tuas chaves públicas.\n\nOpenKeychain ten licenza GPLv3 e está dispoñible en F-Droid e Google Play.\n\n(Por favor, reinicia Quicksy ao rematar). + Quicksy non pode cifrar as tuas mensaxes porque o teu contacto non publicou as sua chave pública.\n\nPor favor, solicita ao contacto que configure OpenPGP. + Quicksy non pode cifrar as tuas mensaxes porque os teus contactos non están a publicar a súa chave pública.\n\nPor favor, pídelle aos teus contactos que configuren OpenPGP. O período de tempo que Quicksy permanece acalado tras ver actividade en outro dispositivo - Enviando trazas de rexistro está axudando ao desenvolvemento de Quicksy + Enviando trazas de rexistro estás axudando ao desenvolvemento de Quicksy Quicksy precisa acceso ao almacenamento externo Quicksy precisa acceso a cámara - O seu dispositivo está a realizar optimizacións de batería intensivas con Quicksy que poderían levar a que as notificacións tarden en chegar ou que as mensaxes se perdan.\nRecomendamos desactivalas. - O seu dispositivo está a realizar optimizacións de batería moi fortes con Quicksy que poderían levar a que se retrasen as notificacións ou que se perdan mensaxes.\n\nPediráselle que as desactive. - Permitir a todos os seus contactos saber cando está a utilizar Quicksy - O seu sistema operativo está restrinxindo o acceso a internet en segundo plano para Quicksy. Para recibir notificacións ou novas mensaxes debería permitir a Quicksy acceso non limitado cando se activa o aforro de datos.\nQuicksy esforzarase en aforrar datos cando sexa posible. - O seu dispositivo non soporta a desactivación do aforro de datos para Quicksy. - Para seguir recibindo notificacións, mesmo coa pantalla apagada, precisa engadir a Quicksy na lista de apps protexidas. - Quicksy non pode enviar mensaxes cifradas a %1$s. Esto podería deberse a que o seu contacto utiliza un servidor antigo ou un cliente sen soporte OMEMO. + O teu dispositivo está a realizar optimizacións de batería intensivas con Quicksy que poderían levar a que as notificacións tarden en chegar ou que as mensaxes se perdan.\nRecomendamos desactivalas. + O teu dispositivo está a realizar optimizacións de batería moi fortes con Quicksy que poderían levar a que se retrasen as notificacións ou que se perdan mensaxes.\n\nVaiche solicitar que as desactives. + Permitir a todos os teus contactos saber cando estás a utilizar Quicksy + O teu sistema operativo está restrinxindo o acceso a internet en segundo plano para Quicksy. Para recibir notificacións ou novas mensaxes deberías permitir a Quicksy acceso non limitado cando se activa o aforro de datos.\nQuicksy esforzarase en aforrar datos cando sexa posible. + O teu dispositivo non soporta a desactivación do aforro de datos para Quicksy. + Para seguir recibindo notificacións, mesmo coa pantalla apagada, precisas engadir a Quicksy na lista de apps protexidas. + Quicksy non pode enviar mensaxes cifradas a %1$s. Esto podería deberse a que o teu contacto utiliza un servidor antigo ou un cliente sen soporte OMEMO. Quicksy precisa acceder ao micrófono Esta categoría de notificacións utilízase para mostrar unha notificación permanente que indica que Quicksy está funcionando. Imaxe de perfil Quicksy - Quicksy non está dispoñible no seu país. - Non se puido validar a identidade do servidor. + Quicksy non está dispoñible no teu país. + Non se puido verificar a identidade do servidor. Fallo de seguridade descoñecido. Caducou a conexión mentras conectaba co servidor. From aecb771ab58436c41ced5c613d3feaf789457b41 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 8 Mar 2020 13:13:15 +0100 Subject: [PATCH 10/14] use 16 byte IVs for http upload files larger than 768KiB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ever since Android 9+ switched to Conscrypt we can no longer efficiently encrypt (and decrypt) large files with AES-GCM. We did’t notice this before because when using 16 byte IVs even modern Androids will fall back to bouncy castle. However the 'bug'/'feature' in Conscrypt surfaced when we switched over to 12 byte IVs (which uses Conscrypt on Android 9+) Switching back entirely to 16 byte IVs is undesirable as this would break compatibility with Monal. So we end up with a weird compromise where we use 12 byte for normale plain text OMEMO messages and 'small' files where the inefficiencies aren’t a problem. The result of this commit is that Monal won’t be able to receive our files larger than 768KiB. However the alternative is that Conversations would always OOM when attempting to send larger files (where large depends on the available RAM.) fixes #3653 --- build.gradle | 4 ++-- src/main/java/eu/siacs/conversations/Config.java | 1 - .../crypto/axolotl/AxolotlService.java | 6 +++--- .../crypto/axolotl/XmppAxolotlMessage.java | 11 +++++------ .../conversations/entities/DownloadableFile.java | 4 ++++ .../conversations/http/HttpUploadConnection.java | 13 +++++++++++-- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index ead92e284..f9f73f18f 100644 --- a/build.gradle +++ b/build.gradle @@ -90,8 +90,8 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 28 - versionCode 364 - versionName "2.7.0" + versionCode 365 + versionName "2.7.1" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index e131a4a32..777953735 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -100,7 +100,6 @@ public final class Config { public static final boolean REMOVE_BROKEN_DEVICES = false; public static final boolean OMEMO_PADDING = false; public static final boolean PUT_AUTH_TAG_INTO_KEY = true; - public static final boolean TWELVE_BYTE_IV = false; public static final boolean USE_BOOKMARKS2 = false; diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index e67755586..906080d06 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -1157,7 +1157,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { @Nullable public XmppAxolotlMessage encrypt(Message message) { - final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId()); + final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId(), true); final String content; if (message.hasFileOnRemoteHost()) { content = message.getFileParams().url.toString(); @@ -1201,7 +1201,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { executor.execute(new Runnable() { @Override public void run() { - final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId()); + final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId(), false); if (buildHeader(axolotlMessage, conversation)) { onMessageCreatedCallback.run(axolotlMessage); } else { @@ -1362,7 +1362,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } private void completeSession(XmppAxolotlSession session) { - final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId()); + final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId(), true); axolotlMessage.addDevice(session, true); try { final Jid jid = Jid.of(session.getRemoteAddress().getName()); diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java index 13082deac..e2a9a2da2 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java @@ -85,11 +85,11 @@ public class XmppAxolotlMessage { } } - XmppAxolotlMessage(Jid from, int sourceDeviceId) { + XmppAxolotlMessage(Jid from, int sourceDeviceId, final boolean twelveByteIv) { this.from = from; this.sourceDeviceId = sourceDeviceId; this.keys = new ArrayList<>(); - this.iv = generateIv(); + this.iv = generateIv(twelveByteIv); this.innerKey = generateKey(); } @@ -115,14 +115,13 @@ public class XmppAxolotlMessage { generator.init(128); return generator.generateKey().getEncoded(); } catch (NoSuchAlgorithmException e) { - Log.e(Config.LOGTAG, e.getMessage()); - return null; + throw new IllegalStateException(e); } } - private static byte[] generateIv() { + private static byte[] generateIv(final boolean twelveByteIv) { final SecureRandom random = new SecureRandom(); - byte[] iv = new byte[Config.TWELVE_BYTE_IV ? 12 : 16]; + byte[] iv = new byte[twelveByteIv ? 12 : 16]; random.nextBytes(iv); return iv; } diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java index c88af6f95..c0b3512a3 100644 --- a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java +++ b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java @@ -1,7 +1,10 @@ package eu.siacs.conversations.entities; +import android.util.Log; + import java.io.File; +import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.MimeUtils; public class DownloadableFile extends File { @@ -66,6 +69,7 @@ public class DownloadableFile extends File { this.iv = new byte[]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf }; System.arraycopy(keyIvCombo, 0, aeskey, 0, 32); } + Log.d(Config.LOGTAG,"using "+this.iv.length+"-byte IV for file transmission"); } public void setKey(byte[] key) { diff --git a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java index 08fae1bc5..ea893924f 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java @@ -105,11 +105,20 @@ public class HttpUploadConnection implements Transferable { } else { this.mime = this.file.getMimeType(); } + final long originalFileSize = file.getSize(); this.delayed = delay; if (Config.ENCRYPT_ON_HTTP_UPLOADED || message.getEncryption() == Message.ENCRYPTION_AXOLOTL || message.getEncryption() == Message.ENCRYPTION_OTR) { - this.key = new byte[Config.TWELVE_BYTE_IV ? 44 : 48]; + //ok, this is going to sound super crazy but on Android 9+ a 12 byte IV will use the + //internal conscrypt library (provided by the OS) instead of bounce castle, while 16 bytes + //will still 'fallback' to bounce castle even on Android 9+ because conscrypt doesnt + //have support for anything but 12. + //For large files conscrypt has extremely bad performance; so why not always use 16 you ask? + //well the ecosystem was moving and some clients like Monal *only* support 16 + //so the result of this code is that we can only send 'small' files to Monal. + //'small' was relatively arbitrarily choose and correlates to roughly 'small' compressed images + this.key = new byte[originalFileSize <= 786432 ? 44 : 48]; mXmppConnectionService.getRNG().nextBytes(this.key); this.file.setKeyAndIv(this.key); } @@ -128,7 +137,7 @@ public class HttpUploadConnection implements Transferable { md5 = null; } - this.file.setExpectedSize(file.getSize() + (file.getKey() != null ? 16 : 0)); + this.file.setExpectedSize(originalFileSize + (file.getKey() != null ? 16 : 0)); message.resetFileParams(); this.mSlotRequester.request(method, account, file, mime, md5, new SlotRequester.OnSlotRequested() { @Override From 7851174b7780bf2962bc82c9d5f2586dbe433a82 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 8 Mar 2020 21:10:58 +0100 Subject: [PATCH 11/14] modify 'create backup' faq entry --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e935c15c..0bfc8b77c 100644 --- a/README.md +++ b/README.md @@ -291,7 +291,7 @@ and introduce yourself to `iNPUTmice` so he can approve your join request. #### How do I backup / move Conversations to a new device? On the one hand Conversations supports Message Archive Management to keep a server side history of your messages so when migrating to a new device that device can display your entire history. However that does not work if you enable OMEMO due to its forward secrecy. (Read [The State of Mobile XMPP in 2016](https://gultsch.de/xmpp_2016.html) especially the section on encryption.) -As of version 2.4.0 an integrated Backup & Restore function will help with this, go to Settings → Expert settings → Create backup. A notification will pop-up during the creation process that will announce you when it's ready. After the files, one for each account, are created, you can move the **Conversations** folder *(if you want your old media files too)* or only the **Conversations/Backup** folder *(for OMEMO keys and history only)* to your new device (or to a storage place) where a freshly installed Conversations can restore each account. Don't forget to enable the accounts after a succesful restore. +As of version 2.4.0 an integrated Backup & Restore function will help with this, go to Settings and you’ll find a setting called Create backup. A notification will pop-up during the creation process that will announce you when it's ready. After the files, one for each account, are created, you can move the **Conversations** folder *(if you want your old media files too)* or only the **Conversations/Backup** folder *(for OMEMO keys and history only)* to your new device (or to a storage place) where a freshly installed Conversations can restore each account. Don't forget to enable the accounts after a succesful restore. This backup method will include your OMEMO keys. Due to forward secrecy you will not be able to recover messages sent and received between creating the backup and restoring it. If you have a server side archive (MAM) those messages will be retrieved but displayed as *unable to decrypt*. For technical reasons you might also lose the first message you either sent or receive after the restore; for each conversation you have. This message will then also show up as *unable to decrypt*, but this will automatically recover itself as long as both participants are on Conversations 2.3.11+. Note that this doesn’t happen if you just transfer to a new phone and no messages have been exchanged between backup and restore. From 257de4b51e99edb1f366a4ea672df9d904ab3ddf Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 9 Mar 2020 15:06:21 +0100 Subject: [PATCH 12/14] fixed typo --- .../java/eu/siacs/conversations/http/HttpUploadConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java index ea893924f..3a21b4bad 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java @@ -115,7 +115,7 @@ public class HttpUploadConnection implements Transferable { //will still 'fallback' to bounce castle even on Android 9+ because conscrypt doesnt //have support for anything but 12. //For large files conscrypt has extremely bad performance; so why not always use 16 you ask? - //well the ecosystem was moving and some clients like Monal *only* support 16 + //well the ecosystem was moving and some clients like Monal *only* support 12 //so the result of this code is that we can only send 'small' files to Monal. //'small' was relatively arbitrarily choose and correlates to roughly 'small' compressed images this.key = new byte[originalFileSize <= 786432 ? 44 : 48]; From 00191e2b6055292a871bb3b525d79fdc8e38cb30 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 9 Mar 2020 19:12:30 +0100 Subject: [PATCH 13/14] explicitly use BouncyCastle for file crypto --- build.gradle | 4 +-- .../crypto/axolotl/AxolotlService.java | 6 ++-- .../crypto/axolotl/XmppAxolotlMessage.java | 8 ++--- .../http/HttpUploadConnection.java | 10 +----- .../services/AbstractConnectionManager.java | 33 ++++++++----------- 5 files changed, 24 insertions(+), 37 deletions(-) diff --git a/build.gradle b/build.gradle index f9f73f18f..39bf82793 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,7 @@ dependencies { compatImplementation "com.android.support:support-emoji-appcompat:$supportLibVersion" conversationsFreeCompatImplementation "com.android.support:support-emoji-bundled:$supportLibVersion" quicksyFreeCompatImplementation "com.android.support:support-emoji-bundled:$supportLibVersion" - implementation 'org.bouncycastle:bcmail-jdk15on:1.58' + implementation 'org.bouncycastle:bcmail-jdk15on:1.64' //zxing stopped supporting Java 7 so we have to stick with 3.3.3 //https://github.com/zxing/zxing/issues/1170 implementation 'com.google.zxing:core:3.3.3' @@ -90,7 +90,7 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 28 - versionCode 365 + versionCode 366 versionName "2.7.1" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 906080d06..e67755586 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -1157,7 +1157,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { @Nullable public XmppAxolotlMessage encrypt(Message message) { - final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId(), true); + final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId()); final String content; if (message.hasFileOnRemoteHost()) { content = message.getFileParams().url.toString(); @@ -1201,7 +1201,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { executor.execute(new Runnable() { @Override public void run() { - final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId(), false); + final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId()); if (buildHeader(axolotlMessage, conversation)) { onMessageCreatedCallback.run(axolotlMessage); } else { @@ -1362,7 +1362,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } private void completeSession(XmppAxolotlSession session) { - final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId(), true); + final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().asBareJid(), getOwnDeviceId()); axolotlMessage.addDevice(session, true); try { final Jid jid = Jid.of(session.getRemoteAddress().getName()); diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java index e2a9a2da2..bec0ff9e2 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java @@ -85,11 +85,11 @@ public class XmppAxolotlMessage { } } - XmppAxolotlMessage(Jid from, int sourceDeviceId, final boolean twelveByteIv) { + XmppAxolotlMessage(Jid from, int sourceDeviceId) { this.from = from; this.sourceDeviceId = sourceDeviceId; this.keys = new ArrayList<>(); - this.iv = generateIv(twelveByteIv); + this.iv = generateIv(); this.innerKey = generateKey(); } @@ -119,9 +119,9 @@ public class XmppAxolotlMessage { } } - private static byte[] generateIv(final boolean twelveByteIv) { + private static byte[] generateIv() { final SecureRandom random = new SecureRandom(); - byte[] iv = new byte[twelveByteIv ? 12 : 16]; + final byte[] iv = new byte[12]; random.nextBytes(iv); return iv; } diff --git a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java index 3a21b4bad..430c7532b 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java @@ -110,15 +110,7 @@ public class HttpUploadConnection implements Transferable { if (Config.ENCRYPT_ON_HTTP_UPLOADED || message.getEncryption() == Message.ENCRYPTION_AXOLOTL || message.getEncryption() == Message.ENCRYPTION_OTR) { - //ok, this is going to sound super crazy but on Android 9+ a 12 byte IV will use the - //internal conscrypt library (provided by the OS) instead of bounce castle, while 16 bytes - //will still 'fallback' to bounce castle even on Android 9+ because conscrypt doesnt - //have support for anything but 12. - //For large files conscrypt has extremely bad performance; so why not always use 16 you ask? - //well the ecosystem was moving and some clients like Monal *only* support 12 - //so the result of this code is that we can only send 'small' files to Monal. - //'small' was relatively arbitrarily choose and correlates to roughly 'small' compressed images - this.key = new byte[originalFileSize <= 786432 ? 44 : 48]; + this.key = new byte[44]; mXmppConnectionService.getRNG().nextBytes(this.key); this.file.setKeyAndIv(this.key); } diff --git a/src/main/java/eu/siacs/conversations/services/AbstractConnectionManager.java b/src/main/java/eu/siacs/conversations/services/AbstractConnectionManager.java index 81f3f80bc..98721aaf4 100644 --- a/src/main/java/eu/siacs/conversations/services/AbstractConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/services/AbstractConnectionManager.java @@ -5,6 +5,14 @@ import android.os.PowerManager; import android.os.SystemClock; import android.util.Log; +import org.bouncycastle.crypto.engines.AESEngine; +import org.bouncycastle.crypto.io.CipherInputStream; +import org.bouncycastle.crypto.io.CipherOutputStream; +import org.bouncycastle.crypto.modes.AEADBlockCipher; +import org.bouncycastle.crypto.modes.GCMBlockCipher; +import org.bouncycastle.crypto.params.AEADParameters; +import org.bouncycastle.crypto.params.KeyParameter; + import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; @@ -15,24 +23,15 @@ import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.util.concurrent.atomic.AtomicLong; -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.CipherOutputStream; import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.utils.Compatibility; -import eu.siacs.conversations.utils.CryptoHelper; public class AbstractConnectionManager { - private static final String KEYTYPE = "AES"; - private static final String CIPHERMODE = "AES/GCM/NoPadding"; - private static final String PROVIDER = "BC"; private static final int UI_REFRESH_THRESHOLD = 250; private static final AtomicLong LAST_UI_UPDATE_CALL = new AtomicLong(0); protected XmppConnectionService mXmppConnectionService; @@ -43,10 +42,8 @@ public class AbstractConnectionManager { public static InputStream upgrade(DownloadableFile file, InputStream is) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, NoSuchProviderException { if (file.getKey() != null && file.getIv() != null) { - final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER); - SecretKeySpec keySpec = new SecretKeySpec(file.getKey(), KEYTYPE); - IvParameterSpec ivSpec = new IvParameterSpec(file.getIv()); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine()); + cipher.init(true, new AEADParameters(new KeyParameter(file.getKey()), 128, file.getIv())); return new CipherInputStream(is, cipher); } else { return is; @@ -61,17 +58,15 @@ public class AbstractConnectionManager { return os; } } catch (FileNotFoundException e) { - Log.d(Config.LOGTAG,"unable to create output stream", e); + Log.d(Config.LOGTAG, "unable to create output stream", e); return null; } try { - final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER); - SecretKeySpec keySpec = new SecretKeySpec(file.getKey(), KEYTYPE); - IvParameterSpec ivSpec = new IvParameterSpec(file.getIv()); - cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); + AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine()); + cipher.init(false, new AEADParameters(new KeyParameter(file.getKey()), 128, file.getIv())); return new CipherOutputStream(os, cipher); } catch (Exception e) { - Log.d(Config.LOGTAG,"unable to create cipher output stream", e); + Log.d(Config.LOGTAG, "unable to create cipher output stream", e); return null; } } From 36de53cdec46dba207187139aab8efccaa08f8dd Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 10 Mar 2020 11:54:11 +0100 Subject: [PATCH 14/14] version bump to 2.7.1 + changelog --- CHANGELOG.md | 5 +++++ build.gradle | 2 +- fastlane/metadata/android/en-US/changelogs/367.txt | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/367.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 14dbf7755..091e36daf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +### Version 2.7.1 + +* Fix avatar selection on some Android 10 devices +* Fix file transfer for larger files + ### Version 2.7.0 * Provide PDF preview on Android 5+ diff --git a/build.gradle b/build.gradle index 39bf82793..cd378aa9e 100644 --- a/build.gradle +++ b/build.gradle @@ -90,7 +90,7 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 28 - versionCode 366 + versionCode 367 versionName "2.7.1" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" diff --git a/fastlane/metadata/android/en-US/changelogs/367.txt b/fastlane/metadata/android/en-US/changelogs/367.txt new file mode 100644 index 000000000..2f42bd95f --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/367.txt @@ -0,0 +1,2 @@ +* Fix avatar selection on some Android 10 devices +* Fix file transfer for larger files