diff --git a/build.gradle b/build.gradle index 818cf6b5..ff937e3a 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ dependencies { compile 'de.timroes.android:EnhancedListView:0.3.4' compile 'me.leolin:ShortcutBadger:1.1.12@aar' compile 'com.kyleduo.switchbutton:library:1.2.8' - compile 'org.whispersystems:axolotl-android:1.3.4' + compile 'org.whispersystems:signal-protocol-java:2.5.3' compile 'com.makeramen:roundedimageview:2.2.0' compile "com.wefika:flowlayout:0.4.1" compile 'net.ypresto.androidtranscoder:android-transcoder:0.2.0' 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 84df8596..ff3f7fce 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -8,18 +8,18 @@ import android.util.Log; import android.util.Pair; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.whispersystems.libaxolotl.AxolotlAddress; -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.IdentityKeyPair; -import org.whispersystems.libaxolotl.InvalidKeyException; -import org.whispersystems.libaxolotl.InvalidKeyIdException; -import org.whispersystems.libaxolotl.SessionBuilder; -import org.whispersystems.libaxolotl.UntrustedIdentityException; -import org.whispersystems.libaxolotl.ecc.ECPublicKey; -import org.whispersystems.libaxolotl.state.PreKeyBundle; -import org.whispersystems.libaxolotl.state.PreKeyRecord; -import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; -import org.whispersystems.libaxolotl.util.KeyHelper; +import org.whispersystems.libsignal.SignalProtocolAddress; +import org.whispersystems.libsignal.IdentityKey; +import org.whispersystems.libsignal.IdentityKeyPair; +import org.whispersystems.libsignal.InvalidKeyException; +import org.whispersystems.libsignal.InvalidKeyIdException; +import org.whispersystems.libsignal.SessionBuilder; +import org.whispersystems.libsignal.UntrustedIdentityException; +import org.whispersystems.libsignal.ecc.ECPublicKey; +import org.whispersystems.libsignal.state.PreKeyBundle; +import org.whispersystems.libsignal.state.PreKeyRecord; +import org.whispersystems.libsignal.state.SignedPreKeyRecord; +import org.whispersystems.libsignal.util.KeyHelper; import java.security.PrivateKey; import java.security.Security; @@ -94,8 +94,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { for(Jid jid : jids) { if (deviceIds.get(jid) != null) { for (Integer foreignId : this.deviceIds.get(jid)) { - AxolotlAddress address = new AxolotlAddress(jid.toPreppedString(), foreignId); - if (fetchStatusMap.getAll(address).containsValue(FetchStatus.ERROR)) { + SignalProtocolAddress address = new SignalProtocolAddress(jid.toPreppedString(), foreignId); + if (fetchStatusMap.getAll(address.getName()).containsValue(FetchStatus.ERROR)) { return true; } } @@ -113,7 +113,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } public boolean hasVerifiedKeys(String name) { - for(XmppAxolotlSession session : this.sessions.getAll(new AxolotlAddress(name,0)).values()) { + for(XmppAxolotlSession session : this.sessions.getAll(name).values()) { if (session.getTrust().isVerified()) { return true; } @@ -129,7 +129,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { this.map = new HashMap<>(); } - public void put(AxolotlAddress address, T value) { + public void put(SignalProtocolAddress address, T value) { synchronized (MAP_LOCK) { Map devices = map.get(address.getName()); if (devices == null) { @@ -140,7 +140,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } } - public T get(AxolotlAddress address) { + public T get(SignalProtocolAddress address) { synchronized (MAP_LOCK) { Map devices = map.get(address.getName()); if (devices == null) { @@ -150,9 +150,9 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } } - public Map getAll(AxolotlAddress address) { + public Map getAll(String name) { synchronized (MAP_LOCK) { - Map devices = map.get(address.getName()); + Map devices = map.get(name); if (devices == null) { return new HashMap<>(); } @@ -160,7 +160,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } } - public boolean hasAny(AxolotlAddress address) { + public boolean hasAny(SignalProtocolAddress address) { synchronized (MAP_LOCK) { Map devices = map.get(address.getName()); return devices != null && !devices.isEmpty(); @@ -186,7 +186,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private void putDevicesForJid(String bareJid, List deviceIds, SQLiteAxolotlStore store) { for (Integer deviceId : deviceIds) { - AxolotlAddress axolotlAddress = new AxolotlAddress(bareJid, deviceId); + SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(bareJid, deviceId); IdentityKey identityKey = store.loadSession(axolotlAddress).getSessionState().getRemoteIdentityKey(); if(Config.X509_VERIFICATION) { X509Certificate certificate = store.getFingerprintCertificate(identityKey.getFingerprint().replaceAll("\\s", "")); @@ -219,7 +219,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } @Override - public void put(AxolotlAddress address, XmppAxolotlSession value) { + public void put(SignalProtocolAddress address, XmppAxolotlSession value) { super.put(address, value); value.setNotFresh(); xmppConnectionService.syncRosterToDisk(account); //TODO why? @@ -276,7 +276,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } public String getOwnFingerprint() { - return axolotlStore.getIdentityKeyPair().getPublicKey().getFingerprint().replaceAll("\\s", ""); + return CryptoHelper.bytesToHex(axolotlStore.getIdentityKeyPair().getPublicKey().serialize()); } public Set getKeysWithTrust(FingerprintStatus status) { @@ -308,13 +308,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return false; } - private AxolotlAddress getAddressForJid(Jid jid) { - return new AxolotlAddress(jid.toPreppedString(), 0); + private SignalProtocolAddress getAddressForJid(Jid jid) { + return new SignalProtocolAddress(jid.toPreppedString(), 0); } public Collection findOwnSessions() { - AxolotlAddress ownAddress = getAddressForJid(account.getJid().toBareJid()); - ArrayList s = new ArrayList<>(this.sessions.getAll(ownAddress).values()); + SignalProtocolAddress ownAddress = getAddressForJid(account.getJid().toBareJid()); + ArrayList s = new ArrayList<>(this.sessions.getAll(ownAddress.getName()).values()); Collections.sort(s); return s; } @@ -322,8 +322,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { public Collection findSessionsForContact(Contact contact) { - AxolotlAddress contactAddress = getAddressForJid(contact.getJid()); - ArrayList s = new ArrayList<>(this.sessions.getAll(contactAddress).values()); + SignalProtocolAddress contactAddress = getAddressForJid(contact.getJid()); + ArrayList s = new ArrayList<>(this.sessions.getAll(contactAddress.getName()).values()); Collections.sort(s); return s; } @@ -331,7 +331,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private Set findSessionsForConversation(Conversation conversation) { HashSet sessions = new HashSet<>(); for(Jid jid : conversation.getAcceptedCryptoTargets()) { - sessions.addAll(this.sessions.getAll(getAddressForJid(jid)).values()); + sessions.addAll(this.sessions.getAll(getAddressForJid(jid).getName()).values()); } return sessions; } @@ -364,8 +364,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return axolotlStore.getLocalRegistrationId(); } - public AxolotlAddress getOwnAxolotlAddress() { - return new AxolotlAddress(account.getJid().toBareJid().toPreppedString(),getOwnDeviceId()); + public SignalProtocolAddress getOwnAxolotlAddress() { + return new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(),getOwnDeviceId()); } public Set getOwnDeviceIds() { @@ -385,7 +385,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { Set expiredDevices = new HashSet<>(axolotlStore.getSubDeviceSessions(jid.toBareJid().toPreppedString())); expiredDevices.removeAll(deviceIds); for (Integer deviceId : expiredDevices) { - AxolotlAddress address = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId); + SignalProtocolAddress address = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), deviceId); XmppAxolotlSession session = sessions.get(address); if (session != null && session.getFingerprint() != null) { if (session.getTrust().isActive()) { @@ -395,7 +395,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } Set newDevices = new HashSet<>(deviceIds); for (Integer deviceId : newDevices) { - AxolotlAddress address = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId); + SignalProtocolAddress address = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), deviceId); XmppAxolotlSession session = sessions.get(address); if (session != null && session.getFingerprint() != null) { if (!session.getTrust().isActive()) { @@ -409,7 +409,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { needsPublishing |= deviceIds.removeAll(getExpiredDevices()); } for (Integer deviceId : deviceIds) { - AxolotlAddress ownDeviceAddress = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId); + SignalProtocolAddress ownDeviceAddress = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), deviceId); if (sessions.get(ownDeviceAddress) == null) { FetchStatus status = fetchStatusMap.get(ownDeviceAddress); if (status == null || status == FetchStatus.TIMEOUT) { @@ -755,7 +755,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private void verifySessionWithPEP(final XmppAxolotlSession session) { Log.d(Config.LOGTAG, "trying to verify fresh session (" + session.getRemoteAddress().getName() + ") with pep"); - final AxolotlAddress address = session.getRemoteAddress(); + final SignalProtocolAddress address = session.getRemoteAddress(); final IdentityKey identityKey = session.getIdentityKey(); try { IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveVerificationForDevice(Jid.fromString(address.getName()), address.getDeviceId()); @@ -809,10 +809,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private final Set PREVIOUSLY_REMOVED_FROM_ANNOUNCEMENT = new HashSet<>(); - private void finishBuildingSessionsFromPEP(final AxolotlAddress address) { - AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toPreppedString(), 0); - Map own = fetchStatusMap.getAll(ownAddress); - Map remote = fetchStatusMap.getAll(address); + private void finishBuildingSessionsFromPEP(final SignalProtocolAddress address) { + SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), 0); + Map own = fetchStatusMap.getAll(ownAddress.getName()); + Map remote = fetchStatusMap.getAll(address.getName()); if (!own.containsValue(FetchStatus.PENDING) && !remote.containsValue(FetchStatus.PENDING)) { FetchStatus report = null; if (own.containsValue(FetchStatus.SUCCESS) || remote.containsValue(FetchStatus.SUCCESS)) { @@ -842,7 +842,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } } - private void buildSessionFromPEP(final AxolotlAddress address) { + private void buildSessionFromPEP(final SignalProtocolAddress address) { Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building new session for " + address.toString()); if (address.equals(getOwnAxolotlAddress())) { throw new AssertionError("We should NEVER build a session with ourselves. What happened here?!"); @@ -921,13 +921,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } } - public Set findDevicesWithoutSession(final Conversation conversation) { - Set addresses = new HashSet<>(); + public Set findDevicesWithoutSession(final Conversation conversation) { + Set addresses = new HashSet<>(); for(Jid jid : getCryptoTargets(conversation)) { Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Finding devices without session for " + jid); if (deviceIds.get(jid) != null) { for (Integer foreignId : this.deviceIds.get(jid)) { - AxolotlAddress address = new AxolotlAddress(jid.toPreppedString(), foreignId); + SignalProtocolAddress address = new SignalProtocolAddress(jid.toPreppedString(), foreignId); if (sessions.get(address) == null) { IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey(); if (identityKey != null) { @@ -950,7 +950,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } if (deviceIds.get(account.getJid().toBareJid()) != null) { for (Integer ownId : this.deviceIds.get(account.getJid().toBareJid())) { - AxolotlAddress address = new AxolotlAddress(account.getJid().toBareJid().toPreppedString(), ownId); + SignalProtocolAddress address = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), ownId); if (sessions.get(address) == null) { IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey(); if (identityKey != null) { @@ -975,8 +975,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { public boolean createSessionsIfNeeded(final Conversation conversation) { Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Creating axolotl sessions if needed..."); boolean newSessions = false; - Set addresses = findDevicesWithoutSession(conversation); - for (AxolotlAddress address : addresses) { + Set addresses = findDevicesWithoutSession(conversation); + for (SignalProtocolAddress address : addresses) { Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Processing device: " + address.toString()); FetchStatus status = fetchStatusMap.get(address); if (status == null || status == FetchStatus.TIMEOUT) { @@ -1010,13 +1010,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } public boolean hasPendingKeyFetches(Account account, List jids) { - AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toPreppedString(), 0); - if (fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING)) { + SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), 0); + if (fetchStatusMap.getAll(ownAddress.getName()).containsValue(FetchStatus.PENDING)) { return true; } for(Jid jid : jids) { - AxolotlAddress foreignAddress = new AxolotlAddress(jid.toBareJid().toPreppedString(), 0); - if (fetchStatusMap.getAll(foreignAddress).containsValue(FetchStatus.PENDING)) { + SignalProtocolAddress foreignAddress = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), 0); + if (fetchStatusMap.getAll(foreignAddress.getName()).containsValue(FetchStatus.PENDING)) { return true; } } @@ -1104,7 +1104,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return axolotlMessage; } - private XmppAxolotlSession recreateUncachedSession(AxolotlAddress address) { + private XmppAxolotlSession recreateUncachedSession(SignalProtocolAddress address) { IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey(); return (identityKey != null) ? new XmppAxolotlSession(account, axolotlStore, address, identityKey) @@ -1112,7 +1112,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } private XmppAxolotlSession getReceivingSession(XmppAxolotlMessage message) { - AxolotlAddress senderAddress = new AxolotlAddress(message.getFrom().toPreppedString(), + SignalProtocolAddress senderAddress = new SignalProtocolAddress(message.getFrom().toPreppedString(), message.getSenderDeviceId()); XmppAxolotlSession session = sessions.get(senderAddress); if (session == null) { diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java index eb08832e..29f85161 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java @@ -3,17 +3,17 @@ package eu.siacs.conversations.crypto.axolotl; import android.util.Log; import android.util.LruCache; -import org.whispersystems.libaxolotl.AxolotlAddress; -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.IdentityKeyPair; -import org.whispersystems.libaxolotl.InvalidKeyIdException; -import org.whispersystems.libaxolotl.ecc.Curve; -import org.whispersystems.libaxolotl.ecc.ECKeyPair; -import org.whispersystems.libaxolotl.state.AxolotlStore; -import org.whispersystems.libaxolotl.state.PreKeyRecord; -import org.whispersystems.libaxolotl.state.SessionRecord; -import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; -import org.whispersystems.libaxolotl.util.KeyHelper; +import org.whispersystems.libsignal.SignalProtocolAddress; +import org.whispersystems.libsignal.IdentityKey; +import org.whispersystems.libsignal.IdentityKeyPair; +import org.whispersystems.libsignal.InvalidKeyIdException; +import org.whispersystems.libsignal.ecc.Curve; +import org.whispersystems.libsignal.ecc.ECKeyPair; +import org.whispersystems.libsignal.state.SignalProtocolStore; +import org.whispersystems.libsignal.state.PreKeyRecord; +import org.whispersystems.libsignal.state.SessionRecord; +import org.whispersystems.libsignal.state.SignedPreKeyRecord; +import org.whispersystems.libsignal.util.KeyHelper; import java.security.cert.X509Certificate; import java.util.List; @@ -23,7 +23,7 @@ import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.services.XmppConnectionService; -public class SQLiteAxolotlStore implements AxolotlStore { +public class SQLiteAxolotlStore implements SignalProtocolStore { public static final String PREKEY_TABLENAME = "prekeys"; public static final String SIGNED_PREKEY_TABLENAME = "signed_prekeys"; @@ -179,17 +179,18 @@ public class SQLiteAxolotlStore implements AxolotlStore { *

* Store a remote client's identity key as trusted. * - * @param name The name of the remote client. + * @param address The address of the remote client. * @param identityKey The remote client's identity key. + * @return true on success */ @Override - public void saveIdentity(String name, IdentityKey identityKey) { - if (!mXmppConnectionService.databaseBackend.loadIdentityKeys(account, name).contains(identityKey)) { + public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityKey) { + if (!mXmppConnectionService.databaseBackend.loadIdentityKeys(account, address.getName()).contains(identityKey)) { String fingerprint = identityKey.getFingerprint().replaceAll("\\s", ""); FingerprintStatus status = getFingerprintStatus(fingerprint); if (status == null) { - if (mXmppConnectionService.blindTrustBeforeVerification() && !account.getAxolotlService().hasVerifiedKeys(name)) { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": blindly trusted "+fingerprint+" of "+name); + if (mXmppConnectionService.blindTrustBeforeVerification() && !account.getAxolotlService().hasVerifiedKeys(address.getName())) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": blindly trusted "+fingerprint+" of "+address.getName()); status = FingerprintStatus.createActiveTrusted(); } else { status = FingerprintStatus.createActiveUndecided(); @@ -197,9 +198,10 @@ public class SQLiteAxolotlStore implements AxolotlStore { } else { status = status.toActive(); } - mXmppConnectionService.databaseBackend.storeIdentityKey(account, name, identityKey, status); + mXmppConnectionService.databaseBackend.storeIdentityKey(account, address.getName(), identityKey, status); trustCache.remove(fingerprint); } + return true; } /** @@ -212,12 +214,11 @@ public class SQLiteAxolotlStore implements AxolotlStore { * store. Only if it mismatches an entry in the local store is it considered * 'untrusted.' * - * @param name The name of the remote client. * @param identityKey The identity key to verify. * @return true if trusted, false if untrusted. */ @Override - public boolean isTrustedIdentity(String name, IdentityKey identityKey) { + public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) { return true; } @@ -264,7 +265,7 @@ public class SQLiteAxolotlStore implements AxolotlStore { * a new SessionRecord if one does not currently exist. */ @Override - public SessionRecord loadSession(AxolotlAddress address) { + public SessionRecord loadSession(SignalProtocolAddress address) { SessionRecord session = mXmppConnectionService.databaseBackend.loadSession(this.account, address); return (session != null) ? session : new SessionRecord(); } @@ -278,7 +279,7 @@ public class SQLiteAxolotlStore implements AxolotlStore { @Override public List getSubDeviceSessions(String name) { return mXmppConnectionService.databaseBackend.getSubDeviceSessions(account, - new AxolotlAddress(name, 0)); + new SignalProtocolAddress(name, 0)); } /** @@ -288,7 +289,7 @@ public class SQLiteAxolotlStore implements AxolotlStore { * @param record the current SessionRecord for the remote client. */ @Override - public void storeSession(AxolotlAddress address, SessionRecord record) { + public void storeSession(SignalProtocolAddress address, SessionRecord record) { mXmppConnectionService.databaseBackend.storeSession(account, address, record); } @@ -299,7 +300,7 @@ public class SQLiteAxolotlStore implements AxolotlStore { * @return true if a {@link SessionRecord} exists, false otherwise. */ @Override - public boolean containsSession(AxolotlAddress address) { + public boolean containsSession(SignalProtocolAddress address) { return mXmppConnectionService.databaseBackend.containsSession(account, address); } @@ -309,7 +310,7 @@ public class SQLiteAxolotlStore implements AxolotlStore { * @param address the address of the remote client. */ @Override - public void deleteSession(AxolotlAddress address) { + public void deleteSession(SignalProtocolAddress address) { mXmppConnectionService.databaseBackend.deleteSession(account, address); } @@ -320,7 +321,7 @@ public class SQLiteAxolotlStore implements AxolotlStore { */ @Override public void deleteAllSessions(String name) { - AxolotlAddress address = new AxolotlAddress(name, 0); + SignalProtocolAddress address = new SignalProtocolAddress(name, 0); mXmppConnectionService.databaseBackend.deleteAllSessions(account, address); } diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java index e90b7e90..d08b7ecf 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java @@ -3,39 +3,40 @@ 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.DuplicateMessageException; -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.InvalidKeyException; -import org.whispersystems.libaxolotl.InvalidKeyIdException; -import org.whispersystems.libaxolotl.InvalidMessageException; -import org.whispersystems.libaxolotl.InvalidVersionException; -import org.whispersystems.libaxolotl.LegacyMessageException; -import org.whispersystems.libaxolotl.NoSessionException; -import org.whispersystems.libaxolotl.SessionCipher; -import org.whispersystems.libaxolotl.UntrustedIdentityException; -import org.whispersystems.libaxolotl.protocol.CiphertextMessage; -import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage; -import org.whispersystems.libaxolotl.protocol.WhisperMessage; -import org.whispersystems.libaxolotl.util.guava.Optional; +import org.whispersystems.libsignal.SignalProtocolAddress; +import org.whispersystems.libsignal.DuplicateMessageException; +import org.whispersystems.libsignal.IdentityKey; +import org.whispersystems.libsignal.InvalidKeyException; +import org.whispersystems.libsignal.InvalidKeyIdException; +import org.whispersystems.libsignal.InvalidMessageException; +import org.whispersystems.libsignal.InvalidVersionException; +import org.whispersystems.libsignal.LegacyMessageException; +import org.whispersystems.libsignal.NoSessionException; +import org.whispersystems.libsignal.SessionCipher; +import org.whispersystems.libsignal.UntrustedIdentityException; +import org.whispersystems.libsignal.protocol.CiphertextMessage; +import org.whispersystems.libsignal.protocol.PreKeySignalMessage; +import org.whispersystems.libsignal.protocol.SignalMessage; +import org.whispersystems.libsignal.util.guava.Optional; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.utils.CryptoHelper; public class XmppAxolotlSession implements Comparable { private final SessionCipher cipher; private final SQLiteAxolotlStore sqLiteAxolotlStore; - private final AxolotlAddress remoteAddress; + private final SignalProtocolAddress remoteAddress; private final Account account; private IdentityKey identityKey; private Integer preKeyId = null; private boolean fresh = true; - public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress remoteAddress, IdentityKey identityKey) { + public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, SignalProtocolAddress remoteAddress, IdentityKey identityKey) { this(account, store, remoteAddress); this.identityKey = identityKey; } - public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress remoteAddress) { + public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, SignalProtocolAddress remoteAddress) { this.cipher = new SessionCipher(store, remoteAddress); this.remoteAddress = remoteAddress; this.sqLiteAxolotlStore = store; @@ -52,14 +53,14 @@ public class XmppAxolotlSession implements Comparable { } public String getFingerprint() { - return identityKey == null ? null : identityKey.getFingerprint().replaceAll("\\s", ""); + return identityKey == null ? null : CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize()); } public IdentityKey getIdentityKey() { return identityKey; } - public AxolotlAddress getRemoteAddress() { + public SignalProtocolAddress getRemoteAddress() { return remoteAddress; } @@ -88,9 +89,9 @@ public class XmppAxolotlSession implements Comparable { try { CiphertextMessage ciphertextMessage; try { - ciphertextMessage = new PreKeyWhisperMessage(encryptedKey.key); - Optional optionalPreKeyId = ((PreKeyWhisperMessage) ciphertextMessage).getPreKeyId(); - IdentityKey identityKey = ((PreKeyWhisperMessage) ciphertextMessage).getIdentityKey(); + ciphertextMessage = new PreKeySignalMessage(encryptedKey.key); + Optional optionalPreKeyId = ((PreKeySignalMessage) ciphertextMessage).getPreKeyId(); + IdentityKey identityKey = ((PreKeySignalMessage) ciphertextMessage).getIdentityKey(); if (!optionalPreKeyId.isPresent()) { throw new CryptoFailedException("PreKeyWhisperMessage did not contain a PreKeyId"); } @@ -100,12 +101,12 @@ public class XmppAxolotlSession implements Comparable { } this.identityKey = identityKey; } catch (InvalidVersionException | InvalidMessageException e) { - ciphertextMessage = new WhisperMessage(encryptedKey.key); + ciphertextMessage = new SignalMessage(encryptedKey.key); } - if (ciphertextMessage instanceof PreKeyWhisperMessage) { - plaintext = cipher.decrypt((PreKeyWhisperMessage) ciphertextMessage); + if (ciphertextMessage instanceof PreKeySignalMessage) { + plaintext = cipher.decrypt((PreKeySignalMessage) ciphertextMessage); } else { - plaintext = cipher.decrypt((WhisperMessage) ciphertextMessage); + plaintext = cipher.decrypt((SignalMessage) ciphertextMessage); } } catch (InvalidKeyException | LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException | InvalidKeyIdException | UntrustedIdentityException e) { if (!(e instanceof DuplicateMessageException)) { @@ -126,8 +127,12 @@ public class XmppAxolotlSession implements Comparable { public AxolotlKey processSending(@NonNull byte[] outgoingMessage) { FingerprintStatus status = getTrust(); if (status.isTrustedAndActive()) { - CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage); - return new AxolotlKey(ciphertextMessage.serialize(),ciphertextMessage.getType() == CiphertextMessage.PREKEY_TYPE); + try { + CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage); + return new AxolotlKey(ciphertextMessage.serialize(),ciphertextMessage.getType() == CiphertextMessage.PREKEY_TYPE); + } catch (UntrustedIdentityException e) { + return null; + } } else { return null; } diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index 2f8b66df..ed16cfc7 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -5,10 +5,10 @@ import android.os.Bundle; import android.util.Base64; import android.util.Log; -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.ecc.ECPublicKey; -import org.whispersystems.libaxolotl.state.PreKeyRecord; -import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; +import org.whispersystems.libsignal.IdentityKey; +import org.whispersystems.libsignal.ecc.ECPublicKey; +import org.whispersystems.libsignal.state.PreKeyRecord; +import org.whispersystems.libsignal.state.SignedPreKeyRecord; import java.nio.ByteBuffer; import java.security.cert.CertificateEncodingException; diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index 0eb2b3ad..7e8bbcba 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -5,10 +5,10 @@ import android.util.Base64; import android.util.Log; import android.util.Pair; -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.ecc.Curve; -import org.whispersystems.libaxolotl.ecc.ECPublicKey; -import org.whispersystems.libaxolotl.state.PreKeyBundle; +import org.whispersystems.libsignal.IdentityKey; +import org.whispersystems.libsignal.ecc.Curve; +import org.whispersystems.libsignal.ecc.ECPublicKey; +import org.whispersystems.libsignal.state.PreKeyBundle; import java.io.ByteArrayInputStream; import java.security.cert.CertificateException; diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index 45e4eb17..f38abfa6 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -13,13 +13,13 @@ import android.util.Log; import android.util.Pair; import org.json.JSONObject; -import org.whispersystems.libaxolotl.AxolotlAddress; -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.IdentityKeyPair; -import org.whispersystems.libaxolotl.InvalidKeyException; -import org.whispersystems.libaxolotl.state.PreKeyRecord; -import org.whispersystems.libaxolotl.state.SessionRecord; -import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; +import org.whispersystems.libsignal.SignalProtocolAddress; +import org.whispersystems.libsignal.IdentityKey; +import org.whispersystems.libsignal.IdentityKeyPair; +import org.whispersystems.libsignal.InvalidKeyException; +import org.whispersystems.libsignal.state.PreKeyRecord; +import org.whispersystems.libsignal.state.SessionRecord; +import org.whispersystems.libsignal.state.SignedPreKeyRecord; import java.io.ByteArrayInputStream; import java.io.File; @@ -305,7 +305,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { continue; } int ownDeviceId = Integer.valueOf(ownDeviceIdString); - AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toPreppedString(), ownDeviceId); + SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), ownDeviceId); deleteSession(db, account, ownAddress); IdentityKeyPair identityKeyPair = loadOwnIdentityKeyPair(db, account); if (identityKeyPair != null) { @@ -887,7 +887,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { return maxClearDate; } - private Cursor getCursorForSession(Account account, AxolotlAddress contact) { + private Cursor getCursorForSession(Account account, SignalProtocolAddress contact) { final SQLiteDatabase db = this.getReadableDatabase(); String[] selectionArgs = {account.getUuid(), contact.getName(), @@ -901,7 +901,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { null, null, null); } - public SessionRecord loadSession(Account account, AxolotlAddress contact) { + public SessionRecord loadSession(Account account, SignalProtocolAddress contact) { SessionRecord session = null; Cursor cursor = getCursorForSession(account, contact); if (cursor.getCount() != 0) { @@ -917,12 +917,12 @@ public class DatabaseBackend extends SQLiteOpenHelper { return session; } - public List getSubDeviceSessions(Account account, AxolotlAddress contact) { + public List getSubDeviceSessions(Account account, SignalProtocolAddress contact) { final SQLiteDatabase db = this.getReadableDatabase(); return getSubDeviceSessions(db, account, contact); } - private List getSubDeviceSessions(SQLiteDatabase db, Account account, AxolotlAddress contact) { + private List getSubDeviceSessions(SQLiteDatabase db, Account account, SignalProtocolAddress contact) { List devices = new ArrayList<>(); String[] columns = {SQLiteAxolotlStore.DEVICE_ID}; String[] selectionArgs = {account.getUuid(), @@ -943,14 +943,14 @@ public class DatabaseBackend extends SQLiteOpenHelper { return devices; } - public boolean containsSession(Account account, AxolotlAddress contact) { + public boolean containsSession(Account account, SignalProtocolAddress contact) { Cursor cursor = getCursorForSession(account, contact); int count = cursor.getCount(); cursor.close(); return count != 0; } - public void storeSession(Account account, AxolotlAddress contact, SessionRecord session) { + public void storeSession(Account account, SignalProtocolAddress contact, SessionRecord session) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(SQLiteAxolotlStore.NAME, contact.getName()); @@ -960,12 +960,12 @@ public class DatabaseBackend extends SQLiteOpenHelper { db.insert(SQLiteAxolotlStore.SESSION_TABLENAME, null, values); } - public void deleteSession(Account account, AxolotlAddress contact) { + public void deleteSession(Account account, SignalProtocolAddress contact) { SQLiteDatabase db = this.getWritableDatabase(); deleteSession(db, account, contact); } - private void deleteSession(SQLiteDatabase db, Account account, AxolotlAddress contact) { + private void deleteSession(SQLiteDatabase db, Account account, SignalProtocolAddress contact) { String[] args = {account.getUuid(), contact.getName(), Integer.toString(contact.getDeviceId())}; @@ -976,7 +976,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { args); } - public void deleteAllSessions(Account account, AxolotlAddress contact) { + public void deleteAllSessions(Account account, SignalProtocolAddress contact) { SQLiteDatabase db = this.getWritableDatabase(); String[] args = {account.getUuid(), contact.getName()}; db.delete(SQLiteAxolotlStore.SESSION_TABLENAME, diff --git a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java index 02556d31..b8b918d5 100644 --- a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java @@ -17,7 +17,7 @@ import android.widget.Toast; import com.google.zxing.integration.android.IntentIntegrator; -import org.whispersystems.libaxolotl.IdentityKey; +import org.whispersystems.libsignal.IdentityKey; import java.util.ArrayList; import java.util.Arrays; diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java index 01034c1d..c91891a7 100644 --- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java @@ -103,7 +103,7 @@ public final class CryptoHelper { } else if (fingerprint.length() < 40) { return fingerprint; } - StringBuilder builder = new StringBuilder(fingerprint.toLowerCase(Locale.US).replaceAll("\\s", "")); + StringBuilder builder = new StringBuilder(fingerprint); for(int i=8;i