mirror of
https://github.com/moparisthebest/Conversations
synced 2024-11-25 02:02:16 -05:00
Overhauled Message tagging
Messages are now tagged with the IdentityKey fingerprint of the originating session. IdentityKeys have one of three trust states: undecided (default), trusted, and untrusted/not yet trusted.
This commit is contained in:
parent
7f918542c8
commit
d173913eba
@ -85,6 +85,7 @@ public class AxolotlService {
|
|||||||
public static final String DEVICE_ID = "device_id";
|
public static final String DEVICE_ID = "device_id";
|
||||||
public static final String ID = "id";
|
public static final String ID = "id";
|
||||||
public static final String KEY = "key";
|
public static final String KEY = "key";
|
||||||
|
public static final String FINGERPRINT = "fingerprint";
|
||||||
public static final String NAME = "name";
|
public static final String NAME = "name";
|
||||||
public static final String TRUSTED = "trusted";
|
public static final String TRUSTED = "trusted";
|
||||||
public static final String OWN = "ownkey";
|
public static final String OWN = "ownkey";
|
||||||
@ -99,6 +100,23 @@ public class AxolotlService {
|
|||||||
private final int localRegistrationId;
|
private final int localRegistrationId;
|
||||||
private int currentPreKeyId = 0;
|
private int currentPreKeyId = 0;
|
||||||
|
|
||||||
|
public enum Trust {
|
||||||
|
UNDECIDED, // 0
|
||||||
|
TRUSTED,
|
||||||
|
UNTRUSTED;
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
switch(this){
|
||||||
|
case UNDECIDED:
|
||||||
|
return "Trust undecided";
|
||||||
|
case TRUSTED:
|
||||||
|
return "Trusted";
|
||||||
|
case UNTRUSTED:
|
||||||
|
default:
|
||||||
|
return "Untrusted";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private static IdentityKeyPair generateIdentityKeyPair() {
|
private static IdentityKeyPair generateIdentityKeyPair() {
|
||||||
Log.i(Config.LOGTAG, AxolotlService.LOGPREFIX+" : "+"Generating axolotl IdentityKeyPair...");
|
Log.i(Config.LOGTAG, AxolotlService.LOGPREFIX+" : "+"Generating axolotl IdentityKeyPair...");
|
||||||
@ -242,11 +260,17 @@ public class AxolotlService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
|
public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
|
||||||
//Set<IdentityKey> trustedKeys = mXmppConnectionService.databaseBackend.loadIdentityKeys(account, name);
|
|
||||||
//return trustedKeys.isEmpty() || trustedKeys.contains(identityKey);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Trust getFingerprintTrust(String name, String fingerprint) {
|
||||||
|
return mXmppConnectionService.databaseBackend.isIdentityKeyTrusted(account, name, fingerprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFingerprintTrust(String name, String fingerprint, Trust trust) {
|
||||||
|
mXmppConnectionService.databaseBackend.setIdentityKeyTrust(account, name, fingerprint, trust);
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
// SessionStore
|
// SessionStore
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
@ -325,14 +349,6 @@ public class AxolotlService {
|
|||||||
new AxolotlAddress(name, 0));
|
new AxolotlAddress(name, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTrustedSession(AxolotlAddress address) {
|
|
||||||
return mXmppConnectionService.databaseBackend.isTrustedSession(this.account, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTrustedSession(AxolotlAddress address, boolean trusted) {
|
|
||||||
mXmppConnectionService.databaseBackend.setTrustedSession(this.account, address, trusted);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
// PreKeyStore
|
// PreKeyStore
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
@ -453,27 +469,22 @@ public class AxolotlService {
|
|||||||
|
|
||||||
public static class XmppAxolotlSession {
|
public static class XmppAxolotlSession {
|
||||||
private final SessionCipher cipher;
|
private final SessionCipher cipher;
|
||||||
private boolean isTrusted = false;
|
|
||||||
private Integer preKeyId = null;
|
private Integer preKeyId = null;
|
||||||
private final SQLiteAxolotlStore sqLiteAxolotlStore;
|
private final SQLiteAxolotlStore sqLiteAxolotlStore;
|
||||||
private final AxolotlAddress remoteAddress;
|
private final AxolotlAddress remoteAddress;
|
||||||
private final Account account;
|
private final Account account;
|
||||||
|
private String fingerprint = null;
|
||||||
|
|
||||||
|
public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress remoteAddress, String fingerprint) {
|
||||||
|
this(account, store, remoteAddress);
|
||||||
|
this.fingerprint = fingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress remoteAddress) {
|
public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress 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;
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.isTrusted = sqLiteAxolotlStore.isTrustedSession(remoteAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void trust() {
|
|
||||||
sqLiteAxolotlStore.setTrustedSession(remoteAddress, true);
|
|
||||||
this.isTrusted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTrusted() {
|
|
||||||
return this.isTrusted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getPreKeyId() {
|
public Integer getPreKeyId() {
|
||||||
@ -481,19 +492,30 @@ public class AxolotlService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void resetPreKeyId() {
|
public void resetPreKeyId() {
|
||||||
|
|
||||||
preKeyId = null;
|
preKeyId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFingerprint() {
|
||||||
|
return fingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] processReceiving(XmppAxolotlMessage.XmppAxolotlMessageHeader incomingHeader) {
|
public byte[] processReceiving(XmppAxolotlMessage.XmppAxolotlMessageHeader incomingHeader) {
|
||||||
byte[] plaintext = null;
|
byte[] plaintext = null;
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
PreKeyWhisperMessage message = new PreKeyWhisperMessage(incomingHeader.getContents());
|
PreKeyWhisperMessage message = new PreKeyWhisperMessage(incomingHeader.getContents());
|
||||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
|
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
|
||||||
|
String fingerprint = message.getIdentityKey().getFingerprint().replaceAll("\\s", "");
|
||||||
|
if (this.fingerprint != null && !this.fingerprint.equals(fingerprint)) {
|
||||||
|
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Had session with fingerprint "+ this.fingerprint+", received message with fingerprint "+fingerprint);
|
||||||
|
} else {
|
||||||
|
this.fingerprint = fingerprint;
|
||||||
plaintext = cipher.decrypt(message);
|
plaintext = cipher.decrypt(message);
|
||||||
if (message.getPreKeyId().isPresent()) {
|
if (message.getPreKeyId().isPresent()) {
|
||||||
preKeyId = message.getPreKeyId().get();
|
preKeyId = message.getPreKeyId().get();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (InvalidMessageException | InvalidVersionException e) {
|
} catch (InvalidMessageException | InvalidVersionException e) {
|
||||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"WhisperMessage received");
|
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"WhisperMessage received");
|
||||||
WhisperMessage message = new WhisperMessage(incomingHeader.getContents());
|
WhisperMessage message = new WhisperMessage(incomingHeader.getContents());
|
||||||
@ -582,7 +604,9 @@ public class AxolotlService {
|
|||||||
List<Integer> deviceIDs = store.getSubDeviceSessions(address);
|
List<Integer> deviceIDs = store.getSubDeviceSessions(address);
|
||||||
for (Integer deviceId : deviceIDs) {
|
for (Integer deviceId : deviceIDs) {
|
||||||
AxolotlAddress axolotlAddress = new AxolotlAddress(address, deviceId);
|
AxolotlAddress axolotlAddress = new AxolotlAddress(address, deviceId);
|
||||||
this.put(axolotlAddress, new XmppAxolotlSession(account, store, axolotlAddress));
|
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Building session for remote address: "+axolotlAddress.toString());
|
||||||
|
String fingerprint = store.loadSession(axolotlAddress).getSessionState().getRemoteIdentityKey().getFingerprint().replaceAll("\\s", "");
|
||||||
|
this.put(axolotlAddress, new XmppAxolotlSession(account, store, axolotlAddress, fingerprint));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -619,18 +643,6 @@ public class AxolotlService {
|
|||||||
return axolotlStore.getIdentityKeyPair().getPublicKey();
|
return axolotlStore.getIdentityKeyPair().getPublicKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void trustSession(AxolotlAddress counterpart) {
|
|
||||||
XmppAxolotlSession session = sessions.get(counterpart);
|
|
||||||
if (session != null) {
|
|
||||||
session.trust();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTrustedSession(AxolotlAddress counterpart) {
|
|
||||||
XmppAxolotlSession session = sessions.get(counterpart);
|
|
||||||
return session != null && session.isTrusted();
|
|
||||||
}
|
|
||||||
|
|
||||||
private AxolotlAddress getAddressForJid(Jid jid) {
|
private AxolotlAddress getAddressForJid(Jid jid) {
|
||||||
return new AxolotlAddress(jid.toString(), 0);
|
return new AxolotlAddress(jid.toString(), 0);
|
||||||
}
|
}
|
||||||
@ -808,11 +820,19 @@ public class AxolotlService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isContactAxolotlCapable(Contact contact) {
|
public boolean isContactAxolotlCapable(Contact contact) {
|
||||||
|
|
||||||
Jid jid = contact.getJid().toBareJid();
|
Jid jid = contact.getJid().toBareJid();
|
||||||
AxolotlAddress address = new AxolotlAddress(jid.toString(), 0);
|
AxolotlAddress address = new AxolotlAddress(jid.toString(), 0);
|
||||||
return sessions.hasAny(address) ||
|
return sessions.hasAny(address) ||
|
||||||
( deviceIds.containsKey(jid) && !deviceIds.get(jid).isEmpty());
|
( deviceIds.containsKey(jid) && !deviceIds.get(jid).isEmpty());
|
||||||
}
|
}
|
||||||
|
public SQLiteAxolotlStore.Trust getFingerprintTrust(String name, String fingerprint) {
|
||||||
|
return axolotlStore.getFingerprintTrust(name, fingerprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFingerprintTrust(String name, String fingerprint, SQLiteAxolotlStore.Trust trust) {
|
||||||
|
axolotlStore.setFingerprintTrust(name, fingerprint, trust);
|
||||||
|
}
|
||||||
|
|
||||||
private void buildSessionFromPEP(final Conversation conversation, final AxolotlAddress address) {
|
private void buildSessionFromPEP(final Conversation conversation, final AxolotlAddress address) {
|
||||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Building new sesstion for " + address.getDeviceId());
|
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Building new sesstion for " + address.getDeviceId());
|
||||||
@ -851,7 +871,7 @@ public class AxolotlService {
|
|||||||
try {
|
try {
|
||||||
SessionBuilder builder = new SessionBuilder(axolotlStore, address);
|
SessionBuilder builder = new SessionBuilder(axolotlStore, address);
|
||||||
builder.process(preKeyBundle);
|
builder.process(preKeyBundle);
|
||||||
XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address);
|
XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey().getFingerprint().replaceAll("\\s", ""));
|
||||||
sessions.put(address, session);
|
sessions.put(address, session);
|
||||||
fetchStatusMap.put(address, FetchStatus.SUCCESS);
|
fetchStatusMap.put(address, FetchStatus.SUCCESS);
|
||||||
} catch (UntrustedIdentityException|InvalidKeyException e) {
|
} catch (UntrustedIdentityException|InvalidKeyException e) {
|
||||||
@ -1003,7 +1023,7 @@ public class AxolotlService {
|
|||||||
byte[] payloadKey = session.processReceiving(header);
|
byte[] payloadKey = session.processReceiving(header);
|
||||||
if (payloadKey != null) {
|
if (payloadKey != null) {
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Got payload key from axolotl header. Decrypting message...");
|
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Got payload key from axolotl header. Decrypting message...");
|
||||||
plaintextMessage = message.decrypt(session, payloadKey);
|
plaintextMessage = message.decrypt(session, payloadKey, session.getFingerprint());
|
||||||
}
|
}
|
||||||
Integer preKeyId = session.getPreKeyId();
|
Integer preKeyId = session.getPreKeyId();
|
||||||
if (preKeyId != null) {
|
if (preKeyId != null) {
|
||||||
|
@ -67,10 +67,12 @@ public class XmppAxolotlMessage {
|
|||||||
public static class XmppAxolotlPlaintextMessage {
|
public static class XmppAxolotlPlaintextMessage {
|
||||||
private final AxolotlService.XmppAxolotlSession session;
|
private final AxolotlService.XmppAxolotlSession session;
|
||||||
private final String plaintext;
|
private final String plaintext;
|
||||||
|
private final String fingerprint;
|
||||||
|
|
||||||
public XmppAxolotlPlaintextMessage(AxolotlService.XmppAxolotlSession session, String plaintext) {
|
public XmppAxolotlPlaintextMessage(AxolotlService.XmppAxolotlSession session, String plaintext, String fingerprint) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.plaintext = plaintext;
|
this.plaintext = plaintext;
|
||||||
|
this.fingerprint = fingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPlaintext() {
|
public String getPlaintext() {
|
||||||
@ -81,6 +83,9 @@ public class XmppAxolotlMessage {
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFingerprint() {
|
||||||
|
return fingerprint;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public XmppAxolotlMessage(Jid from, Element axolotlMessage) {
|
public XmppAxolotlMessage(Jid from, Element axolotlMessage) {
|
||||||
@ -167,7 +172,7 @@ public class XmppAxolotlMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public XmppAxolotlPlaintextMessage decrypt(AxolotlService.XmppAxolotlSession session, byte[] key) {
|
public XmppAxolotlPlaintextMessage decrypt(AxolotlService.XmppAxolotlSession session, byte[] key, String fingerprint) {
|
||||||
XmppAxolotlPlaintextMessage plaintextMessage = null;
|
XmppAxolotlPlaintextMessage plaintextMessage = null;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@ -178,7 +183,7 @@ public class XmppAxolotlMessage {
|
|||||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
|
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
|
||||||
|
|
||||||
String plaintext = new String(cipher.doFinal(ciphertext));
|
String plaintext = new String(cipher.doFinal(ciphertext));
|
||||||
plaintextMessage = new XmppAxolotlPlaintextMessage(session, plaintext);
|
plaintextMessage = new XmppAxolotlPlaintextMessage(session, plaintext, fingerprint);
|
||||||
|
|
||||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
|
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
|
||||||
| InvalidAlgorithmParameterException | IllegalBlockSizeException
|
| InvalidAlgorithmParameterException | IllegalBlockSizeException
|
||||||
|
@ -54,6 +54,7 @@ public class Message extends AbstractEntity {
|
|||||||
public static final String REMOTE_MSG_ID = "remoteMsgId";
|
public static final String REMOTE_MSG_ID = "remoteMsgId";
|
||||||
public static final String SERVER_MSG_ID = "serverMsgId";
|
public static final String SERVER_MSG_ID = "serverMsgId";
|
||||||
public static final String RELATIVE_FILE_PATH = "relativeFilePath";
|
public static final String RELATIVE_FILE_PATH = "relativeFilePath";
|
||||||
|
public static final String FINGERPRINT = "axolotl_fingerprint";
|
||||||
public static final String ME_COMMAND = "/me ";
|
public static final String ME_COMMAND = "/me ";
|
||||||
|
|
||||||
|
|
||||||
@ -67,7 +68,6 @@ public class Message extends AbstractEntity {
|
|||||||
protected int encryption;
|
protected int encryption;
|
||||||
protected int status;
|
protected int status;
|
||||||
protected int type;
|
protected int type;
|
||||||
private AxolotlService.XmppAxolotlSession axolotlSession = null;
|
|
||||||
protected String relativeFilePath;
|
protected String relativeFilePath;
|
||||||
protected boolean read = true;
|
protected boolean read = true;
|
||||||
protected String remoteMsgId = null;
|
protected String remoteMsgId = null;
|
||||||
@ -76,6 +76,7 @@ public class Message extends AbstractEntity {
|
|||||||
protected Transferable transferable = null;
|
protected Transferable transferable = null;
|
||||||
private Message mNextMessage = null;
|
private Message mNextMessage = null;
|
||||||
private Message mPreviousMessage = null;
|
private Message mPreviousMessage = null;
|
||||||
|
private String axolotlFingerprint = null;
|
||||||
|
|
||||||
private Message() {
|
private Message() {
|
||||||
|
|
||||||
@ -97,6 +98,7 @@ public class Message extends AbstractEntity {
|
|||||||
TYPE_TEXT,
|
TYPE_TEXT,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
null);
|
null);
|
||||||
this.conversation = conversation;
|
this.conversation = conversation;
|
||||||
}
|
}
|
||||||
@ -104,7 +106,7 @@ public class Message extends AbstractEntity {
|
|||||||
private Message(final String uuid, final String conversationUUid, final Jid counterpart,
|
private Message(final String uuid, final String conversationUUid, final Jid counterpart,
|
||||||
final Jid trueCounterpart, final String body, final long timeSent,
|
final Jid trueCounterpart, final String body, final long timeSent,
|
||||||
final int encryption, final int status, final int type, final String remoteMsgId,
|
final int encryption, final int status, final int type, final String remoteMsgId,
|
||||||
final String relativeFilePath, final String serverMsgId) {
|
final String relativeFilePath, final String serverMsgId, final String fingerprint) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.conversationUuid = conversationUUid;
|
this.conversationUuid = conversationUUid;
|
||||||
this.counterpart = counterpart;
|
this.counterpart = counterpart;
|
||||||
@ -117,6 +119,7 @@ public class Message extends AbstractEntity {
|
|||||||
this.remoteMsgId = remoteMsgId;
|
this.remoteMsgId = remoteMsgId;
|
||||||
this.relativeFilePath = relativeFilePath;
|
this.relativeFilePath = relativeFilePath;
|
||||||
this.serverMsgId = serverMsgId;
|
this.serverMsgId = serverMsgId;
|
||||||
|
this.axolotlFingerprint = fingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Message fromCursor(Cursor cursor) {
|
public static Message fromCursor(Cursor cursor) {
|
||||||
@ -153,7 +156,8 @@ public class Message extends AbstractEntity {
|
|||||||
cursor.getInt(cursor.getColumnIndex(TYPE)),
|
cursor.getInt(cursor.getColumnIndex(TYPE)),
|
||||||
cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)),
|
cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)),
|
||||||
cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)),
|
cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)),
|
||||||
cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)));
|
cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)),
|
||||||
|
cursor.getString(cursor.getColumnIndex(FINGERPRINT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Message createStatusMessage(Conversation conversation, String body) {
|
public static Message createStatusMessage(Conversation conversation, String body) {
|
||||||
@ -187,6 +191,7 @@ public class Message extends AbstractEntity {
|
|||||||
values.put(REMOTE_MSG_ID, remoteMsgId);
|
values.put(REMOTE_MSG_ID, remoteMsgId);
|
||||||
values.put(RELATIVE_FILE_PATH, relativeFilePath);
|
values.put(RELATIVE_FILE_PATH, relativeFilePath);
|
||||||
values.put(SERVER_MSG_ID, serverMsgId);
|
values.put(SERVER_MSG_ID, serverMsgId);
|
||||||
|
values.put(FINGERPRINT, axolotlFingerprint);
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,11 +672,7 @@ public class Message extends AbstractEntity {
|
|||||||
public int height = 0;
|
public int height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTrusted() {
|
public void setAxolotlFingerprint(String fingerprint) {
|
||||||
return this.axolotlSession != null && this.axolotlSession.isTrusted();
|
this.axolotlFingerprint = fingerprint;
|
||||||
}
|
|
||||||
|
|
||||||
public void setAxolotlSession(AxolotlService.XmppAxolotlSession session) {
|
|
||||||
this.axolotlSession = session;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,8 @@ public class MessageParser extends AbstractParser implements
|
|||||||
XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = service.processReceiving(xmppAxolotlMessage);
|
XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = service.processReceiving(xmppAxolotlMessage);
|
||||||
if(plaintextMessage != null) {
|
if(plaintextMessage != null) {
|
||||||
finishedMessage = new Message(conversation, plaintextMessage.getPlaintext(), Message.ENCRYPTION_AXOLOTL, status);
|
finishedMessage = new Message(conversation, plaintextMessage.getPlaintext(), Message.ENCRYPTION_AXOLOTL, status);
|
||||||
finishedMessage.setAxolotlSession(plaintextMessage.getSession());
|
finishedMessage.setAxolotlFingerprint(plaintextMessage.getFingerprint());
|
||||||
|
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(finishedMessage.getConversation().getAccount())+" Received Message with session fingerprint: "+plaintextMessage.getFingerprint());
|
||||||
}
|
}
|
||||||
|
|
||||||
return finishedMessage;
|
return finishedMessage;
|
||||||
|
@ -82,7 +82,6 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
+ AxolotlService.SQLiteAxolotlStore.ACCOUNT + " TEXT, "
|
+ AxolotlService.SQLiteAxolotlStore.ACCOUNT + " TEXT, "
|
||||||
+ AxolotlService.SQLiteAxolotlStore.NAME + " TEXT, "
|
+ AxolotlService.SQLiteAxolotlStore.NAME + " TEXT, "
|
||||||
+ AxolotlService.SQLiteAxolotlStore.DEVICE_ID + " INTEGER, "
|
+ AxolotlService.SQLiteAxolotlStore.DEVICE_ID + " INTEGER, "
|
||||||
+ AxolotlService.SQLiteAxolotlStore.TRUSTED + " INTEGER, "
|
|
||||||
+ AxolotlService.SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY("
|
+ AxolotlService.SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY("
|
||||||
+ AxolotlService.SQLiteAxolotlStore.ACCOUNT
|
+ AxolotlService.SQLiteAxolotlStore.ACCOUNT
|
||||||
+ ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, "
|
+ ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, "
|
||||||
@ -97,6 +96,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
+ AxolotlService.SQLiteAxolotlStore.ACCOUNT + " TEXT, "
|
+ AxolotlService.SQLiteAxolotlStore.ACCOUNT + " TEXT, "
|
||||||
+ AxolotlService.SQLiteAxolotlStore.NAME + " TEXT, "
|
+ AxolotlService.SQLiteAxolotlStore.NAME + " TEXT, "
|
||||||
+ AxolotlService.SQLiteAxolotlStore.OWN + " INTEGER, "
|
+ AxolotlService.SQLiteAxolotlStore.OWN + " INTEGER, "
|
||||||
|
+ AxolotlService.SQLiteAxolotlStore.FINGERPRINT + " TEXT PRIMARY KEY ON CONFLICT IGNORE, "
|
||||||
|
+ AxolotlService.SQLiteAxolotlStore.TRUSTED + " INTEGER, "
|
||||||
+ AxolotlService.SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY("
|
+ AxolotlService.SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY("
|
||||||
+ AxolotlService.SQLiteAxolotlStore.ACCOUNT
|
+ AxolotlService.SQLiteAxolotlStore.ACCOUNT
|
||||||
+ ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE "
|
+ ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE "
|
||||||
@ -132,6 +133,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
+ Message.STATUS + " NUMBER," + Message.TYPE + " NUMBER, "
|
+ Message.STATUS + " NUMBER," + Message.TYPE + " NUMBER, "
|
||||||
+ Message.RELATIVE_FILE_PATH + " TEXT, "
|
+ Message.RELATIVE_FILE_PATH + " TEXT, "
|
||||||
+ Message.SERVER_MSG_ID + " TEXT, "
|
+ Message.SERVER_MSG_ID + " TEXT, "
|
||||||
|
+ Message.FINGERPRINT + " TEXT, "
|
||||||
+ Message.REMOTE_MSG_ID + " TEXT, FOREIGN KEY("
|
+ Message.REMOTE_MSG_ID + " TEXT, FOREIGN KEY("
|
||||||
+ Message.CONVERSATION + ") REFERENCES "
|
+ Message.CONVERSATION + ") REFERENCES "
|
||||||
+ Conversation.TABLENAME + "(" + Conversation.UUID
|
+ Conversation.TABLENAME + "(" + Conversation.UUID
|
||||||
@ -284,6 +286,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
}
|
}
|
||||||
if (oldVersion < 15 && newVersion >= 15) {
|
if (oldVersion < 15 && newVersion >= 15) {
|
||||||
recreateAxolotlDb();
|
recreateAxolotlDb();
|
||||||
|
db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "
|
||||||
|
+ Message.FINGERPRINT + " TEXT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,28 +649,6 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
args);
|
args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTrustedSession(Account account, AxolotlAddress contact) {
|
|
||||||
boolean trusted = false;
|
|
||||||
Cursor cursor = getCursorForSession(account, contact);
|
|
||||||
if(cursor.getCount() != 0) {
|
|
||||||
cursor.moveToFirst();
|
|
||||||
trusted = cursor.getInt(cursor.getColumnIndex(
|
|
||||||
AxolotlService.SQLiteAxolotlStore.TRUSTED)) > 0;
|
|
||||||
}
|
|
||||||
cursor.close();
|
|
||||||
return trusted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTrustedSession(Account account, AxolotlAddress contact, boolean trusted) {
|
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
values.put(AxolotlService.SQLiteAxolotlStore.NAME, contact.getName());
|
|
||||||
values.put(AxolotlService.SQLiteAxolotlStore.DEVICE_ID, contact.getDeviceId());
|
|
||||||
values.put(AxolotlService.SQLiteAxolotlStore.ACCOUNT, account.getUuid());
|
|
||||||
values.put(AxolotlService.SQLiteAxolotlStore.TRUSTED, trusted?1:0);
|
|
||||||
db.insert(AxolotlService.SQLiteAxolotlStore.SESSION_TABLENAME, null, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Cursor getCursorForPreKey(Account account, int preKeyId) {
|
private Cursor getCursorForPreKey(Account account, int preKeyId) {
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
String[] columns = {AxolotlService.SQLiteAxolotlStore.KEY};
|
String[] columns = {AxolotlService.SQLiteAxolotlStore.KEY};
|
||||||
@ -796,17 +778,28 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Cursor getIdentityKeyCursor(Account account, String name, boolean own) {
|
private Cursor getIdentityKeyCursor(Account account, String name, boolean own) {
|
||||||
|
return getIdentityKeyCursor(account, name, own, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cursor getIdentityKeyCursor(Account account, String name, boolean own, String fingerprint) {
|
||||||
final SQLiteDatabase db = this.getReadableDatabase();
|
final SQLiteDatabase db = this.getReadableDatabase();
|
||||||
String[] columns = {AxolotlService.SQLiteAxolotlStore.KEY};
|
String[] columns = {AxolotlService.SQLiteAxolotlStore.TRUSTED,
|
||||||
String[] selectionArgs = {account.getUuid(),
|
AxolotlService.SQLiteAxolotlStore.KEY};
|
||||||
name,
|
ArrayList<String> selectionArgs = new ArrayList<>(4);
|
||||||
own?"1":"0"};
|
selectionArgs.add(account.getUuid());
|
||||||
|
selectionArgs.add(name);
|
||||||
|
selectionArgs.add(own?"1":"0");
|
||||||
|
String selectionString = AxolotlService.SQLiteAxolotlStore.ACCOUNT + " = ? AND "
|
||||||
|
+ AxolotlService.SQLiteAxolotlStore.NAME + " = ? AND "
|
||||||
|
+ AxolotlService.SQLiteAxolotlStore.OWN + " = ? ";
|
||||||
|
if (fingerprint != null){
|
||||||
|
selectionArgs.add(fingerprint);
|
||||||
|
selectionString += "AND " +AxolotlService.SQLiteAxolotlStore.FINGERPRINT + " = ? ";
|
||||||
|
}
|
||||||
Cursor cursor = db.query(AxolotlService.SQLiteAxolotlStore.IDENTITIES_TABLENAME,
|
Cursor cursor = db.query(AxolotlService.SQLiteAxolotlStore.IDENTITIES_TABLENAME,
|
||||||
columns,
|
columns,
|
||||||
AxolotlService.SQLiteAxolotlStore.ACCOUNT + " = ? AND "
|
selectionString,
|
||||||
+ AxolotlService.SQLiteAxolotlStore.NAME + " = ? AND "
|
selectionArgs.toArray(new String[selectionArgs.size()]),
|
||||||
+ AxolotlService.SQLiteAxolotlStore.OWN + " = ? ",
|
|
||||||
selectionArgs,
|
|
||||||
null, null, null);
|
null, null, null);
|
||||||
|
|
||||||
return cursor;
|
return cursor;
|
||||||
@ -844,22 +837,52 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||||||
return identityKeys;
|
return identityKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeIdentityKey(Account account, String name, boolean own, String base64Serialized) {
|
private void storeIdentityKey(Account account, String name, boolean own, String fingerprint, String base64Serialized) {
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(AxolotlService.SQLiteAxolotlStore.ACCOUNT, account.getUuid());
|
values.put(AxolotlService.SQLiteAxolotlStore.ACCOUNT, account.getUuid());
|
||||||
values.put(AxolotlService.SQLiteAxolotlStore.NAME, name);
|
values.put(AxolotlService.SQLiteAxolotlStore.NAME, name);
|
||||||
values.put(AxolotlService.SQLiteAxolotlStore.OWN, own ? 1 : 0);
|
values.put(AxolotlService.SQLiteAxolotlStore.OWN, own ? 1 : 0);
|
||||||
|
values.put(AxolotlService.SQLiteAxolotlStore.FINGERPRINT, fingerprint);
|
||||||
values.put(AxolotlService.SQLiteAxolotlStore.KEY, base64Serialized);
|
values.put(AxolotlService.SQLiteAxolotlStore.KEY, base64Serialized);
|
||||||
db.insert(AxolotlService.SQLiteAxolotlStore.IDENTITIES_TABLENAME, null, values);
|
db.insert(AxolotlService.SQLiteAxolotlStore.IDENTITIES_TABLENAME, null, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AxolotlService.SQLiteAxolotlStore.Trust isIdentityKeyTrusted(Account account, String name, String fingerprint) {
|
||||||
|
Cursor cursor = getIdentityKeyCursor(account, name, false, fingerprint);
|
||||||
|
AxolotlService.SQLiteAxolotlStore.Trust trust = null;
|
||||||
|
if (cursor.getCount() > 0) {
|
||||||
|
cursor.moveToFirst();
|
||||||
|
int trustValue = cursor.getInt(cursor.getColumnIndex(AxolotlService.SQLiteAxolotlStore.TRUSTED));
|
||||||
|
trust = AxolotlService.SQLiteAxolotlStore.Trust.values()[trustValue];
|
||||||
|
}
|
||||||
|
cursor.close();
|
||||||
|
return trust;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setIdentityKeyTrust(Account account, String name, String fingerprint, AxolotlService.SQLiteAxolotlStore.Trust trust) {
|
||||||
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
|
String[] selectionArgs = {
|
||||||
|
account.getUuid(),
|
||||||
|
name,
|
||||||
|
fingerprint
|
||||||
|
};
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(AxolotlService.SQLiteAxolotlStore.TRUSTED, trust.ordinal());
|
||||||
|
int rows = db.update(AxolotlService.SQLiteAxolotlStore.IDENTITIES_TABLENAME, values,
|
||||||
|
AxolotlService.SQLiteAxolotlStore.ACCOUNT + " = ? "
|
||||||
|
+ AxolotlService.SQLiteAxolotlStore.NAME + " = ? "
|
||||||
|
+ AxolotlService.SQLiteAxolotlStore.FINGERPRINT + " = ? ",
|
||||||
|
selectionArgs);
|
||||||
|
return rows == 1;
|
||||||
|
}
|
||||||
|
|
||||||
public void storeIdentityKey(Account account, String name, IdentityKey identityKey) {
|
public void storeIdentityKey(Account account, String name, IdentityKey identityKey) {
|
||||||
storeIdentityKey(account, name, false, Base64.encodeToString(identityKey.serialize(), Base64.DEFAULT));
|
storeIdentityKey(account, name, false, identityKey.getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKey.serialize(), Base64.DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeOwnIdentityKeyPair(Account account, String name, IdentityKeyPair identityKeyPair) {
|
public void storeOwnIdentityKeyPair(Account account, String name, IdentityKeyPair identityKeyPair) {
|
||||||
storeIdentityKey(account, name, true, Base64.encodeToString(identityKeyPair.serialize(),Base64.DEFAULT));
|
storeIdentityKey(account, name, true, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKeyPair.serialize(), Base64.DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recreateAxolotlDb() {
|
public void recreateAxolotlDb() {
|
||||||
|
Loading…
Reference in New Issue
Block a user