aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Straub <andy@strb.org>2015-06-29 13:53:39 +0200
committerAndreas Straub <andy@strb.org>2015-07-19 21:32:26 +0200
commit74026b742bd7e1d4b79fd839f887a0beb940b0dc (patch)
tree96b14e16f0a83daac3ce000d8c20a9ec4c88ca11
parent9e07fc5651015dc60e54bcb2f796d0f932d5f925 (diff)
Save IdentityKeys in database
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java70
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java85
2 files changed, 108 insertions, 47 deletions
diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
index 5c4b34a4..d788ed06 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
@@ -68,12 +68,14 @@ public class AxolotlService {
public static final String PREKEY_TABLENAME = "prekeys";
public static final String SIGNED_PREKEY_TABLENAME = "signed_prekeys";
public static final String SESSION_TABLENAME = "sessions";
+ public static final String IDENTITIES_TABLENAME = "identities";
public static final String ACCOUNT = "account";
public static final String DEVICE_ID = "device_id";
public static final String ID = "id";
public static final String KEY = "key";
public static final String NAME = "name";
public static final String TRUSTED = "trusted";
+ public static final String OWN = "ownkey";
public static final String JSONKEY_IDENTITY_KEY_PAIR = "axolotl_key";
public static final String JSONKEY_REGISTRATION_ID = "axolotl_reg_id";
@@ -82,7 +84,7 @@ public class AxolotlService {
private final Account account;
private final XmppConnectionService mXmppConnectionService;
- private final IdentityKeyPair identityKeyPair;
+ private IdentityKeyPair identityKeyPair;
private final int localRegistrationId;
private int currentPreKeyId = 0;
@@ -104,10 +106,9 @@ public class AxolotlService {
public SQLiteAxolotlStore(Account account, XmppConnectionService service) {
this.account = account;
this.mXmppConnectionService = service;
- this.identityKeyPair = loadIdentityKeyPair();
this.localRegistrationId = loadRegistrationId();
this.currentPreKeyId = loadCurrentPreKeyId();
- for( SignedPreKeyRecord record:loadSignedPreKeys()) {
+ for (SignedPreKeyRecord record : loadSignedPreKeys()) {
Log.d(Config.LOGTAG, "Got Axolotl signed prekey record:" + record.getId());
}
}
@@ -121,26 +122,17 @@ public class AxolotlService {
// --------------------------------------
private IdentityKeyPair loadIdentityKeyPair() {
- String serializedKey = this.account.getKey(JSONKEY_IDENTITY_KEY_PAIR);
- IdentityKeyPair ownKey;
- if( serializedKey != null ) {
- try {
- ownKey = new IdentityKeyPair(Base64.decode(serializedKey,Base64.DEFAULT));
- return ownKey;
- } catch (InvalidKeyException e) {
- Log.d(Config.LOGTAG, "Invalid key stored for account " + account.getJid() + ": " + e.getMessage());
-// return null;
- }
- } //else {
- Log.d(Config.LOGTAG, "Could not retrieve axolotl key for account " + account.getJid());
+ String ownName = account.getJid().toBareJid().toString();
+ IdentityKeyPair ownKey = mXmppConnectionService.databaseBackend.loadOwnIdentityKeyPair(account,
+ ownName);
+
+ if (ownKey != null) {
+ return ownKey;
+ } else {
+ Log.d(Config.LOGTAG, "Could not retrieve axolotl key for account " + ownName);
ownKey = generateIdentityKeyPair();
- boolean success = this.account.setKey(JSONKEY_IDENTITY_KEY_PAIR, Base64.encodeToString(ownKey.serialize(), Base64.DEFAULT));
- if(success) {
- mXmppConnectionService.databaseBackend.updateAccount(account);
- } else {
- Log.e(Config.LOGTAG, "Failed to write new key to the database!");
- }
- //}
+ mXmppConnectionService.databaseBackend.storeOwnIdentityKeyPair(account, ownName, ownKey);
+ }
return ownKey;
}
@@ -152,8 +144,8 @@ public class AxolotlService {
} else {
Log.d(Config.LOGTAG, "Could not retrieve axolotl registration id for account " + account.getJid());
reg_id = generateRegistrationId();
- boolean success = this.account.setKey(JSONKEY_REGISTRATION_ID,""+reg_id);
- if(success) {
+ boolean success = this.account.setKey(JSONKEY_REGISTRATION_ID, Integer.toString(reg_id));
+ if (success) {
mXmppConnectionService.databaseBackend.updateAccount(account);
} else {
Log.e(Config.LOGTAG, "Failed to write new key to the database!");
@@ -182,6 +174,9 @@ public class AxolotlService {
*/
@Override
public IdentityKeyPair getIdentityKeyPair() {
+ if(identityKeyPair == null) {
+ identityKeyPair = loadIdentityKeyPair();
+ }
return identityKeyPair;
}
@@ -208,16 +203,8 @@ public class AxolotlService {
*/
@Override
public void saveIdentity(String name, IdentityKey identityKey) {
- try {
- Jid contactJid = Jid.fromString(name);
- Conversation conversation = this.mXmppConnectionService.find(this.account, contactJid);
- if (conversation != null) {
- conversation.getContact().addAxolotlIdentityKey(identityKey);
- mXmppConnectionService.updateConversationUi();
- mXmppConnectionService.syncRosterToDisk(conversation.getAccount());
- }
- } catch (final InvalidJidException e) {
- Log.e(Config.LOGTAG, "Failed to save identityKey for contact name " + name + ": " + e.toString());
+ if(!mXmppConnectionService.databaseBackend.loadIdentityKeys(account, name).contains(identityKey)) {
+ mXmppConnectionService.databaseBackend.storeIdentityKey(account, name, identityKey);
}
}
@@ -237,19 +224,8 @@ public class AxolotlService {
*/
@Override
public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
- try {
- Jid contactJid = Jid.fromString(name);
- Conversation conversation = this.mXmppConnectionService.find(this.account, contactJid);
- if (conversation != null) {
- List<IdentityKey> trustedKeys = conversation.getContact().getAxolotlIdentityKeys();
- return trustedKeys.isEmpty() || trustedKeys.contains(identityKey);
- } else {
- return false;
- }
- } catch (final InvalidJidException e) {
- Log.e(Config.LOGTAG, "Failed to save identityKey for contact name" + name + ": " + e.toString());
- return false;
- }
+ Set<IdentityKey> trustedKeys = mXmppConnectionService.databaseBackend.loadIdentityKeys(account, name);
+ return trustedKeys.isEmpty() || trustedKeys.contains(identityKey);
}
// --------------------------------------
diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
index 966734ba..c70ffad2 100644
--- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
@@ -10,13 +10,18 @@ import android.util.Base64;
import android.util.Log;
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 java.io.IOException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import eu.siacs.conversations.Config;
@@ -87,6 +92,16 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ ") ON CONFLICT REPLACE"
+");";
+ private static String CREATE_IDENTITIES_STATEMENT = "CREATE TABLE "
+ + AxolotlService.SQLiteAxolotlStore.IDENTITIES_TABLENAME + "("
+ + AxolotlService.SQLiteAxolotlStore.ACCOUNT + " TEXT, "
+ + AxolotlService.SQLiteAxolotlStore.NAME + " TEXT, "
+ + AxolotlService.SQLiteAxolotlStore.OWN + " INTEGER, "
+ + AxolotlService.SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY("
+ + AxolotlService.SQLiteAxolotlStore.ACCOUNT
+ + ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE "
+ +");";
+
private DatabaseBackend(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@@ -126,6 +141,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL(CREATE_SESSIONS_STATEMENT);
db.execSQL(CREATE_PREKEYS_STATEMENT);
db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT);
+ db.execSQL(CREATE_IDENTITIES_STATEMENT);
}
@Override
@@ -273,6 +289,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL(CREATE_PREKEYS_STATEMENT);
db.execSQL("DROP TABLE IF EXISTS " + AxolotlService.SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME);
db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT);
+ db.execSQL("DROP TABLE IF EXISTS " + AxolotlService.SQLiteAxolotlStore.IDENTITIES_TABLENAME);
+ db.execSQL(CREATE_IDENTITIES_STATEMENT);
}
}
@@ -783,4 +801,71 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ AxolotlService.SQLiteAxolotlStore.ID + "=?",
args);
}
+
+ private Cursor getIdentityKeyCursor(Account account, String name, boolean own) {
+ final SQLiteDatabase db = this.getReadableDatabase();
+ String[] columns = {AxolotlService.SQLiteAxolotlStore.KEY};
+ String[] selectionArgs = {account.getUuid(),
+ name,
+ own?"1":"0"};
+ Cursor cursor = db.query(AxolotlService.SQLiteAxolotlStore.IDENTITIES_TABLENAME,
+ columns,
+ AxolotlService.SQLiteAxolotlStore.ACCOUNT + " = ? AND "
+ + AxolotlService.SQLiteAxolotlStore.NAME + " = ? AND "
+ + AxolotlService.SQLiteAxolotlStore.OWN + " = ? ",
+ selectionArgs,
+ null, null, null);
+
+ return cursor;
+ }
+
+ public IdentityKeyPair loadOwnIdentityKeyPair(Account account, String name) {
+ IdentityKeyPair identityKeyPair = null;
+ Cursor cursor = getIdentityKeyCursor(account, name, true);
+ if(cursor.getCount() != 0) {
+ cursor.moveToFirst();
+ try {
+ identityKeyPair = new IdentityKeyPair(Base64.decode(cursor.getString(cursor.getColumnIndex(AxolotlService.SQLiteAxolotlStore.KEY)),Base64.DEFAULT));
+ } catch (InvalidKeyException e) {
+ Log.d(Config.LOGTAG, "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name);
+ }
+ }
+ cursor.close();
+
+ return identityKeyPair;
+ }
+
+ public Set<IdentityKey> loadIdentityKeys(Account account, String name) {
+ Set<IdentityKey> identityKeys = new HashSet<>();
+ Cursor cursor = getIdentityKeyCursor(account, name, false);
+
+ while(cursor.moveToNext()) {
+ try {
+ identityKeys.add(new IdentityKey(Base64.decode(cursor.getString(cursor.getColumnIndex(AxolotlService.SQLiteAxolotlStore.KEY)),Base64.DEFAULT),0));
+ } catch (InvalidKeyException e) {
+ Log.d(Config.LOGTAG, "Encountered invalid IdentityKey in database for account"+account.getJid().toBareJid()+", address: "+name);
+ }
+ }
+ cursor.close();
+
+ return identityKeys;
+ }
+
+ private void storeIdentityKey(Account account, String name, boolean own, String base64Serialized) {
+ SQLiteDatabase db = this.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(AxolotlService.SQLiteAxolotlStore.ACCOUNT, account.getUuid());
+ values.put(AxolotlService.SQLiteAxolotlStore.NAME, name);
+ values.put(AxolotlService.SQLiteAxolotlStore.OWN, own?1:0);
+ values.put(AxolotlService.SQLiteAxolotlStore.KEY, base64Serialized);
+ db.insert(AxolotlService.SQLiteAxolotlStore.IDENTITIES_TABLENAME, null, values);
+ }
+
+ public void storeIdentityKey(Account account, String name, IdentityKey identityKey) {
+ storeIdentityKey(account, name, false, Base64.encodeToString(identityKey.serialize(), Base64.DEFAULT));
+ }
+
+ public void storeOwnIdentityKeyPair(Account account, String name, IdentityKeyPair identityKeyPair) {
+ storeIdentityKey(account, name, true, Base64.encodeToString(identityKeyPair.serialize(),Base64.DEFAULT));
+ }
}