Fixes FS#147: Disable OMEMO
This commit is contained in:
parent
c26f907263
commit
5d21abac1d
20 changed files with 1331 additions and 981 deletions
|
@ -14,6 +14,10 @@ public class ConversationsPlusPreferences extends Settings {
|
||||||
private static ConversationsPlusPreferences instance;
|
private static ConversationsPlusPreferences instance;
|
||||||
private final SharedPreferences sharedPreferences;
|
private final SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
|
public static boolean omemoEnabled() {
|
||||||
|
return getBoolean("omemo_enabled", false);
|
||||||
|
}
|
||||||
|
|
||||||
public static String imgTransferFolder() {
|
public static String imgTransferFolder() {
|
||||||
return getString("img_transfer_folder", getString("app_name", "Conversations+"));
|
return getString("img_transfer_folder", getString("app_name", "Conversations+"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package eu.siacs.conversations;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
|
import de.thedevstack.conversationsplus.ConversationsPlusPreferences;
|
||||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
||||||
|
|
||||||
public final class Config {
|
public final class Config {
|
||||||
|
@ -31,7 +32,7 @@ public final class Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean supportOmemo() {
|
public static boolean supportOmemo() {
|
||||||
return (ENCRYPTION_MASK & OMEMO) != 0;
|
return ConversationsPlusPreferences.omemoEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean multipleEncryptionChoices() {
|
public static boolean multipleEncryptionChoices() {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,196 @@
|
||||||
|
package eu.siacs.conversations.crypto.axolotl;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.whispersystems.libaxolotl.AxolotlAddress;
|
||||||
|
import org.whispersystems.libaxolotl.IdentityKey;
|
||||||
|
import org.whispersystems.libaxolotl.state.PreKeyRecord;
|
||||||
|
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.entities.Contact;
|
||||||
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
|
import eu.siacs.conversations.entities.Message;
|
||||||
|
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Axolotl Service Stub implementation to avoid axolotl usage.
|
||||||
|
*/
|
||||||
|
public class AxolotlServiceStub implements AxolotlService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fetchMapHasErrors(Contact contact) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnFingerprint() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<IdentityKey> getKeysWithTrust(XmppAxolotlSession.Trust trust) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<IdentityKey> getKeysWithTrust(XmppAxolotlSession.Trust trust, Contact contact) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getNumTrustedKeys(Contact contact) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getFingerprintsForOwnSessions() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getFingerprintsForContact(Contact contact) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPepBroken() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void regenerateKeys(boolean wipeOther) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOwnDeviceId() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Integer> getOwnDeviceIds() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerDevices(Jid jid, @NonNull Set<Integer> deviceIds) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wipeOtherPepDevices() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void purgeKey(String fingerprint) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishOwnDeviceIdIfNeeded() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishOwnDeviceId(Set<Integer> deviceIds) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishDeviceVerificationAndBundle(SignedPreKeyRecord signedPreKeyRecord, Set<PreKeyRecord> preKeyRecords, boolean announceAfter, boolean wipe) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishBundlesIfNeeded(boolean announce, boolean wipe) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isContactAxolotlCapable(Contact contact) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmppAxolotlSession.Trust getFingerprintTrust(String fingerprint) {
|
||||||
|
return XmppAxolotlSession.Trust.TRUSTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate getFingerprintCertificate(String fingerprint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFingerprintTrust(String fingerprint, XmppAxolotlSession.Trust trust) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<AxolotlAddress> findDevicesWithoutSession(Conversation conversation) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<AxolotlAddress> findDevicesWithoutSession(Jid contactJid) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean createSessionsIfNeeded(Conversation conversation) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean trustedSessionVerified(Conversation conversation) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPendingKeyFetches(Account account, Contact contact) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public XmppAxolotlMessage encrypt(Message message) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preparePayloadMessage(Message message, boolean delay) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepareKeyTransportMessage(Contact contact, OnMessageCreatedCallback onMessageCreatedCallback) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmppAxolotlMessage fetchAxolotlMessageFromCache(Message message) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmppAxolotlMessage.XmppAxolotlPlaintextMessage processReceivingPayloadMessage(XmppAxolotlMessage message) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmppAxolotlMessage.XmppAxolotlKeyTransportMessage processReceivingKeyTransportMessage(XmppAxolotlMessage message) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAdvancedStreamFeaturesAvailable(Account account) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,7 +77,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
||||||
this.localRegistrationId = loadRegistrationId();
|
this.localRegistrationId = loadRegistrationId();
|
||||||
this.currentPreKeyId = loadCurrentPreKeyId();
|
this.currentPreKeyId = loadCurrentPreKeyId();
|
||||||
for (SignedPreKeyRecord record : loadSignedPreKeys()) {
|
for (SignedPreKeyRecord record : loadSignedPreKeys()) {
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Got Axolotl signed prekey record:" + record.getId());
|
Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Got Axolotl signed prekey record:" + record.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
||||||
if (ownKey != null) {
|
if (ownKey != null) {
|
||||||
return ownKey;
|
return ownKey;
|
||||||
} else {
|
} else {
|
||||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Could not retrieve own IdentityKeyPair");
|
Log.i(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Could not retrieve own IdentityKeyPair");
|
||||||
ownKey = generateIdentityKeyPair();
|
ownKey = generateIdentityKeyPair();
|
||||||
mXmppConnectionService.databaseBackend.storeOwnIdentityKeyPair(account, ownKey);
|
mXmppConnectionService.databaseBackend.storeOwnIdentityKeyPair(account, ownKey);
|
||||||
}
|
}
|
||||||
|
@ -112,13 +112,13 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
||||||
if (!regenerate && regIdString != null) {
|
if (!regenerate && regIdString != null) {
|
||||||
reg_id = Integer.valueOf(regIdString);
|
reg_id = Integer.valueOf(regIdString);
|
||||||
} else {
|
} else {
|
||||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Could not retrieve axolotl registration id for account " + account.getJid());
|
Log.i(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Could not retrieve axolotl registration id for account " + account.getJid());
|
||||||
reg_id = generateRegistrationId();
|
reg_id = generateRegistrationId();
|
||||||
boolean success = this.account.setKey(JSONKEY_REGISTRATION_ID, Integer.toString(reg_id));
|
boolean success = this.account.setKey(JSONKEY_REGISTRATION_ID, Integer.toString(reg_id));
|
||||||
if (success) {
|
if (success) {
|
||||||
mXmppConnectionService.databaseBackend.updateAccount(account);
|
mXmppConnectionService.databaseBackend.updateAccount(account);
|
||||||
} else {
|
} else {
|
||||||
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to write new key to the database!");
|
Log.e(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Failed to write new key to the database!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reg_id;
|
return reg_id;
|
||||||
|
@ -130,7 +130,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
||||||
if (regIdString != null) {
|
if (regIdString != null) {
|
||||||
reg_id = Integer.valueOf(regIdString);
|
reg_id = Integer.valueOf(regIdString);
|
||||||
} else {
|
} else {
|
||||||
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Could not retrieve current prekey id for account " + account.getJid());
|
Log.w(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Could not retrieve current prekey id for account " + account.getJid());
|
||||||
reg_id = 0;
|
reg_id = 0;
|
||||||
}
|
}
|
||||||
return reg_id;
|
return reg_id;
|
||||||
|
@ -344,7 +344,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
||||||
if (success) {
|
if (success) {
|
||||||
mXmppConnectionService.databaseBackend.updateAccount(account);
|
mXmppConnectionService.databaseBackend.updateAccount(account);
|
||||||
} else {
|
} else {
|
||||||
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to write new prekey id to the database!");
|
Log.e(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Failed to write new prekey id to the database!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,10 +168,10 @@ public class XmppAxolotlSession {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
PreKeyWhisperMessage message = new PreKeyWhisperMessage(encryptedKey);
|
PreKeyWhisperMessage message = new PreKeyWhisperMessage(encryptedKey);
|
||||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
|
Log.i(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
|
||||||
IdentityKey msgIdentityKey = message.getIdentityKey();
|
IdentityKey msgIdentityKey = message.getIdentityKey();
|
||||||
if (this.identityKey != null && !this.identityKey.equals(msgIdentityKey)) {
|
if (this.identityKey != null && !this.identityKey.equals(msgIdentityKey)) {
|
||||||
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Had session with fingerprint " + this.getFingerprint() + ", received message with fingerprint " + msgIdentityKey.getFingerprint());
|
Log.e(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Had session with fingerprint " + this.getFingerprint() + ", received message with fingerprint " + msgIdentityKey.getFingerprint());
|
||||||
} else {
|
} else {
|
||||||
this.identityKey = msgIdentityKey;
|
this.identityKey = msgIdentityKey;
|
||||||
plaintext = cipher.decrypt(message);
|
plaintext = cipher.decrypt(message);
|
||||||
|
@ -180,14 +180,14 @@ public class XmppAxolotlSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InvalidMessageException | InvalidVersionException e) {
|
} catch (InvalidMessageException | InvalidVersionException e) {
|
||||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "WhisperMessage received");
|
Log.i(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "WhisperMessage received");
|
||||||
WhisperMessage message = new WhisperMessage(encryptedKey);
|
WhisperMessage message = new WhisperMessage(encryptedKey);
|
||||||
plaintext = cipher.decrypt(message);
|
plaintext = cipher.decrypt(message);
|
||||||
} catch (InvalidKeyException | InvalidKeyIdException | UntrustedIdentityException e) {
|
} catch (InvalidKeyException | InvalidKeyIdException | UntrustedIdentityException e) {
|
||||||
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
|
Log.w(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
} catch (LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException e) {
|
} catch (LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException e) {
|
||||||
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
|
Log.w(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plaintext != null) {
|
if (plaintext != null) {
|
||||||
|
|
|
@ -19,11 +19,14 @@ import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
|
import de.thedevstack.conversationsplus.ConversationsPlusPreferences;
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.crypto.OtrService;
|
import eu.siacs.conversations.crypto.OtrService;
|
||||||
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
||||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
|
import eu.siacs.conversations.crypto.axolotl.AxolotlServiceImpl;
|
||||||
|
import eu.siacs.conversations.crypto.axolotl.AxolotlServiceStub;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||||
|
@ -352,10 +355,15 @@ public class Account extends AbstractEntity {
|
||||||
|
|
||||||
public void initAccountServices(final XmppConnectionService context) {
|
public void initAccountServices(final XmppConnectionService context) {
|
||||||
this.mOtrService = new OtrService(context, this);
|
this.mOtrService = new OtrService(context, this);
|
||||||
this.axolotlService = new AxolotlService(this, context);
|
if (ConversationsPlusPreferences.omemoEnabled()) {
|
||||||
if (xmppConnection != null) {
|
this.axolotlService = new AxolotlServiceImpl(this, context);
|
||||||
xmppConnection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService);
|
if (xmppConnection != null) {
|
||||||
}
|
xmppConnection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.axolotlService = new AxolotlServiceStub();
|
||||||
|
}
|
||||||
|
|
||||||
this.pgpDecryptionService = new PgpDecryptionService(context);
|
this.pgpDecryptionService = new PgpDecryptionService(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,8 @@ import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import de.thedevstack.conversationsplus.ConversationsPlusApplication;
|
import de.thedevstack.conversationsplus.ConversationsPlusApplication;
|
||||||
import de.thedevstack.conversationsplus.ConversationsPlusPreferences;
|
|
||||||
import de.tzur.conversations.Settings;
|
import de.tzur.conversations.Settings;
|
||||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
|
||||||
import eu.siacs.conversations.utils.PhoneHelper;
|
|
||||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
|
||||||
|
|
||||||
public abstract class AbstractGenerator {
|
public abstract class AbstractGenerator {
|
||||||
private final String[] FEATURES = {
|
private final String[] FEATURES = {
|
||||||
|
|
|
@ -25,7 +25,6 @@ import eu.siacs.conversations.services.MessageArchiveService;
|
||||||
import eu.siacs.conversations.utils.Xmlns;
|
import eu.siacs.conversations.utils.Xmlns;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.forms.Data;
|
import eu.siacs.conversations.xmpp.forms.Data;
|
||||||
import eu.siacs.conversations.xmpp.forms.Field;
|
|
||||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
|
|
|
@ -157,7 +157,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
||||||
try {
|
try {
|
||||||
return Base64.decode(signedPreKeySignature.getContent(), Base64.DEFAULT);
|
return Base64.decode(signedPreKeySignature.getContent(), Base64.DEFAULT);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(Config.LOGTAG,AxolotlService.LOGPREFIX+" : Invalid base64 in signedPreKeySignature");
|
Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX+" : Invalid base64 in signedPreKeySignature");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
||||||
try {
|
try {
|
||||||
identityKey = new IdentityKey(Base64.decode(identityKeyElement.getContent(), Base64.DEFAULT), 0);
|
identityKey = new IdentityKey(Base64.decode(identityKeyElement.getContent(), Base64.DEFAULT), 0);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(Config.LOGTAG,AxolotlService.LOGPREFIX+" : "+"Invalid identityKey in PEP: "+e.getMessage());
|
Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX+" : "+"Invalid identityKey in PEP: "+e.getMessage());
|
||||||
}
|
}
|
||||||
return identityKey;
|
return identityKey;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
||||||
|
|
||||||
public Pair<X509Certificate[],byte[]> verification(final IqPacket packet) {
|
public Pair<X509Certificate[],byte[]> verification(final IqPacket packet) {
|
||||||
Element item = getItem(packet);
|
Element item = getItem(packet);
|
||||||
Element verification = item != null ? item.findChild("verification",AxolotlService.PEP_PREFIX) : null;
|
Element verification = item != null ? item.findChild("verification", AxolotlService.PEP_PREFIX) : null;
|
||||||
Element chain = verification != null ? verification.findChild("chain") : null;
|
Element chain = verification != null ? verification.findChild("chain") : null;
|
||||||
Element signature = verification != null ? verification.findChild("signature") : null;
|
Element signature = verification != null ? verification.findChild("signature") : null;
|
||||||
if (chain != null && signature != null) {
|
if (chain != null && signature != null) {
|
||||||
|
|
|
@ -10,14 +10,14 @@ import net.java.otr4j.session.SessionStatus;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import de.thedevstack.android.logcat.Logging;
|
import de.thedevstack.android.logcat.Logging;
|
||||||
import de.thedevstack.conversationsplus.ConversationsPlusPreferences;
|
import de.thedevstack.conversationsplus.ConversationsPlusPreferences;
|
||||||
import de.thedevstack.conversationsplus.utils.AvatarUtil;
|
import de.thedevstack.conversationsplus.utils.AvatarUtil;
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
|
||||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
|
import eu.siacs.conversations.crypto.axolotl.AxolotlServiceImpl;
|
||||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
|
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Bookmark;
|
import eu.siacs.conversations.entities.Bookmark;
|
||||||
|
@ -118,7 +118,7 @@ public class MessageParser extends AbstractParser implements
|
||||||
if(plaintextMessage != null) {
|
if(plaintextMessage != null) {
|
||||||
finishedMessage = new Message(conversation, plaintextMessage.getPlaintext(), Message.ENCRYPTION_AXOLOTL, status);
|
finishedMessage = new Message(conversation, plaintextMessage.getPlaintext(), Message.ENCRYPTION_AXOLOTL, status);
|
||||||
finishedMessage.setAxolotlFingerprint(plaintextMessage.getFingerprint());
|
finishedMessage.setAxolotlFingerprint(plaintextMessage.getFingerprint());
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(finishedMessage.getConversation().getAccount())+" Received Message with session fingerprint: "+plaintextMessage.getFingerprint());
|
Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(finishedMessage.getConversation().getAccount())+" Received Message with session fingerprint: "+plaintextMessage.getFingerprint());
|
||||||
}
|
}
|
||||||
|
|
||||||
return finishedMessage;
|
return finishedMessage;
|
||||||
|
@ -211,8 +211,8 @@ public class MessageParser extends AbstractParser implements
|
||||||
mXmppConnectionService.updateConversationUi();
|
mXmppConnectionService.updateConversationUi();
|
||||||
mXmppConnectionService.updateAccountUi();
|
mXmppConnectionService.updateAccountUi();
|
||||||
}
|
}
|
||||||
} else if (AxolotlService.PEP_DEVICE_LIST.equals(node)) {
|
} else if (ConversationsPlusPreferences.omemoEnabled() && AxolotlService.PEP_DEVICE_LIST.equals(node)) {
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Received PEP device list update from "+ from + ", processing...");
|
Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account)+"Received PEP device list update from "+ from + ", processing...");
|
||||||
Element item = items.findChild("item");
|
Element item = items.findChild("item");
|
||||||
Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item);
|
Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item);
|
||||||
AxolotlService axolotlService = account.getAxolotlService();
|
AxolotlService axolotlService = account.getAxolotlService();
|
||||||
|
@ -297,8 +297,6 @@ public class MessageParser extends AbstractParser implements
|
||||||
final String body = packet.getBody();
|
final String body = packet.getBody();
|
||||||
final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user");
|
final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user");
|
||||||
final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted");
|
final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted");
|
||||||
final Element replaceElement = packet.findChild("replace","urn:xmpp:message-correct:0");
|
|
||||||
final String replacementId = replaceElement == null ? null : replaceElement.getAttribute("id");
|
|
||||||
final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX);
|
final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX);
|
||||||
int status;
|
int status;
|
||||||
final Jid counterpart;
|
final Jid counterpart;
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.json.JSONException;
|
||||||
|
|
||||||
import de.thedevstack.android.logcat.Logging;
|
import de.thedevstack.android.logcat.Logging;
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
import eu.siacs.conversations.crypto.axolotl.AxolotlServiceImpl;
|
||||||
import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore;
|
import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore;
|
||||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
@ -940,7 +940,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
try {
|
try {
|
||||||
identityKeyPair = new IdentityKeyPair(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT));
|
identityKeyPair = new IdentityKeyPair(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT));
|
||||||
} catch (InvalidKeyException e) {
|
} catch (InvalidKeyException e) {
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name);
|
Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor.close();
|
cursor.close();
|
||||||
|
@ -965,7 +965,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
try {
|
try {
|
||||||
identityKeys.add(new IdentityKey(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT), 0));
|
identityKeys.add(new IdentityKey(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT), 0));
|
||||||
} catch (InvalidKeyException e) {
|
} catch (InvalidKeyException e) {
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name);
|
Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor.close();
|
cursor.close();
|
||||||
|
@ -1095,7 +1095,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recreateAxolotlDb(SQLiteDatabase db) {
|
public void recreateAxolotlDb(SQLiteDatabase db) {
|
||||||
Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + ">>> (RE)CREATING AXOLOTL DATABASE <<<");
|
Log.d(Config.LOGTAG, AxolotlServiceImpl.LOGPREFIX + " : " + ">>> (RE)CREATING AXOLOTL DATABASE <<<");
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + SQLiteAxolotlStore.SESSION_TABLENAME);
|
db.execSQL("DROP TABLE IF EXISTS " + SQLiteAxolotlStore.SESSION_TABLENAME);
|
||||||
db.execSQL(CREATE_SESSIONS_STATEMENT);
|
db.execSQL(CREATE_SESSIONS_STATEMENT);
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + SQLiteAxolotlStore.PREKEY_TABLENAME);
|
db.execSQL("DROP TABLE IF EXISTS " + SQLiteAxolotlStore.PREKEY_TABLENAME);
|
||||||
|
@ -1108,7 +1108,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
|
|
||||||
public void wipeAxolotlDb(Account account) {
|
public void wipeAxolotlDb(Account account) {
|
||||||
String accountName = account.getUuid();
|
String accountName = account.getUuid();
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + ">>> WIPING AXOLOTL DATABASE FOR ACCOUNT " + accountName + " <<<");
|
Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(account) + ">>> WIPING AXOLOTL DATABASE FOR ACCOUNT " + accountName + " <<<");
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
String[] deleteArgs = {
|
String[] deleteArgs = {
|
||||||
accountName
|
accountName
|
||||||
|
|
|
@ -50,6 +50,7 @@ import de.timroes.android.listview.EnhancedListView;
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
|
import eu.siacs.conversations.crypto.axolotl.AxolotlServiceImpl;
|
||||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Blockable;
|
import eu.siacs.conversations.entities.Blockable;
|
||||||
|
@ -835,7 +836,7 @@ public class ConversationActivity extends XmppActivity
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R.id.encryption_choice_axolotl:
|
case R.id.encryption_choice_axolotl:
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(conversation.getAccount())
|
Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(conversation.getAccount())
|
||||||
+ "Enabled axolotl for Contact " + conversation.getContact().getJid());
|
+ "Enabled axolotl for Contact " + conversation.getContact().getJid());
|
||||||
conversation.setNextEncryption(Message.ENCRYPTION_AXOLOTL);
|
conversation.setNextEncryption(Message.ENCRYPTION_AXOLOTL);
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import android.content.SharedPreferences;
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.CheckBoxPreference;
|
||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceCategory;
|
import android.preference.PreferenceCategory;
|
||||||
|
@ -123,6 +124,12 @@ public class SettingsActivity extends XmppActivity implements
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Avoid appearence of setting to enable or disable omemo in screen
|
||||||
|
Preference omemoEnabledPreference = this.mSettingsFragment.findPreference("omemo_enabled");
|
||||||
|
PreferenceCategory otherExpertSettingsGroup = (PreferenceCategory) this.mSettingsFragment.findPreference("other_expert_settings");
|
||||||
|
if (null != omemoEnabledPreference && null != otherExpertSettingsGroup) {
|
||||||
|
otherExpertSettingsGroup.removePreference(omemoEnabledPreference);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -504,7 +504,8 @@
|
||||||
android:id="@+id/axolotl_fingerprint_box"
|
android:id="@+id/axolotl_fingerprint_box"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginTop="32dp">
|
android:layout_marginTop="32dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
android:title="@string/encryption_choice_unencrypted"/>
|
android:title="@string/encryption_choice_unencrypted"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/encryption_choice_axolotl"
|
android:id="@+id/encryption_choice_axolotl"
|
||||||
android:title="@string/encryption_choice_omemo"/>
|
android:title="@string/encryption_choice_omemo"
|
||||||
|
android:visible="@bool/omemo_enabled"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/encryption_choice_otr"
|
android:id="@+id/encryption_choice_otr"
|
||||||
android:title="@string/encryption_choice_otr"/>
|
android:title="@string/encryption_choice_otr"/>
|
||||||
|
|
4
src/main/res/values/encryption_settings.xml
Normal file
4
src/main/res/values/encryption_settings.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<bool name="omemo_enabled">false</bool>
|
||||||
|
</resources>
|
|
@ -654,4 +654,6 @@
|
||||||
<string name="no_accounts">(No activated accounts)</string>
|
<string name="no_accounts">(No activated accounts)</string>
|
||||||
<string name="this_field_is_required">This field is required</string>
|
<string name="this_field_is_required">This field is required</string>
|
||||||
<string name="retry_decryption">Retry decryption</string>
|
<string name="retry_decryption">Retry decryption</string>
|
||||||
|
<string name="pref_omemo_enabled_summary">Enable OMEMO?</string>
|
||||||
|
<string name="pref_omemo_enabled_title">Enable OMEMO</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -227,7 +227,7 @@
|
||||||
android:summary="@string/pref_xa_on_silent_mode_summary"
|
android:summary="@string/pref_xa_on_silent_mode_summary"
|
||||||
android:title="@string/pref_xa_on_silent_mode"/>
|
android:title="@string/pref_xa_on_silent_mode"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/pref_expert_options_other">
|
<PreferenceCategory android:key="other_expert_settings" android:title="@string/pref_expert_options_other">
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="autojoin"
|
android:key="autojoin"
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
|
@ -251,6 +251,11 @@
|
||||||
<de.thedevstack.conversationsplus.ui.preferences.LogInformationPreference
|
<de.thedevstack.conversationsplus.ui.preferences.LogInformationPreference
|
||||||
android:summary="@string/pref_show_logcat_summary"
|
android:summary="@string/pref_show_logcat_summary"
|
||||||
android:title="@string/pref_show_logcat_title"/>
|
android:title="@string/pref_show_logcat_title"/>
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="@bool/omemo_enabled"
|
||||||
|
android:key="omemo_enabled"
|
||||||
|
android:summary="@string/pref_omemo_enabled_summary"
|
||||||
|
android:title="@string/pref_omemo_enabled_title"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue