From 8aa185070bf16fae370e3c7cac17bbcc4d9f5852 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Fri, 15 Mar 2019 15:21:53 -0700 Subject: [PATCH] Update libsignalservice to 2.13.0 - Eliminate the explicit spongycastle dependency. All access to primitives is done through the JCE interfaces now, which allows us to use a secure native-backed provider like conscrypt. - Use conscrypt for our default security provider. This gives us fast TLS 1.2 and 1.3 support on all devices, even before they had platform support (like 4.4). - Update minSdk to 18. Unfortunately the JCE interfaces for GCM primitives are JDK 7+ (!) only, which became supported by Android at 18. --- build.gradle | 23 +- proguard-spongycastle.pro | 26 -- .../securesms/ApplicationContext.java | 11 +- .../attachments/AttachmentServer.java | 6 +- .../securesms/crypto/PRNGFixes.java | 346 ------------------ .../securesms/jobs/RetrieveProfileJob.java | 3 +- 6 files changed, 22 insertions(+), 393 deletions(-) delete mode 100644 proguard-spongycastle.pro delete mode 100644 src/org/thoughtcrime/securesms/crypto/PRNGFixes.java diff --git a/build.gradle b/build.gradle index afcc6aa869..08c9802052 100644 --- a/build.gradle +++ b/build.gradle @@ -85,7 +85,9 @@ dependencies { compile 'com.google.android.exoplayer:exoplayer-core:2.9.1' compile 'com.google.android.exoplayer:exoplayer-ui:2.9.1' - compile 'org.whispersystems:signal-service-android:2.12.8' + compile 'org.conscrypt:conscrypt-android:2.0.0' + + compile 'org.whispersystems:signal-service-android:2.13.0' compile 'org.whispersystems:webrtc-android:M73-S1' compile "me.leolin:ShortcutBadger:1.1.16" @@ -186,7 +188,8 @@ dependencyVerification { 'com.google.android.gms:play-services-auth:aec9e1c584d442cb9f59481a50b2c66dc191872607c04d97ecb82dd0eb5149ec', 'com.google.android.exoplayer:exoplayer-ui:7a942afcc402ff01e9bf48e8d3942850986710f06562d50a1408aaf04a683151', 'com.google.android.exoplayer:exoplayer-core:b6ab34abac36bc2bc6934b7a50008162feca2c0fde91aaf1e8c1c22f2c16e2c0', - 'org.whispersystems:signal-service-android:68a349a9e05089f33ab5a9b9fc330526f59d31e8385ff9f5b70bc4a88bd0e297', + 'org.conscrypt:conscrypt-android:400ca559a49b860a82862b22cee0e3110764bdcf7ee7c79e7479895c25cdfc09', + 'org.whispersystems:signal-service-android:2268f5c13d74a9b8fc582e71f0e5b3041659b4d2597e4e3c47b410dd4ef7c1dc', 'org.whispersystems:webrtc-android:1ae3716728f2581724f982f5b4ded92d7aa33edf19d0daa35529d9529f8eb3a2', 'me.leolin:ShortcutBadger:e3cb3e7625892129b0c92dd5e4bc649faffdd526d5af26d9c45ee31ff8851774', 'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb', @@ -259,7 +262,7 @@ dependencyVerification { 'com.android.support.constraint:constraint-layout-solver:2cafbe356f71c208013d021f32943904798cd6459e5107f9fe27000eb5bc2aef', 'com.google.guava:listenablefuture:e4ad7607e5c0477c6f890ef26a49cb8d1bb4dffb650bab4502afee64644e3069', 'org.signal:signal-metadata-android:d9d798aab7ee7200373ecff8718baf8aaeb632c123604e8a41b7b4c0c97eeee1', - 'org.whispersystems:signal-service-java:fde1a008fe42ebbf1cd35018b363135cd8fec9e690304f8917b5ffb7080fa2a5', + 'org.whispersystems:signal-service-java:0af556834936d6fa06c6cb9ec58a3049320475df1e7882aef24f3488d967e154', 'com.github.bumptech.glide:disklrucache:c1b1b6f5bbd01e2fcdc9d7f60913c8d338bdb65ed4a93bfa02b56f19daaade4b', 'com.github.bumptech.glide:annotations:bede99ef9f71517a4274bac18fd3e483e9f2b6108d7d6fe8f4949be4aa4d9512', 'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a', @@ -271,21 +274,19 @@ dependencyVerification { 'org.signal:signal-metadata-java:af1d0dd766b1e301ed1c44e65161084cf03e2587fe97fdd29ecbea58c6aa6930', 'org.whispersystems:signal-protocol-java:b08207f7e1847228f2a1f0d49e113f93c96c6ed8490be14edddd4be55b2a4a4e', 'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74', - 'com.googlecode.libphonenumber:libphonenumber:183392c0565be16d3f6f86680b4106bbde6fe31a402ad21bf9823d938c0c8706', - 'com.fasterxml.jackson.core:jackson-databind:0fb4e079c118e752cc94c15ad22e6782b0dfc5dc09145f4813fb39d82e686047', - 'com.squareup.okhttp3:okhttp:7265adbd6f028aade307f58569d814835cd02bc9beffb70c25f72c9de50d61c4', - 'com.madgag.spongycastle:pkix:0d9cca6991f68eb373cfad309d5268c9fc38db5efb5fe00dcccf5c973af1eca1', - 'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a', + 'com.googlecode.libphonenumber:libphonenumber:dbf4bf566d17a60044c19e282a619684e4b4abb0f9f9f24f843c55d19826ab5e', + 'com.fasterxml.jackson.core:jackson-databind:2351c3eba73a545db9079f5d6d768347ad72666537362c8220fe3e950a55a864', + 'com.squareup.okhttp3:okhttp:07c3d82ca7eaf4722f00b2da807dc7860f6169ae60cfedcf5d40218f90880a46', 'org.threeten:threetenbp:f4c23ffaaed717c3b99c003e0ee02d6d66377fd47d866fec7d971bd8644fc1a7', 'org.whispersystems:curve25519-android:82595394422b957d4a5b5f1b27b75ba25cf6dc4db4d312418ca38cd6fff279ca', 'com.fasterxml.jackson.core:jackson-annotations:45d32ac61ef8a744b464c54c2b3414be571016dd46bfc2bec226761cf7ae457a', - 'com.fasterxml.jackson.core:jackson-core:a2bebaa325ad25455b02149c67e6052367a7d7fc1ce77de000eed284a5214eac', - 'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850', - 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', + 'com.fasterxml.jackson.core:jackson-core:d934dab0bd48994eeea2c1b493cb547158a338a80b58c4fbc8e85fb0905e105f', + 'com.squareup.okio:okio:693fa319a7e8843300602b204023b7674f106ebcb577f2dd5807212b66118bd2', 'org.whispersystems:curve25519-java:7dd659d8822c06c3aea1a47f18fac9e5761e29cab8100030b877db445005f03e', ] } + android { flavorDimensions "none" compileSdkVersion 28 diff --git a/proguard-spongycastle.pro b/proguard-spongycastle.pro deleted file mode 100644 index 26c6842672..0000000000 --- a/proguard-spongycastle.pro +++ /dev/null @@ -1,26 +0,0 @@ --keep class org.spongycastle.crypto.* {*;} --keep class org.spongycastle.crypto.agreement.** {*;} --keep class org.spongycastle.crypto.digests.* {*;} --keep class org.spongycastle.crypto.ec.* {*;} --keep class org.spongycastle.crypto.encodings.* {*;} --keep class org.spongycastle.crypto.engines.* {*;} --keep class org.spongycastle.crypto.macs.* {*;} --keep class org.spongycastle.crypto.modes.* {*;} --keep class org.spongycastle.crypto.paddings.* {*;} --keep class org.spongycastle.crypto.params.* {*;} --keep class org.spongycastle.crypto.prng.* {*;} --keep class org.spongycastle.crypto.signers.* {*;} - --keep class org.spongycastle.jcajce.provider.asymmetric.* {*;} --keep class org.spongycastle.jcajce.provider.asymmetric.util.* {*;} --keep class org.spongycastle.jcajce.provider.asymmetric.dh.* {*;} --keep class org.spongycastle.jcajce.provider.asymmetric.ec.* {*;} - --keep class org.spongycastle.jcajce.provider.digest.** {*;} --keep class org.spongycastle.jcajce.provider.keystore.** {*;} --keep class org.spongycastle.jcajce.provider.symmetric.** {*;} --keep class org.spongycastle.jcajce.spec.* {*;} --keep class org.spongycastle.jce.** {*;} - - --dontwarn javax.naming.** \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 68f5e89b0e..d3a3cfb2cb 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -28,11 +28,9 @@ import android.support.multidex.MultiDexApplication; import com.google.android.gms.security.ProviderInstaller; +import org.conscrypt.Conscrypt; import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusSender; -import org.thoughtcrime.securesms.crypto.PRNGFixes; -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule; import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule; @@ -66,6 +64,7 @@ import org.webrtc.voiceengine.WebRtcAudioManager; import org.webrtc.voiceengine.WebRtcAudioUtils; import org.whispersystems.libsignal.logging.SignalProtocolLoggerProvider; +import java.security.Security; import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -104,7 +103,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate()"); - initializeRandomNumberFix(); + initializeSecurityProvider(); initializeLogging(); initializeCrashHandling(); initializeDependencyInjection(); @@ -171,8 +170,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc return persistentLogger; } - private void initializeRandomNumberFix() { - PRNGFixes.apply(); + private void initializeSecurityProvider() { + Security.insertProviderAt(Conscrypt.newProvider(), 1); } private void initializeLogging() { diff --git a/src/org/thoughtcrime/securesms/attachments/AttachmentServer.java b/src/org/thoughtcrime/securesms/attachments/AttachmentServer.java index e44e7d6ab2..bc68557175 100644 --- a/src/org/thoughtcrime/securesms/attachments/AttachmentServer.java +++ b/src/org/thoughtcrime/securesms/attachments/AttachmentServer.java @@ -4,10 +4,10 @@ package org.thoughtcrime.securesms.attachments; import android.content.Context; import android.net.Uri; import android.support.annotation.NonNull; -import org.thoughtcrime.securesms.logging.Log; -import org.spongycastle.util.encoders.Hex; +import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.mms.PartAuthority; +import org.thoughtcrime.securesms.util.Hex; import org.thoughtcrime.securesms.util.Util; import java.io.BufferedOutputStream; @@ -52,7 +52,7 @@ public class AttachmentServer implements Runnable { this.attachment = attachment; this.socket = new ServerSocket(0, 0, InetAddress.getByAddress(new byte[]{127, 0, 0, 1})); this.port = socket.getLocalPort(); - this.auth = new String(Hex.encode(Util.getSecretBytes(16))); + this.auth = Hex.toStringCondensed(Util.getSecretBytes(16)); this.socket.setSoTimeout(5000); } catch (UnknownHostException e) { diff --git a/src/org/thoughtcrime/securesms/crypto/PRNGFixes.java b/src/org/thoughtcrime/securesms/crypto/PRNGFixes.java deleted file mode 100644 index 9bcb7084e4..0000000000 --- a/src/org/thoughtcrime/securesms/crypto/PRNGFixes.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * This software is provided 'as-is', without any express or implied - * warranty. In no event will Google be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, as long as the origin is not misrepresented. - */ - -package org.thoughtcrime.securesms.crypto; - -import android.os.Build; -import android.os.Process; -import org.thoughtcrime.securesms.logging.Log; - -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.SecureRandom; -import java.security.SecureRandomSpi; -import java.security.Security; - -/** - * This class is taken directly from the Android blog post announcing this bug: - * http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html - * - * Since I still don't know exactly what the source of this bug was, I'm using - * this class verbatim under the assumption that the Android team knows what - * they're doing. Although, at this point, that is perhaps a foolish assumption. - */ - -/** - * Fixes for the output of the default PRNG having low entropy. - * - * The fixes need to be applied via {@link #apply()} before any use of Java - * Cryptography Architecture primitives. A good place to invoke them is in the - * application's {@code onCreate}. - */ -public final class PRNGFixes { - - private static final String TAG = PRNGFixes.class.getSimpleName(); - - private static final int VERSION_CODE_JELLY_BEAN = 16; - private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18; - private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL = - getBuildFingerprintAndDeviceSerial(); - - /** Hidden constructor to prevent instantiation. */ - private PRNGFixes() {} - - /** - * Applies all fixes. - * - * @throws SecurityException if a fix is needed but could not be applied. - */ - public static void apply() { - applyOpenSSLFix(); - installLinuxPRNGSecureRandom(); - } - - /** - * Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the - * fix is not needed. - * - * @throws SecurityException if the fix is needed but could not be applied. - */ - private static void applyOpenSSLFix() throws SecurityException { - if ((Build.VERSION.SDK_INT < VERSION_CODE_JELLY_BEAN) - || (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2)) { - // No need to apply the fix - return; - } - - try { - // Mix in the device- and invocation-specific seed. - Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto") - .getMethod("RAND_seed", byte[].class) - .invoke(null, generateSeed()); - - // Mix output of Linux PRNG into OpenSSL's PRNG - int bytesRead = (Integer) Class.forName( - "org.apache.harmony.xnet.provider.jsse.NativeCrypto") - .getMethod("RAND_load_file", String.class, long.class) - .invoke(null, "/dev/urandom", 1024); - if (bytesRead != 1024) { - throw new IOException( - "Unexpected number of bytes read from Linux PRNG: " - + bytesRead); - } - } catch (Exception e) { - throw new SecurityException("Failed to seed OpenSSL PRNG", e); - } - } - - /** - * Installs a Linux PRNG-backed {@code SecureRandom} implementation as the - * default. Does nothing if the implementation is already the default or if - * there is not need to install the implementation. - * - * @throws SecurityException if the fix is needed but could not be applied. - */ - private static void installLinuxPRNGSecureRandom() - throws SecurityException { - if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) { - // No need to apply the fix - return; - } - - // Install a Linux PRNG-based SecureRandom implementation as the - // default, if not yet installed. - Provider[] secureRandomProviders = - Security.getProviders("SecureRandom.SHA1PRNG"); - if ((secureRandomProviders == null) - || (secureRandomProviders.length < 1) - || (!LinuxPRNGSecureRandomProvider.class.equals( - secureRandomProviders[0].getClass()))) { - Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1); - } - - // Assert that new SecureRandom() and - // SecureRandom.getInstance("SHA1PRNG") return a SecureRandom backed - // by the Linux PRNG-based SecureRandom implementation. - SecureRandom rng1 = new SecureRandom(); - if (!LinuxPRNGSecureRandomProvider.class.equals( - rng1.getProvider().getClass())) { - throw new SecurityException( - "new SecureRandom() backed by wrong Provider: " - + rng1.getProvider().getClass()); - } - - SecureRandom rng2; - try { - rng2 = SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - throw new SecurityException("SHA1PRNG not available", e); - } - if (!LinuxPRNGSecureRandomProvider.class.equals( - rng2.getProvider().getClass())) { - throw new SecurityException( - "SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong" - + " Provider: " + rng2.getProvider().getClass()); - } - } - - /** - * {@code Provider} of {@code SecureRandom} engines which pass through - * all requests to the Linux PRNG. - */ - private static class LinuxPRNGSecureRandomProvider extends Provider { - - public LinuxPRNGSecureRandomProvider() { - super("LinuxPRNG", - 1.0, - "A Linux-specific random number provider that uses" - + " /dev/urandom"); - // Although /dev/urandom is not a SHA-1 PRNG, some apps - // explicitly request a SHA1PRNG SecureRandom and we thus need to - // prevent them from getting the default implementation whose output - // may have low entropy. - put("SecureRandom.SHA1PRNG", LinuxPRNGSecureRandom.class.getName()); - put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); - } - } - - /** - * {@link SecureRandomSpi} which passes all requests to the Linux PRNG - * ({@code /dev/urandom}). - */ - public static class LinuxPRNGSecureRandom extends SecureRandomSpi { - - /* - * IMPLEMENTATION NOTE: Requests to generate bytes and to mix in a seed - * are passed through to the Linux PRNG (/dev/urandom). Instances of - * this class seed themselves by mixing in the current time, PID, UID, - * build fingerprint, and hardware serial number (where available) into - * Linux PRNG. - * - * Concurrency: Read requests to the underlying Linux PRNG are - * serialized (on sLock) to ensure that multiple threads do not get - * duplicated PRNG output. - */ - - private static final File URANDOM_FILE = new File("/dev/urandom"); - - private static final Object sLock = new Object(); - - /** - * Input stream for reading from Linux PRNG or {@code null} if not yet - * opened. - * - * @GuardedBy("sLock") - */ - private static DataInputStream sUrandomIn; - - /** - * Output stream for writing to Linux PRNG or {@code null} if not yet - * opened. - * - * @GuardedBy("sLock") - */ - private static OutputStream sUrandomOut; - - /** - * Whether this engine instance has been seeded. This is needed because - * each instance needs to seed itself if the client does not explicitly - * seed it. - */ - private boolean mSeeded; - - @Override - protected void engineSetSeed(byte[] bytes) { - try { - OutputStream out; - synchronized (sLock) { - out = getUrandomOutputStream(); - } - out.write(bytes); - out.flush(); - } catch (IOException e) { - // On a small fraction of devices /dev/urandom is not writable. - // Log and ignore. - Log.w(TAG, "Failed to mix seed into " + URANDOM_FILE); - } finally { - mSeeded = true; - } - } - - @Override - protected void engineNextBytes(byte[] bytes) { - if (!mSeeded) { - // Mix in the device- and invocation-specific seed. - engineSetSeed(generateSeed()); - } - - try { - DataInputStream in; - synchronized (sLock) { - in = getUrandomInputStream(); - } - synchronized (in) { - in.readFully(bytes); - } - } catch (IOException e) { - throw new SecurityException( - "Failed to read from " + URANDOM_FILE, e); - } - } - - @Override - protected byte[] engineGenerateSeed(int size) { - byte[] seed = new byte[size]; - engineNextBytes(seed); - return seed; - } - - private DataInputStream getUrandomInputStream() { - synchronized (sLock) { - if (sUrandomIn == null) { - // NOTE: Consider inserting a BufferedInputStream between - // DataInputStream and FileInputStream if you need higher - // PRNG output performance and can live with future PRNG - // output being pulled into this process prematurely. - try { - sUrandomIn = new DataInputStream( - new FileInputStream(URANDOM_FILE)); - } catch (IOException e) { - throw new SecurityException("Failed to open " - + URANDOM_FILE + " for reading", e); - } - } - return sUrandomIn; - } - } - - private OutputStream getUrandomOutputStream() throws IOException { - synchronized (sLock) { - if (sUrandomOut == null) { - sUrandomOut = new FileOutputStream(URANDOM_FILE); - } - return sUrandomOut; - } - } - } - - /** - * Generates a device- and invocation-specific seed to be mixed into the - * Linux PRNG. - */ - private static byte[] generateSeed() { - try { - ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream(); - DataOutputStream seedBufferOut = - new DataOutputStream(seedBuffer); - seedBufferOut.writeLong(System.currentTimeMillis()); - seedBufferOut.writeLong(System.nanoTime()); - seedBufferOut.writeInt(Process.myPid()); - seedBufferOut.writeInt(Process.myUid()); - seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL); - seedBufferOut.close(); - return seedBuffer.toByteArray(); - } catch (IOException e) { - throw new SecurityException("Failed to generate seed", e); - } - } - - /** - * Gets the hardware serial number of this device. - * - * @return serial number or {@code null} if not available. - */ - private static String getDeviceSerialNumber() { - // We're using the Reflection API because Build.SERIAL is only available - // since API Level 9 (Gingerbread, Android 2.3). - try { - return (String) Build.class.getField("SERIAL").get(null); - } catch (Exception ignored) { - return null; - } - } - - private static byte[] getBuildFingerprintAndDeviceSerial() { - StringBuilder result = new StringBuilder(); - String fingerprint = Build.FINGERPRINT; - if (fingerprint != null) { - result.append(fingerprint); - } - String serial = getDeviceSerialNumber(); - if (serial != null) { - result.append(serial); - } - try { - return result.toString().getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("UTF-8 encoding not supported"); - } - } -} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java index 73dbd716cd..31f7e77723 100644 --- a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java @@ -25,6 +25,7 @@ import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceMessagePipe; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; +import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException; import org.whispersystems.signalservice.api.crypto.ProfileCipher; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair; @@ -210,7 +211,7 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType { if (!Util.equals(plaintextProfileName, recipient.getProfileName())) { DatabaseFactory.getRecipientDatabase(context).setProfileName(recipient, plaintextProfileName); } - } catch (ProfileCipher.InvalidCiphertextException | IOException e) { + } catch (InvalidCiphertextException | IOException e) { Log.w(TAG, e); } }