upgrade to signal-protocol-java. thanks @ysangkok

Daniel Gultsch created

fixes #1384
closes #2509

Change summary

build.gradle                                                                |   2 
src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java     | 106 
src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java |  53 
src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java |  63 
src/main/java/eu/siacs/conversations/generator/IqGenerator.java             |   8 
src/main/java/eu/siacs/conversations/parser/IqParser.java                   |   8 
src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java       |  34 
src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java              |   2 
src/main/java/eu/siacs/conversations/utils/CryptoHelper.java                |   2 
9 files changed, 142 insertions(+), 136 deletions(-)

Detailed changes

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'

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<Integer, T> 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<Integer, T> devices = map.get(address.getName());
 				if (devices == null) {
@@ -150,9 +150,9 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 			}
 		}
 
-		public Map<Integer, T> getAll(AxolotlAddress address) {
+		public Map<Integer, T> getAll(String name) {
 			synchronized (MAP_LOCK) {
-				Map<Integer, T> devices = map.get(address.getName());
+				Map<Integer, T> 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<Integer, T> 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<Integer> 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<IdentityKey> 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<XmppAxolotlSession> findOwnSessions() {
-		AxolotlAddress ownAddress = getAddressForJid(account.getJid().toBareJid());
-		ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(ownAddress).values());
+		SignalProtocolAddress ownAddress = getAddressForJid(account.getJid().toBareJid());
+		ArrayList<XmppAxolotlSession> 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<XmppAxolotlSession> findSessionsForContact(Contact contact) {
-		AxolotlAddress contactAddress = getAddressForJid(contact.getJid());
-		ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(contactAddress).values());
+		SignalProtocolAddress contactAddress = getAddressForJid(contact.getJid());
+		ArrayList<XmppAxolotlSession> 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<XmppAxolotlSession> findSessionsForConversation(Conversation conversation) {
 		HashSet<XmppAxolotlSession> 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<Integer> getOwnDeviceIds() {
@@ -385,7 +385,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 		Set<Integer> 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<Integer> 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<Integer> PREVIOUSLY_REMOVED_FROM_ANNOUNCEMENT = new HashSet<>();
 
-	private void finishBuildingSessionsFromPEP(final AxolotlAddress address) {
-		AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toPreppedString(), 0);
-		Map<Integer, FetchStatus> own = fetchStatusMap.getAll(ownAddress);
-		Map<Integer, FetchStatus> remote = fetchStatusMap.getAll(address);
+	private void finishBuildingSessionsFromPEP(final SignalProtocolAddress address) {
+		SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), 0);
+		Map<Integer, FetchStatus> own = fetchStatusMap.getAll(ownAddress.getName());
+		Map<Integer, FetchStatus> 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<AxolotlAddress> findDevicesWithoutSession(final Conversation conversation) {
-		Set<AxolotlAddress> addresses = new HashSet<>();
+	public Set<SignalProtocolAddress> findDevicesWithoutSession(final Conversation conversation) {
+		Set<SignalProtocolAddress> 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<AxolotlAddress> addresses = findDevicesWithoutSession(conversation);
-		for (AxolotlAddress address : addresses) {
+		Set<SignalProtocolAddress> 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<Jid> 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) {

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 {
 	 * <p/>
 	 * 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<Integer> 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);
 	}

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<XmppAxolotlSession> {
 	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<XmppAxolotlSession> {
 	}
 
 	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<XmppAxolotlSession> {
 			try {
 				CiphertextMessage ciphertextMessage;
 				try {
-					ciphertextMessage = new PreKeyWhisperMessage(encryptedKey.key);
-					Optional<Integer> optionalPreKeyId = ((PreKeyWhisperMessage) ciphertextMessage).getPreKeyId();
-					IdentityKey identityKey = ((PreKeyWhisperMessage) ciphertextMessage).getIdentityKey();
+					ciphertextMessage = new PreKeySignalMessage(encryptedKey.key);
+					Optional<Integer> 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<XmppAxolotlSession> {
 					}
 					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<XmppAxolotlSession> {
 	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;
 		}

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;

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;

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<Integer> getSubDeviceSessions(Account account, AxolotlAddress contact) {
+	public List<Integer> getSubDeviceSessions(Account account, SignalProtocolAddress contact) {
 		final SQLiteDatabase db = this.getReadableDatabase();
 		return getSubDeviceSessions(db, account, contact);
 	}
 
-	private List<Integer> getSubDeviceSessions(SQLiteDatabase db, Account account, AxolotlAddress contact) {
+	private List<Integer> getSubDeviceSessions(SQLiteDatabase db, Account account, SignalProtocolAddress contact) {
 		List<Integer> 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,

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;

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<builder.length();i+=9) {
 			builder.insert(i, ' ');
 		}