mirror of
https://github.com/moparisthebest/Conversations
synced 2024-12-11 01:52:17 -05:00
upgrade to signal-protocol-java. thanks @ysangkok
fixes #1384 closes #2509
This commit is contained in:
parent
f67baab983
commit
24768d051d
@ -37,7 +37,7 @@ dependencies {
|
|||||||
compile 'de.timroes.android:EnhancedListView:0.3.4'
|
compile 'de.timroes.android:EnhancedListView:0.3.4'
|
||||||
compile 'me.leolin:ShortcutBadger:1.1.12@aar'
|
compile 'me.leolin:ShortcutBadger:1.1.12@aar'
|
||||||
compile 'com.kyleduo.switchbutton:library:1.2.8'
|
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.makeramen:roundedimageview:2.2.0'
|
||||||
compile "com.wefika:flowlayout:0.4.1"
|
compile "com.wefika:flowlayout:0.4.1"
|
||||||
compile 'net.ypresto.androidtranscoder:android-transcoder:0.2.0'
|
compile 'net.ypresto.androidtranscoder:android-transcoder:0.2.0'
|
||||||
|
@ -8,18 +8,18 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.whispersystems.libaxolotl.AxolotlAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.libaxolotl.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libaxolotl.IdentityKeyPair;
|
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||||
import org.whispersystems.libaxolotl.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libaxolotl.InvalidKeyIdException;
|
import org.whispersystems.libsignal.InvalidKeyIdException;
|
||||||
import org.whispersystems.libaxolotl.SessionBuilder;
|
import org.whispersystems.libsignal.SessionBuilder;
|
||||||
import org.whispersystems.libaxolotl.UntrustedIdentityException;
|
import org.whispersystems.libsignal.UntrustedIdentityException;
|
||||||
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
|
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||||
import org.whispersystems.libaxolotl.state.PreKeyBundle;
|
import org.whispersystems.libsignal.state.PreKeyBundle;
|
||||||
import org.whispersystems.libaxolotl.state.PreKeyRecord;
|
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||||
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.libaxolotl.util.KeyHelper;
|
import org.whispersystems.libsignal.util.KeyHelper;
|
||||||
|
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
@ -94,8 +94,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
for(Jid jid : jids) {
|
for(Jid jid : jids) {
|
||||||
if (deviceIds.get(jid) != null) {
|
if (deviceIds.get(jid) != null) {
|
||||||
for (Integer foreignId : this.deviceIds.get(jid)) {
|
for (Integer foreignId : this.deviceIds.get(jid)) {
|
||||||
AxolotlAddress address = new AxolotlAddress(jid.toPreppedString(), foreignId);
|
SignalProtocolAddress address = new SignalProtocolAddress(jid.toPreppedString(), foreignId);
|
||||||
if (fetchStatusMap.getAll(address).containsValue(FetchStatus.ERROR)) {
|
if (fetchStatusMap.getAll(address.getName()).containsValue(FetchStatus.ERROR)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasVerifiedKeys(String name) {
|
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()) {
|
if (session.getTrust().isVerified()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
this.map = new HashMap<>();
|
this.map = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(AxolotlAddress address, T value) {
|
public void put(SignalProtocolAddress address, T value) {
|
||||||
synchronized (MAP_LOCK) {
|
synchronized (MAP_LOCK) {
|
||||||
Map<Integer, T> devices = map.get(address.getName());
|
Map<Integer, T> devices = map.get(address.getName());
|
||||||
if (devices == null) {
|
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) {
|
synchronized (MAP_LOCK) {
|
||||||
Map<Integer, T> devices = map.get(address.getName());
|
Map<Integer, T> devices = map.get(address.getName());
|
||||||
if (devices == null) {
|
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) {
|
synchronized (MAP_LOCK) {
|
||||||
Map<Integer, T> devices = map.get(address.getName());
|
Map<Integer, T> devices = map.get(name);
|
||||||
if (devices == null) {
|
if (devices == null) {
|
||||||
return new HashMap<>();
|
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) {
|
synchronized (MAP_LOCK) {
|
||||||
Map<Integer, T> devices = map.get(address.getName());
|
Map<Integer, T> devices = map.get(address.getName());
|
||||||
return devices != null && !devices.isEmpty();
|
return devices != null && !devices.isEmpty();
|
||||||
@ -186,7 +186,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
|
|
||||||
private void putDevicesForJid(String bareJid, List<Integer> deviceIds, SQLiteAxolotlStore store) {
|
private void putDevicesForJid(String bareJid, List<Integer> deviceIds, SQLiteAxolotlStore store) {
|
||||||
for (Integer deviceId : deviceIds) {
|
for (Integer deviceId : deviceIds) {
|
||||||
AxolotlAddress axolotlAddress = new AxolotlAddress(bareJid, deviceId);
|
SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(bareJid, deviceId);
|
||||||
IdentityKey identityKey = store.loadSession(axolotlAddress).getSessionState().getRemoteIdentityKey();
|
IdentityKey identityKey = store.loadSession(axolotlAddress).getSessionState().getRemoteIdentityKey();
|
||||||
if(Config.X509_VERIFICATION) {
|
if(Config.X509_VERIFICATION) {
|
||||||
X509Certificate certificate = store.getFingerprintCertificate(identityKey.getFingerprint().replaceAll("\\s", ""));
|
X509Certificate certificate = store.getFingerprintCertificate(identityKey.getFingerprint().replaceAll("\\s", ""));
|
||||||
@ -219,7 +219,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(AxolotlAddress address, XmppAxolotlSession value) {
|
public void put(SignalProtocolAddress address, XmppAxolotlSession value) {
|
||||||
super.put(address, value);
|
super.put(address, value);
|
||||||
value.setNotFresh();
|
value.setNotFresh();
|
||||||
xmppConnectionService.syncRosterToDisk(account); //TODO why?
|
xmppConnectionService.syncRosterToDisk(account); //TODO why?
|
||||||
@ -276,7 +276,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getOwnFingerprint() {
|
public String getOwnFingerprint() {
|
||||||
return axolotlStore.getIdentityKeyPair().getPublicKey().getFingerprint().replaceAll("\\s", "");
|
return CryptoHelper.bytesToHex(axolotlStore.getIdentityKeyPair().getPublicKey().serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<IdentityKey> getKeysWithTrust(FingerprintStatus status) {
|
public Set<IdentityKey> getKeysWithTrust(FingerprintStatus status) {
|
||||||
@ -308,13 +308,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AxolotlAddress getAddressForJid(Jid jid) {
|
private SignalProtocolAddress getAddressForJid(Jid jid) {
|
||||||
return new AxolotlAddress(jid.toPreppedString(), 0);
|
return new SignalProtocolAddress(jid.toPreppedString(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<XmppAxolotlSession> findOwnSessions() {
|
public Collection<XmppAxolotlSession> findOwnSessions() {
|
||||||
AxolotlAddress ownAddress = getAddressForJid(account.getJid().toBareJid());
|
SignalProtocolAddress ownAddress = getAddressForJid(account.getJid().toBareJid());
|
||||||
ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(ownAddress).values());
|
ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(ownAddress.getName()).values());
|
||||||
Collections.sort(s);
|
Collections.sort(s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -322,8 +322,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
|
|
||||||
|
|
||||||
public Collection<XmppAxolotlSession> findSessionsForContact(Contact contact) {
|
public Collection<XmppAxolotlSession> findSessionsForContact(Contact contact) {
|
||||||
AxolotlAddress contactAddress = getAddressForJid(contact.getJid());
|
SignalProtocolAddress contactAddress = getAddressForJid(contact.getJid());
|
||||||
ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(contactAddress).values());
|
ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(contactAddress.getName()).values());
|
||||||
Collections.sort(s);
|
Collections.sort(s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -331,7 +331,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
private Set<XmppAxolotlSession> findSessionsForConversation(Conversation conversation) {
|
private Set<XmppAxolotlSession> findSessionsForConversation(Conversation conversation) {
|
||||||
HashSet<XmppAxolotlSession> sessions = new HashSet<>();
|
HashSet<XmppAxolotlSession> sessions = new HashSet<>();
|
||||||
for(Jid jid : conversation.getAcceptedCryptoTargets()) {
|
for(Jid jid : conversation.getAcceptedCryptoTargets()) {
|
||||||
sessions.addAll(this.sessions.getAll(getAddressForJid(jid)).values());
|
sessions.addAll(this.sessions.getAll(getAddressForJid(jid).getName()).values());
|
||||||
}
|
}
|
||||||
return sessions;
|
return sessions;
|
||||||
}
|
}
|
||||||
@ -364,8 +364,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
return axolotlStore.getLocalRegistrationId();
|
return axolotlStore.getLocalRegistrationId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AxolotlAddress getOwnAxolotlAddress() {
|
public SignalProtocolAddress getOwnAxolotlAddress() {
|
||||||
return new AxolotlAddress(account.getJid().toBareJid().toPreppedString(),getOwnDeviceId());
|
return new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(),getOwnDeviceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Integer> getOwnDeviceIds() {
|
public Set<Integer> getOwnDeviceIds() {
|
||||||
@ -385,7 +385,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
Set<Integer> expiredDevices = new HashSet<>(axolotlStore.getSubDeviceSessions(jid.toBareJid().toPreppedString()));
|
Set<Integer> expiredDevices = new HashSet<>(axolotlStore.getSubDeviceSessions(jid.toBareJid().toPreppedString()));
|
||||||
expiredDevices.removeAll(deviceIds);
|
expiredDevices.removeAll(deviceIds);
|
||||||
for (Integer deviceId : expiredDevices) {
|
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);
|
XmppAxolotlSession session = sessions.get(address);
|
||||||
if (session != null && session.getFingerprint() != null) {
|
if (session != null && session.getFingerprint() != null) {
|
||||||
if (session.getTrust().isActive()) {
|
if (session.getTrust().isActive()) {
|
||||||
@ -395,7 +395,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
}
|
}
|
||||||
Set<Integer> newDevices = new HashSet<>(deviceIds);
|
Set<Integer> newDevices = new HashSet<>(deviceIds);
|
||||||
for (Integer deviceId : newDevices) {
|
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);
|
XmppAxolotlSession session = sessions.get(address);
|
||||||
if (session != null && session.getFingerprint() != null) {
|
if (session != null && session.getFingerprint() != null) {
|
||||||
if (!session.getTrust().isActive()) {
|
if (!session.getTrust().isActive()) {
|
||||||
@ -409,7 +409,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
needsPublishing |= deviceIds.removeAll(getExpiredDevices());
|
needsPublishing |= deviceIds.removeAll(getExpiredDevices());
|
||||||
}
|
}
|
||||||
for (Integer deviceId : deviceIds) {
|
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) {
|
if (sessions.get(ownDeviceAddress) == null) {
|
||||||
FetchStatus status = fetchStatusMap.get(ownDeviceAddress);
|
FetchStatus status = fetchStatusMap.get(ownDeviceAddress);
|
||||||
if (status == null || status == FetchStatus.TIMEOUT) {
|
if (status == null || status == FetchStatus.TIMEOUT) {
|
||||||
@ -755,7 +755,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
|
|
||||||
private void verifySessionWithPEP(final XmppAxolotlSession session) {
|
private void verifySessionWithPEP(final XmppAxolotlSession session) {
|
||||||
Log.d(Config.LOGTAG, "trying to verify fresh session (" + session.getRemoteAddress().getName() + ") with pep");
|
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();
|
final IdentityKey identityKey = session.getIdentityKey();
|
||||||
try {
|
try {
|
||||||
IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveVerificationForDevice(Jid.fromString(address.getName()), address.getDeviceId());
|
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 final Set<Integer> PREVIOUSLY_REMOVED_FROM_ANNOUNCEMENT = new HashSet<>();
|
||||||
|
|
||||||
private void finishBuildingSessionsFromPEP(final AxolotlAddress address) {
|
private void finishBuildingSessionsFromPEP(final SignalProtocolAddress address) {
|
||||||
AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toPreppedString(), 0);
|
SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), 0);
|
||||||
Map<Integer, FetchStatus> own = fetchStatusMap.getAll(ownAddress);
|
Map<Integer, FetchStatus> own = fetchStatusMap.getAll(ownAddress.getName());
|
||||||
Map<Integer, FetchStatus> remote = fetchStatusMap.getAll(address);
|
Map<Integer, FetchStatus> remote = fetchStatusMap.getAll(address.getName());
|
||||||
if (!own.containsValue(FetchStatus.PENDING) && !remote.containsValue(FetchStatus.PENDING)) {
|
if (!own.containsValue(FetchStatus.PENDING) && !remote.containsValue(FetchStatus.PENDING)) {
|
||||||
FetchStatus report = null;
|
FetchStatus report = null;
|
||||||
if (own.containsValue(FetchStatus.SUCCESS) || remote.containsValue(FetchStatus.SUCCESS)) {
|
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());
|
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building new session for " + address.toString());
|
||||||
if (address.equals(getOwnAxolotlAddress())) {
|
if (address.equals(getOwnAxolotlAddress())) {
|
||||||
throw new AssertionError("We should NEVER build a session with ourselves. What happened here?!");
|
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) {
|
public Set<SignalProtocolAddress> findDevicesWithoutSession(final Conversation conversation) {
|
||||||
Set<AxolotlAddress> addresses = new HashSet<>();
|
Set<SignalProtocolAddress> addresses = new HashSet<>();
|
||||||
for(Jid jid : getCryptoTargets(conversation)) {
|
for(Jid jid : getCryptoTargets(conversation)) {
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Finding devices without session for " + jid);
|
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Finding devices without session for " + jid);
|
||||||
if (deviceIds.get(jid) != null) {
|
if (deviceIds.get(jid) != null) {
|
||||||
for (Integer foreignId : this.deviceIds.get(jid)) {
|
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) {
|
if (sessions.get(address) == null) {
|
||||||
IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey();
|
IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey();
|
||||||
if (identityKey != null) {
|
if (identityKey != null) {
|
||||||
@ -950,7 +950,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
}
|
}
|
||||||
if (deviceIds.get(account.getJid().toBareJid()) != null) {
|
if (deviceIds.get(account.getJid().toBareJid()) != null) {
|
||||||
for (Integer ownId : this.deviceIds.get(account.getJid().toBareJid())) {
|
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) {
|
if (sessions.get(address) == null) {
|
||||||
IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey();
|
IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey();
|
||||||
if (identityKey != null) {
|
if (identityKey != null) {
|
||||||
@ -975,8 +975,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
public boolean createSessionsIfNeeded(final Conversation conversation) {
|
public boolean createSessionsIfNeeded(final Conversation conversation) {
|
||||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Creating axolotl sessions if needed...");
|
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Creating axolotl sessions if needed...");
|
||||||
boolean newSessions = false;
|
boolean newSessions = false;
|
||||||
Set<AxolotlAddress> addresses = findDevicesWithoutSession(conversation);
|
Set<SignalProtocolAddress> addresses = findDevicesWithoutSession(conversation);
|
||||||
for (AxolotlAddress address : addresses) {
|
for (SignalProtocolAddress address : addresses) {
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Processing device: " + address.toString());
|
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Processing device: " + address.toString());
|
||||||
FetchStatus status = fetchStatusMap.get(address);
|
FetchStatus status = fetchStatusMap.get(address);
|
||||||
if (status == null || status == FetchStatus.TIMEOUT) {
|
if (status == null || status == FetchStatus.TIMEOUT) {
|
||||||
@ -1010,13 +1010,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPendingKeyFetches(Account account, List<Jid> jids) {
|
public boolean hasPendingKeyFetches(Account account, List<Jid> jids) {
|
||||||
AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toPreppedString(), 0);
|
SignalProtocolAddress ownAddress = new SignalProtocolAddress(account.getJid().toBareJid().toPreppedString(), 0);
|
||||||
if (fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING)) {
|
if (fetchStatusMap.getAll(ownAddress.getName()).containsValue(FetchStatus.PENDING)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for(Jid jid : jids) {
|
for(Jid jid : jids) {
|
||||||
AxolotlAddress foreignAddress = new AxolotlAddress(jid.toBareJid().toPreppedString(), 0);
|
SignalProtocolAddress foreignAddress = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), 0);
|
||||||
if (fetchStatusMap.getAll(foreignAddress).containsValue(FetchStatus.PENDING)) {
|
if (fetchStatusMap.getAll(foreignAddress.getName()).containsValue(FetchStatus.PENDING)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1104,7 +1104,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
return axolotlMessage;
|
return axolotlMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private XmppAxolotlSession recreateUncachedSession(AxolotlAddress address) {
|
private XmppAxolotlSession recreateUncachedSession(SignalProtocolAddress address) {
|
||||||
IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey();
|
IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey();
|
||||||
return (identityKey != null)
|
return (identityKey != null)
|
||||||
? new XmppAxolotlSession(account, axolotlStore, address, identityKey)
|
? new XmppAxolotlSession(account, axolotlStore, address, identityKey)
|
||||||
@ -1112,7 +1112,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private XmppAxolotlSession getReceivingSession(XmppAxolotlMessage message) {
|
private XmppAxolotlSession getReceivingSession(XmppAxolotlMessage message) {
|
||||||
AxolotlAddress senderAddress = new AxolotlAddress(message.getFrom().toPreppedString(),
|
SignalProtocolAddress senderAddress = new SignalProtocolAddress(message.getFrom().toPreppedString(),
|
||||||
message.getSenderDeviceId());
|
message.getSenderDeviceId());
|
||||||
XmppAxolotlSession session = sessions.get(senderAddress);
|
XmppAxolotlSession session = sessions.get(senderAddress);
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
|
@ -3,17 +3,17 @@ package eu.siacs.conversations.crypto.axolotl;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.LruCache;
|
import android.util.LruCache;
|
||||||
|
|
||||||
import org.whispersystems.libaxolotl.AxolotlAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.libaxolotl.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libaxolotl.IdentityKeyPair;
|
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||||
import org.whispersystems.libaxolotl.InvalidKeyIdException;
|
import org.whispersystems.libsignal.InvalidKeyIdException;
|
||||||
import org.whispersystems.libaxolotl.ecc.Curve;
|
import org.whispersystems.libsignal.ecc.Curve;
|
||||||
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
|
import org.whispersystems.libsignal.ecc.ECKeyPair;
|
||||||
import org.whispersystems.libaxolotl.state.AxolotlStore;
|
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
||||||
import org.whispersystems.libaxolotl.state.PreKeyRecord;
|
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||||
import org.whispersystems.libaxolotl.state.SessionRecord;
|
import org.whispersystems.libsignal.state.SessionRecord;
|
||||||
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.libaxolotl.util.KeyHelper;
|
import org.whispersystems.libsignal.util.KeyHelper;
|
||||||
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -23,7 +23,7 @@ import eu.siacs.conversations.Config;
|
|||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
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 PREKEY_TABLENAME = "prekeys";
|
||||||
public static final String SIGNED_PREKEY_TABLENAME = "signed_prekeys";
|
public static final String SIGNED_PREKEY_TABLENAME = "signed_prekeys";
|
||||||
@ -179,17 +179,18 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||||||
* <p/>
|
* <p/>
|
||||||
* Store a remote client's identity key as trusted.
|
* 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.
|
* @param identityKey The remote client's identity key.
|
||||||
|
* @return true on success
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void saveIdentity(String name, IdentityKey identityKey) {
|
public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityKey) {
|
||||||
if (!mXmppConnectionService.databaseBackend.loadIdentityKeys(account, name).contains(identityKey)) {
|
if (!mXmppConnectionService.databaseBackend.loadIdentityKeys(account, address.getName()).contains(identityKey)) {
|
||||||
String fingerprint = identityKey.getFingerprint().replaceAll("\\s", "");
|
String fingerprint = identityKey.getFingerprint().replaceAll("\\s", "");
|
||||||
FingerprintStatus status = getFingerprintStatus(fingerprint);
|
FingerprintStatus status = getFingerprintStatus(fingerprint);
|
||||||
if (status == null) {
|
if (status == null) {
|
||||||
if (mXmppConnectionService.blindTrustBeforeVerification() && !account.getAxolotlService().hasVerifiedKeys(name)) {
|
if (mXmppConnectionService.blindTrustBeforeVerification() && !account.getAxolotlService().hasVerifiedKeys(address.getName())) {
|
||||||
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": blindly trusted "+fingerprint+" of "+name);
|
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": blindly trusted "+fingerprint+" of "+address.getName());
|
||||||
status = FingerprintStatus.createActiveTrusted();
|
status = FingerprintStatus.createActiveTrusted();
|
||||||
} else {
|
} else {
|
||||||
status = FingerprintStatus.createActiveUndecided();
|
status = FingerprintStatus.createActiveUndecided();
|
||||||
@ -197,9 +198,10 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||||||
} else {
|
} else {
|
||||||
status = status.toActive();
|
status = status.toActive();
|
||||||
}
|
}
|
||||||
mXmppConnectionService.databaseBackend.storeIdentityKey(account, name, identityKey, status);
|
mXmppConnectionService.databaseBackend.storeIdentityKey(account, address.getName(), identityKey, status);
|
||||||
trustCache.remove(fingerprint);
|
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
|
* store. Only if it mismatches an entry in the local store is it considered
|
||||||
* 'untrusted.'
|
* 'untrusted.'
|
||||||
*
|
*
|
||||||
* @param name The name of the remote client.
|
|
||||||
* @param identityKey The identity key to verify.
|
* @param identityKey The identity key to verify.
|
||||||
* @return true if trusted, false if untrusted.
|
* @return true if trusted, false if untrusted.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
|
public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +265,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||||||
* a new SessionRecord if one does not currently exist.
|
* a new SessionRecord if one does not currently exist.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public SessionRecord loadSession(AxolotlAddress address) {
|
public SessionRecord loadSession(SignalProtocolAddress address) {
|
||||||
SessionRecord session = mXmppConnectionService.databaseBackend.loadSession(this.account, address);
|
SessionRecord session = mXmppConnectionService.databaseBackend.loadSession(this.account, address);
|
||||||
return (session != null) ? session : new SessionRecord();
|
return (session != null) ? session : new SessionRecord();
|
||||||
}
|
}
|
||||||
@ -278,7 +279,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||||||
@Override
|
@Override
|
||||||
public List<Integer> getSubDeviceSessions(String name) {
|
public List<Integer> getSubDeviceSessions(String name) {
|
||||||
return mXmppConnectionService.databaseBackend.getSubDeviceSessions(account,
|
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.
|
* @param record the current SessionRecord for the remote client.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void storeSession(AxolotlAddress address, SessionRecord record) {
|
public void storeSession(SignalProtocolAddress address, SessionRecord record) {
|
||||||
mXmppConnectionService.databaseBackend.storeSession(account, address, 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.
|
* @return true if a {@link SessionRecord} exists, false otherwise.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean containsSession(AxolotlAddress address) {
|
public boolean containsSession(SignalProtocolAddress address) {
|
||||||
return mXmppConnectionService.databaseBackend.containsSession(account, address);
|
return mXmppConnectionService.databaseBackend.containsSession(account, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +310,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||||||
* @param address the address of the remote client.
|
* @param address the address of the remote client.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void deleteSession(AxolotlAddress address) {
|
public void deleteSession(SignalProtocolAddress address) {
|
||||||
mXmppConnectionService.databaseBackend.deleteSession(account, address);
|
mXmppConnectionService.databaseBackend.deleteSession(account, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +321,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void deleteAllSessions(String name) {
|
public void deleteAllSessions(String name) {
|
||||||
AxolotlAddress address = new AxolotlAddress(name, 0);
|
SignalProtocolAddress address = new SignalProtocolAddress(name, 0);
|
||||||
mXmppConnectionService.databaseBackend.deleteAllSessions(account,
|
mXmppConnectionService.databaseBackend.deleteAllSessions(account,
|
||||||
address);
|
address);
|
||||||
}
|
}
|
||||||
|
@ -3,39 +3,40 @@ package eu.siacs.conversations.crypto.axolotl;
|
|||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.whispersystems.libaxolotl.AxolotlAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.libaxolotl.DuplicateMessageException;
|
import org.whispersystems.libsignal.DuplicateMessageException;
|
||||||
import org.whispersystems.libaxolotl.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libaxolotl.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libaxolotl.InvalidKeyIdException;
|
import org.whispersystems.libsignal.InvalidKeyIdException;
|
||||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
import org.whispersystems.libsignal.InvalidMessageException;
|
||||||
import org.whispersystems.libaxolotl.InvalidVersionException;
|
import org.whispersystems.libsignal.InvalidVersionException;
|
||||||
import org.whispersystems.libaxolotl.LegacyMessageException;
|
import org.whispersystems.libsignal.LegacyMessageException;
|
||||||
import org.whispersystems.libaxolotl.NoSessionException;
|
import org.whispersystems.libsignal.NoSessionException;
|
||||||
import org.whispersystems.libaxolotl.SessionCipher;
|
import org.whispersystems.libsignal.SessionCipher;
|
||||||
import org.whispersystems.libaxolotl.UntrustedIdentityException;
|
import org.whispersystems.libsignal.UntrustedIdentityException;
|
||||||
import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
|
import org.whispersystems.libsignal.protocol.CiphertextMessage;
|
||||||
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
|
import org.whispersystems.libsignal.protocol.PreKeySignalMessage;
|
||||||
import org.whispersystems.libaxolotl.protocol.WhisperMessage;
|
import org.whispersystems.libsignal.protocol.SignalMessage;
|
||||||
import org.whispersystems.libaxolotl.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
|
|
||||||
public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> {
|
public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> {
|
||||||
private final SessionCipher cipher;
|
private final SessionCipher cipher;
|
||||||
private final SQLiteAxolotlStore sqLiteAxolotlStore;
|
private final SQLiteAxolotlStore sqLiteAxolotlStore;
|
||||||
private final AxolotlAddress remoteAddress;
|
private final SignalProtocolAddress remoteAddress;
|
||||||
private final Account account;
|
private final Account account;
|
||||||
private IdentityKey identityKey;
|
private IdentityKey identityKey;
|
||||||
private Integer preKeyId = null;
|
private Integer preKeyId = null;
|
||||||
private boolean fresh = true;
|
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(account, store, remoteAddress);
|
||||||
this.identityKey = identityKey;
|
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.cipher = new SessionCipher(store, remoteAddress);
|
||||||
this.remoteAddress = remoteAddress;
|
this.remoteAddress = remoteAddress;
|
||||||
this.sqLiteAxolotlStore = store;
|
this.sqLiteAxolotlStore = store;
|
||||||
@ -52,14 +53,14 @@ public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getFingerprint() {
|
public String getFingerprint() {
|
||||||
return identityKey == null ? null : identityKey.getFingerprint().replaceAll("\\s", "");
|
return identityKey == null ? null : CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentityKey getIdentityKey() {
|
public IdentityKey getIdentityKey() {
|
||||||
return identityKey;
|
return identityKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AxolotlAddress getRemoteAddress() {
|
public SignalProtocolAddress getRemoteAddress() {
|
||||||
return remoteAddress;
|
return remoteAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,9 +89,9 @@ public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> {
|
|||||||
try {
|
try {
|
||||||
CiphertextMessage ciphertextMessage;
|
CiphertextMessage ciphertextMessage;
|
||||||
try {
|
try {
|
||||||
ciphertextMessage = new PreKeyWhisperMessage(encryptedKey.key);
|
ciphertextMessage = new PreKeySignalMessage(encryptedKey.key);
|
||||||
Optional<Integer> optionalPreKeyId = ((PreKeyWhisperMessage) ciphertextMessage).getPreKeyId();
|
Optional<Integer> optionalPreKeyId = ((PreKeySignalMessage) ciphertextMessage).getPreKeyId();
|
||||||
IdentityKey identityKey = ((PreKeyWhisperMessage) ciphertextMessage).getIdentityKey();
|
IdentityKey identityKey = ((PreKeySignalMessage) ciphertextMessage).getIdentityKey();
|
||||||
if (!optionalPreKeyId.isPresent()) {
|
if (!optionalPreKeyId.isPresent()) {
|
||||||
throw new CryptoFailedException("PreKeyWhisperMessage did not contain a PreKeyId");
|
throw new CryptoFailedException("PreKeyWhisperMessage did not contain a PreKeyId");
|
||||||
}
|
}
|
||||||
@ -100,12 +101,12 @@ public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> {
|
|||||||
}
|
}
|
||||||
this.identityKey = identityKey;
|
this.identityKey = identityKey;
|
||||||
} catch (InvalidVersionException | InvalidMessageException e) {
|
} catch (InvalidVersionException | InvalidMessageException e) {
|
||||||
ciphertextMessage = new WhisperMessage(encryptedKey.key);
|
ciphertextMessage = new SignalMessage(encryptedKey.key);
|
||||||
}
|
}
|
||||||
if (ciphertextMessage instanceof PreKeyWhisperMessage) {
|
if (ciphertextMessage instanceof PreKeySignalMessage) {
|
||||||
plaintext = cipher.decrypt((PreKeyWhisperMessage) ciphertextMessage);
|
plaintext = cipher.decrypt((PreKeySignalMessage) ciphertextMessage);
|
||||||
} else {
|
} else {
|
||||||
plaintext = cipher.decrypt((WhisperMessage) ciphertextMessage);
|
plaintext = cipher.decrypt((SignalMessage) ciphertextMessage);
|
||||||
}
|
}
|
||||||
} catch (InvalidKeyException | LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException | InvalidKeyIdException | UntrustedIdentityException e) {
|
} catch (InvalidKeyException | LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException | InvalidKeyIdException | UntrustedIdentityException e) {
|
||||||
if (!(e instanceof DuplicateMessageException)) {
|
if (!(e instanceof DuplicateMessageException)) {
|
||||||
@ -126,8 +127,12 @@ public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> {
|
|||||||
public AxolotlKey processSending(@NonNull byte[] outgoingMessage) {
|
public AxolotlKey processSending(@NonNull byte[] outgoingMessage) {
|
||||||
FingerprintStatus status = getTrust();
|
FingerprintStatus status = getTrust();
|
||||||
if (status.isTrustedAndActive()) {
|
if (status.isTrustedAndActive()) {
|
||||||
|
try {
|
||||||
CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage);
|
CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage);
|
||||||
return new AxolotlKey(ciphertextMessage.serialize(),ciphertextMessage.getType() == CiphertextMessage.PREKEY_TYPE);
|
return new AxolotlKey(ciphertextMessage.serialize(),ciphertextMessage.getType() == CiphertextMessage.PREKEY_TYPE);
|
||||||
|
} catch (UntrustedIdentityException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@ import android.os.Bundle;
|
|||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.whispersystems.libaxolotl.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
|
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||||
import org.whispersystems.libaxolotl.state.PreKeyRecord;
|
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||||
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
@ -5,10 +5,10 @@ import android.util.Base64;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import org.whispersystems.libaxolotl.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libaxolotl.ecc.Curve;
|
import org.whispersystems.libsignal.ecc.Curve;
|
||||||
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
|
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||||
import org.whispersystems.libaxolotl.state.PreKeyBundle;
|
import org.whispersystems.libsignal.state.PreKeyBundle;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
@ -13,13 +13,13 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.whispersystems.libaxolotl.AxolotlAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.libaxolotl.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libaxolotl.IdentityKeyPair;
|
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||||
import org.whispersystems.libaxolotl.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libaxolotl.state.PreKeyRecord;
|
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||||
import org.whispersystems.libaxolotl.state.SessionRecord;
|
import org.whispersystems.libsignal.state.SessionRecord;
|
||||||
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -305,7 +305,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int ownDeviceId = Integer.valueOf(ownDeviceIdString);
|
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);
|
deleteSession(db, account, ownAddress);
|
||||||
IdentityKeyPair identityKeyPair = loadOwnIdentityKeyPair(db, account);
|
IdentityKeyPair identityKeyPair = loadOwnIdentityKeyPair(db, account);
|
||||||
if (identityKeyPair != null) {
|
if (identityKeyPair != null) {
|
||||||
@ -887,7 +887,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
return maxClearDate;
|
return maxClearDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cursor getCursorForSession(Account account, AxolotlAddress contact) {
|
private Cursor getCursorForSession(Account account, SignalProtocolAddress contact) {
|
||||||
final SQLiteDatabase db = this.getReadableDatabase();
|
final SQLiteDatabase db = this.getReadableDatabase();
|
||||||
String[] selectionArgs = {account.getUuid(),
|
String[] selectionArgs = {account.getUuid(),
|
||||||
contact.getName(),
|
contact.getName(),
|
||||||
@ -901,7 +901,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
null, null, null);
|
null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SessionRecord loadSession(Account account, AxolotlAddress contact) {
|
public SessionRecord loadSession(Account account, SignalProtocolAddress contact) {
|
||||||
SessionRecord session = null;
|
SessionRecord session = null;
|
||||||
Cursor cursor = getCursorForSession(account, contact);
|
Cursor cursor = getCursorForSession(account, contact);
|
||||||
if (cursor.getCount() != 0) {
|
if (cursor.getCount() != 0) {
|
||||||
@ -917,12 +917,12 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Integer> getSubDeviceSessions(Account account, AxolotlAddress contact) {
|
public List<Integer> getSubDeviceSessions(Account account, SignalProtocolAddress contact) {
|
||||||
final SQLiteDatabase db = this.getReadableDatabase();
|
final SQLiteDatabase db = this.getReadableDatabase();
|
||||||
return getSubDeviceSessions(db, account, contact);
|
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<>();
|
List<Integer> devices = new ArrayList<>();
|
||||||
String[] columns = {SQLiteAxolotlStore.DEVICE_ID};
|
String[] columns = {SQLiteAxolotlStore.DEVICE_ID};
|
||||||
String[] selectionArgs = {account.getUuid(),
|
String[] selectionArgs = {account.getUuid(),
|
||||||
@ -943,14 +943,14 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsSession(Account account, AxolotlAddress contact) {
|
public boolean containsSession(Account account, SignalProtocolAddress contact) {
|
||||||
Cursor cursor = getCursorForSession(account, contact);
|
Cursor cursor = getCursorForSession(account, contact);
|
||||||
int count = cursor.getCount();
|
int count = cursor.getCount();
|
||||||
cursor.close();
|
cursor.close();
|
||||||
return count != 0;
|
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();
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(SQLiteAxolotlStore.NAME, contact.getName());
|
values.put(SQLiteAxolotlStore.NAME, contact.getName());
|
||||||
@ -960,12 +960,12 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
db.insert(SQLiteAxolotlStore.SESSION_TABLENAME, null, values);
|
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();
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
deleteSession(db, account, contact);
|
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(),
|
String[] args = {account.getUuid(),
|
||||||
contact.getName(),
|
contact.getName(),
|
||||||
Integer.toString(contact.getDeviceId())};
|
Integer.toString(contact.getDeviceId())};
|
||||||
@ -976,7 +976,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
args);
|
args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteAllSessions(Account account, AxolotlAddress contact) {
|
public void deleteAllSessions(Account account, SignalProtocolAddress contact) {
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
String[] args = {account.getUuid(), contact.getName()};
|
String[] args = {account.getUuid(), contact.getName()};
|
||||||
db.delete(SQLiteAxolotlStore.SESSION_TABLENAME,
|
db.delete(SQLiteAxolotlStore.SESSION_TABLENAME,
|
||||||
|
@ -17,7 +17,7 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.google.zxing.integration.android.IntentIntegrator;
|
import com.google.zxing.integration.android.IntentIntegrator;
|
||||||
|
|
||||||
import org.whispersystems.libaxolotl.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -103,7 +103,7 @@ public final class CryptoHelper {
|
|||||||
} else if (fingerprint.length() < 40) {
|
} else if (fingerprint.length() < 40) {
|
||||||
return fingerprint;
|
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) {
|
for(int i=8;i<builder.length();i+=9) {
|
||||||
builder.insert(i, ' ');
|
builder.insert(i, ' ');
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user