Save IdentityKeys in database
This commit is contained in:
parent
71c0a75ec9
commit
046a2d6045
|
@ -68,12 +68,14 @@ public class AxolotlService {
|
||||||
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";
|
||||||
public static final String SESSION_TABLENAME = "sessions";
|
public static final String SESSION_TABLENAME = "sessions";
|
||||||
|
public static final String IDENTITIES_TABLENAME = "identities";
|
||||||
public static final String ACCOUNT = "account";
|
public static final String ACCOUNT = "account";
|
||||||
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 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 JSONKEY_IDENTITY_KEY_PAIR = "axolotl_key";
|
public static final String JSONKEY_IDENTITY_KEY_PAIR = "axolotl_key";
|
||||||
public static final String JSONKEY_REGISTRATION_ID = "axolotl_reg_id";
|
public static final String JSONKEY_REGISTRATION_ID = "axolotl_reg_id";
|
||||||
|
@ -82,7 +84,7 @@ public class AxolotlService {
|
||||||
private final Account account;
|
private final Account account;
|
||||||
private final XmppConnectionService mXmppConnectionService;
|
private final XmppConnectionService mXmppConnectionService;
|
||||||
|
|
||||||
private final IdentityKeyPair identityKeyPair;
|
private IdentityKeyPair identityKeyPair;
|
||||||
private final int localRegistrationId;
|
private final int localRegistrationId;
|
||||||
private int currentPreKeyId = 0;
|
private int currentPreKeyId = 0;
|
||||||
|
|
||||||
|
@ -104,10 +106,9 @@ public class AxolotlService {
|
||||||
public SQLiteAxolotlStore(Account account, XmppConnectionService service) {
|
public SQLiteAxolotlStore(Account account, XmppConnectionService service) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.mXmppConnectionService = service;
|
this.mXmppConnectionService = service;
|
||||||
this.identityKeyPair = loadIdentityKeyPair();
|
|
||||||
this.localRegistrationId = loadRegistrationId();
|
this.localRegistrationId = loadRegistrationId();
|
||||||
this.currentPreKeyId = loadCurrentPreKeyId();
|
this.currentPreKeyId = loadCurrentPreKeyId();
|
||||||
for( SignedPreKeyRecord record:loadSignedPreKeys()) {
|
for (SignedPreKeyRecord record : loadSignedPreKeys()) {
|
||||||
Log.d(Config.LOGTAG, "Got Axolotl signed prekey record:" + record.getId());
|
Log.d(Config.LOGTAG, "Got Axolotl signed prekey record:" + record.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,26 +122,17 @@ public class AxolotlService {
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
|
|
||||||
private IdentityKeyPair loadIdentityKeyPair() {
|
private IdentityKeyPair loadIdentityKeyPair() {
|
||||||
String serializedKey = this.account.getKey(JSONKEY_IDENTITY_KEY_PAIR);
|
String ownName = account.getJid().toBareJid().toString();
|
||||||
IdentityKeyPair ownKey;
|
IdentityKeyPair ownKey = mXmppConnectionService.databaseBackend.loadOwnIdentityKeyPair(account,
|
||||||
if( serializedKey != null ) {
|
ownName);
|
||||||
try {
|
|
||||||
ownKey = new IdentityKeyPair(Base64.decode(serializedKey,Base64.DEFAULT));
|
if (ownKey != null) {
|
||||||
return ownKey;
|
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());
|
|
||||||
ownKey = generateIdentityKeyPair();
|
|
||||||
boolean success = this.account.setKey(JSONKEY_IDENTITY_KEY_PAIR, Base64.encodeToString(ownKey.serialize(), Base64.DEFAULT));
|
|
||||||
if(success) {
|
|
||||||
mXmppConnectionService.databaseBackend.updateAccount(account);
|
|
||||||
} else {
|
} else {
|
||||||
Log.e(Config.LOGTAG, "Failed to write new key to the database!");
|
Log.d(Config.LOGTAG, "Could not retrieve axolotl key for account " + ownName);
|
||||||
|
ownKey = generateIdentityKeyPair();
|
||||||
|
mXmppConnectionService.databaseBackend.storeOwnIdentityKeyPair(account, ownName, ownKey);
|
||||||
}
|
}
|
||||||
//}
|
|
||||||
return ownKey;
|
return ownKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,8 +144,8 @@ public class AxolotlService {
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG, "Could not retrieve axolotl registration id for account " + account.getJid());
|
Log.d(Config.LOGTAG, "Could not retrieve axolotl registration id for account " + account.getJid());
|
||||||
reg_id = generateRegistrationId();
|
reg_id = generateRegistrationId();
|
||||||
boolean success = this.account.setKey(JSONKEY_REGISTRATION_ID,""+reg_id);
|
boolean success = this.account.setKey(JSONKEY_REGISTRATION_ID, Integer.toString(reg_id));
|
||||||
if(success) {
|
if (success) {
|
||||||
mXmppConnectionService.databaseBackend.updateAccount(account);
|
mXmppConnectionService.databaseBackend.updateAccount(account);
|
||||||
} else {
|
} else {
|
||||||
Log.e(Config.LOGTAG, "Failed to write new key to the database!");
|
Log.e(Config.LOGTAG, "Failed to write new key to the database!");
|
||||||
|
@ -182,6 +174,9 @@ public class AxolotlService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IdentityKeyPair getIdentityKeyPair() {
|
public IdentityKeyPair getIdentityKeyPair() {
|
||||||
|
if(identityKeyPair == null) {
|
||||||
|
identityKeyPair = loadIdentityKeyPair();
|
||||||
|
}
|
||||||
return identityKeyPair;
|
return identityKeyPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,16 +203,8 @@ public class AxolotlService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void saveIdentity(String name, IdentityKey identityKey) {
|
public void saveIdentity(String name, IdentityKey identityKey) {
|
||||||
try {
|
if(!mXmppConnectionService.databaseBackend.loadIdentityKeys(account, name).contains(identityKey)) {
|
||||||
Jid contactJid = Jid.fromString(name);
|
mXmppConnectionService.databaseBackend.storeIdentityKey(account, name, identityKey);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,19 +224,8 @@ public class AxolotlService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
|
public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
|
||||||
try {
|
Set<IdentityKey> trustedKeys = mXmppConnectionService.databaseBackend.loadIdentityKeys(account, name);
|
||||||
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);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
|
|
|
@ -10,13 +10,18 @@ import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.whispersystems.libaxolotl.AxolotlAddress;
|
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.PreKeyRecord;
|
||||||
import org.whispersystems.libaxolotl.state.SessionRecord;
|
import org.whispersystems.libaxolotl.state.SessionRecord;
|
||||||
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
|
@ -87,6 +92,16 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
+ ") ON CONFLICT REPLACE"
|
+ ") 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) {
|
private DatabaseBackend(Context context) {
|
||||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
}
|
}
|
||||||
|
@ -126,6 +141,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
db.execSQL(CREATE_SESSIONS_STATEMENT);
|
db.execSQL(CREATE_SESSIONS_STATEMENT);
|
||||||
db.execSQL(CREATE_PREKEYS_STATEMENT);
|
db.execSQL(CREATE_PREKEYS_STATEMENT);
|
||||||
db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT);
|
db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT);
|
||||||
|
db.execSQL(CREATE_IDENTITIES_STATEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -273,6 +289,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
db.execSQL(CREATE_PREKEYS_STATEMENT);
|
db.execSQL(CREATE_PREKEYS_STATEMENT);
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + AxolotlService.SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME);
|
db.execSQL("DROP TABLE IF EXISTS " + AxolotlService.SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME);
|
||||||
db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT);
|
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 + "=?",
|
+ AxolotlService.SQLiteAxolotlStore.ID + "=?",
|
||||||
args);
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue