mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-09-27 10:09:32 +02:00
08e897113d
And matching ImportOrder settings for Eclipse in resources/eclipse/smack.importorder
792 lines
32 KiB
Java
792 lines
32 KiB
Java
/**
|
|
*
|
|
* Copyright 2017 Paul Schaub
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package org.jivesoftware.smackx.omemo;
|
|
|
|
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.TARGET_PRE_KEY_COUNT;
|
|
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.WeakHashMap;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
|
|
import org.jivesoftware.smack.roster.Roster;
|
|
import org.jivesoftware.smack.roster.RosterEntry;
|
|
|
|
import org.jivesoftware.smackx.omemo.element.OmemoBundleVAxolotlElement;
|
|
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement;
|
|
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
|
|
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
|
import org.jivesoftware.smackx.omemo.internal.CachedDeviceList;
|
|
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
|
|
import org.jivesoftware.smackx.omemo.internal.OmemoSession;
|
|
import org.jivesoftware.smackx.omemo.util.OmemoKeyUtil;
|
|
|
|
import org.jxmpp.jid.BareJid;
|
|
|
|
/**
|
|
* Class that presents some methods that are used to load/generate/store keys and session data needed for OMEMO.
|
|
*
|
|
* @param <T_IdKeyPair> IdentityKeyPair class
|
|
* @param <T_IdKey> IdentityKey class
|
|
* @param <T_PreKey> PreKey class
|
|
* @param <T_SigPreKey> SignedPreKey class
|
|
* @param <T_Sess> Session class
|
|
* @param <T_Addr> Address class
|
|
* @param <T_ECPub> Elliptic Curve PublicKey class
|
|
* @param <T_Bundle> Bundle class
|
|
* @param <T_Ciph> Cipher class
|
|
* @author Paul Schaub
|
|
*/
|
|
public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph> {
|
|
private static final Logger LOGGER = Logger.getLogger(OmemoStore.class.getName());
|
|
|
|
private final WeakHashMap<OmemoManager, HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>>>
|
|
omemoSessions = new WeakHashMap<>();
|
|
|
|
/**
|
|
* Create a new OmemoStore.
|
|
*/
|
|
public OmemoStore() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Return true if this is a fresh installation.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @return true or false.
|
|
*/
|
|
public abstract boolean isFreshInstallation(OmemoManager omemoManager);
|
|
|
|
/**
|
|
* Check, if our freshly generated deviceId is available (unique) in our deviceList.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param id our deviceId.
|
|
* @return true if list did not contain our id, else false
|
|
*/
|
|
boolean isAvailableDeviceId(OmemoManager omemoManager, int id) {
|
|
LOGGER.log(Level.INFO, "Check if id " + id + " is available...");
|
|
|
|
//Lookup local cached device list
|
|
BareJid ownJid = omemoManager.getOwnJid();
|
|
CachedDeviceList cachedDeviceList = loadCachedDeviceList(omemoManager, ownJid);
|
|
|
|
if (cachedDeviceList == null) {
|
|
cachedDeviceList = new CachedDeviceList();
|
|
}
|
|
//Does the list already contain that id?
|
|
return !cachedDeviceList.contains(id);
|
|
}
|
|
|
|
/**
|
|
* Generate a new Identity (deviceId, identityKeys, preKeys...).
|
|
*
|
|
* @param omemoManager omemoManager of our device we want to regenerate.
|
|
* @throws CorruptedOmemoKeyException in case something goes wrong
|
|
*/
|
|
void regenerate(OmemoManager omemoManager) throws CorruptedOmemoKeyException {
|
|
LOGGER.log(Level.INFO, "Regenerating with deviceId " + omemoManager.getDeviceId() + "...");
|
|
int nextPreKeyId = 1;
|
|
storeOmemoIdentityKeyPair(omemoManager, generateOmemoIdentityKeyPair());
|
|
storeOmemoPreKeys(omemoManager, generateOmemoPreKeys(nextPreKeyId, TARGET_PRE_KEY_COUNT));
|
|
storeLastPreKeyId(omemoManager, OmemoKeyUtil.addInBounds(nextPreKeyId, TARGET_PRE_KEY_COUNT));
|
|
storeCurrentSignedPreKeyId(omemoManager, -1); //Set back to no-value default
|
|
changeSignedPreKey(omemoManager);
|
|
initializeOmemoSessions(omemoManager);
|
|
}
|
|
|
|
/**
|
|
* Merge the received OmemoDeviceListElement with the one we already have. If we had none, the received one is saved.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param contact Contact we received the list from.
|
|
* @param list List we received.
|
|
*/
|
|
void mergeCachedDeviceList(OmemoManager omemoManager, BareJid contact, OmemoDeviceListElement list) {
|
|
CachedDeviceList cached = loadCachedDeviceList(omemoManager, contact);
|
|
|
|
if (cached == null) {
|
|
cached = new CachedDeviceList();
|
|
}
|
|
|
|
if (list != null) {
|
|
cached.merge(list.getDeviceIds());
|
|
}
|
|
storeCachedDeviceList(omemoManager, contact, cached);
|
|
}
|
|
|
|
/**
|
|
* Renew our singed preKey. This should be done once every 7-14 days.
|
|
* The old signed PreKey should be kept for around a month or so (look it up in the XEP).
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @throws CorruptedOmemoKeyException when our identityKey is invalid
|
|
*/
|
|
void changeSignedPreKey(OmemoManager omemoManager) throws CorruptedOmemoKeyException {
|
|
int lastSignedPreKeyId = loadCurrentSignedPreKeyId(omemoManager);
|
|
if (lastSignedPreKeyId == -1) lastSignedPreKeyId = 0;
|
|
try {
|
|
T_SigPreKey newSignedPreKey = generateOmemoSignedPreKey(loadOmemoIdentityKeyPair(omemoManager), lastSignedPreKeyId + 1);
|
|
storeOmemoSignedPreKey(omemoManager, lastSignedPreKeyId + 1, newSignedPreKey);
|
|
storeCurrentSignedPreKeyId(omemoManager, lastSignedPreKeyId + 1);
|
|
setDateOfLastSignedPreKeyRenewal(omemoManager);
|
|
removeOldSignedPreKeys(omemoManager);
|
|
|
|
} catch (CorruptedOmemoKeyException e) {
|
|
LOGGER.log(Level.INFO, "Couldn't change SignedPreKey: " + e.getMessage());
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove the oldest signedPreKey until there are only MAX_NUMBER_OF_STORED_SIGNED_PREKEYS left.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
*/
|
|
private void removeOldSignedPreKeys(OmemoManager omemoManager) {
|
|
if (OmemoConfiguration.getMaxNumberOfStoredSignedPreKeys() <= 0) {
|
|
return;
|
|
}
|
|
|
|
int currentId = loadCurrentSignedPreKeyId(omemoManager);
|
|
if (currentId == -1) currentId = 0;
|
|
HashMap<Integer, T_SigPreKey> signedPreKeys = loadOmemoSignedPreKeys(omemoManager);
|
|
|
|
for (int i : signedPreKeys.keySet()) {
|
|
if (i <= currentId - OmemoConfiguration.getMaxNumberOfStoredSignedPreKeys()) {
|
|
LOGGER.log(Level.INFO, "Remove signedPreKey " + i + ".");
|
|
removeOmemoSignedPreKey(omemoManager, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pack a OmemoBundleElement containing our key material.
|
|
* If we used up n preKeys since we last published our bundle, generate n new preKeys and add them to the bundle.
|
|
* We should always publish TARGET_PRE_KEY_COUNT keys.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @return OmemoBundleElement
|
|
* @throws CorruptedOmemoKeyException when a key could not be loaded
|
|
*/
|
|
OmemoBundleVAxolotlElement packOmemoBundle(OmemoManager omemoManager) throws CorruptedOmemoKeyException {
|
|
int currentSignedPreKeyId = loadCurrentSignedPreKeyId(omemoManager);
|
|
if (currentSignedPreKeyId == -1) currentSignedPreKeyId = 0;
|
|
T_SigPreKey currentSignedPreKey = loadOmemoSignedPreKey(omemoManager, currentSignedPreKeyId);
|
|
T_IdKeyPair identityKeyPair = loadOmemoIdentityKeyPair(omemoManager);
|
|
|
|
HashMap<Integer, T_PreKey> preKeys = loadOmemoPreKeys(omemoManager);
|
|
int newKeysCount = TARGET_PRE_KEY_COUNT - preKeys.size();
|
|
|
|
if (newKeysCount > 0) {
|
|
int lastPreKeyId = loadLastPreKeyId(omemoManager);
|
|
if (lastPreKeyId == -1) lastPreKeyId = 0;
|
|
HashMap<Integer, T_PreKey> newKeys = generateOmemoPreKeys(lastPreKeyId + 1, newKeysCount);
|
|
storeOmemoPreKeys(omemoManager, newKeys);
|
|
preKeys.putAll(newKeys);
|
|
storeLastPreKeyId(omemoManager, lastPreKeyId + newKeysCount);
|
|
}
|
|
|
|
return new OmemoBundleVAxolotlElement(
|
|
currentSignedPreKeyId,
|
|
keyUtil().signedPreKeyPublicForBundle(currentSignedPreKey),
|
|
keyUtil().signedPreKeySignatureFromKey(currentSignedPreKey),
|
|
keyUtil().identityKeyForBundle(keyUtil().identityKeyFromPair(identityKeyPair)),
|
|
keyUtil().preKeyPublisKeysForBundle(preKeys)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Preload all OMEMO sessions for our devices and our contacts from existing raw sessions.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
*/
|
|
void initializeOmemoSessions(OmemoManager omemoManager) {
|
|
|
|
//Get HashMap of our omemoSessions
|
|
HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>>
|
|
sessions = omemoSessions.get(omemoManager);
|
|
if (sessions == null) {
|
|
sessions = new HashMap<>();
|
|
omemoSessions.put(omemoManager, sessions);
|
|
}
|
|
|
|
//Sessions with our own devices
|
|
HashMap<Integer, T_Sess> ourRawSessions = loadAllRawSessionsOf(omemoManager, omemoManager.getOwnJid());
|
|
ourRawSessions.remove(omemoManager.getDeviceId()); //Just to make sure we have no session with ourselves...
|
|
sessions.putAll(createOmemoSessionsFromRawSessions(omemoManager, omemoManager.getOwnJid(), ourRawSessions));
|
|
|
|
//Sessions with contacts
|
|
for (RosterEntry rosterEntry : Roster.getInstanceFor(omemoManager.getConnection()).getEntries()) {
|
|
HashMap<Integer, T_Sess> contactDevices = loadAllRawSessionsOf(omemoManager, rosterEntry.getJid().asBareJid());
|
|
sessions.putAll(createOmemoSessionsFromRawSessions(omemoManager, rosterEntry.getJid().asBareJid(), contactDevices));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Forget all omemoSessions of the omemoManager from cache.
|
|
* This will not remove the sessions from persistent memory!
|
|
*
|
|
* @param omemoManager omemoManager we want to forget sessions from.
|
|
*/
|
|
void forgetOmemoSessions(OmemoManager omemoManager) {
|
|
omemoSessions.remove(omemoManager);
|
|
}
|
|
|
|
/**
|
|
* Create a new concrete OmemoSession with a contact.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device to establish the session with
|
|
* @param identityKey identityKey of the device
|
|
* @return concrete OmemoSession
|
|
*/
|
|
private OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>
|
|
createOmemoSession(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) {
|
|
return keyUtil().createOmemoSession(omemoManager, this, device, identityKey);
|
|
}
|
|
|
|
/**
|
|
* Return the OmemoSession for the OmemoDevice. If there is no OmemoSession for the device yet,
|
|
* build one from local raw session material.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device OmemoDevice
|
|
* @return OmemoSession
|
|
*/
|
|
public OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>
|
|
getOmemoSessionOf(OmemoManager omemoManager, OmemoDevice device) {
|
|
|
|
HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>>
|
|
sessions = omemoSessions.get(omemoManager);
|
|
|
|
if (sessions == null) {
|
|
sessions = new HashMap<>();
|
|
omemoSessions.put(omemoManager, sessions);
|
|
}
|
|
|
|
OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>
|
|
session = sessions.get(device);
|
|
//No OmemoSession found
|
|
if (session == null) {
|
|
T_IdKey identityKey = null;
|
|
try {
|
|
identityKey = loadOmemoIdentityKey(omemoManager, device);
|
|
} catch (CorruptedOmemoKeyException e) {
|
|
LOGGER.log(Level.WARNING, "getOmemoSessionOf could not load identityKey of " + device + ": " + e.getMessage());
|
|
}
|
|
|
|
if (identityKey != null) {
|
|
session = createOmemoSession(omemoManager, device, identityKey);
|
|
|
|
} else {
|
|
LOGGER.log(Level.INFO, "getOmemoSessionOf couldn't find an identityKey for " + device
|
|
+ ". Initiate session without.");
|
|
session = createOmemoSession(omemoManager, device, null);
|
|
}
|
|
|
|
sessions.put(device, session);
|
|
}
|
|
|
|
if (session.getIdentityKey() == null) {
|
|
try {
|
|
session.setIdentityKey(loadOmemoIdentityKey(omemoManager, device));
|
|
} catch (CorruptedOmemoKeyException e) {
|
|
LOGGER.log(Level.WARNING, "Can't update IdentityKey of " + device + ": " + e.getMessage());
|
|
}
|
|
}
|
|
return session;
|
|
}
|
|
|
|
/**
|
|
* Create OmemoSession objects for all T_Sess objects of the contact.
|
|
* The T_Sess objects will be wrapped inside a OmemoSession for every device of the contact.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param contact BareJid of the contact
|
|
* @param rawSessions HashMap of Integers (deviceIds) and T_Sess sessions.
|
|
* @return HashMap of OmemoContacts and OmemoSessions
|
|
*/
|
|
private HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>>
|
|
createOmemoSessionsFromRawSessions(OmemoManager omemoManager, BareJid contact, HashMap<Integer, T_Sess> rawSessions) {
|
|
|
|
HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>>
|
|
sessions = new HashMap<>();
|
|
|
|
for (Map.Entry<Integer, T_Sess> sessionEntry : rawSessions.entrySet()) {
|
|
OmemoDevice omemoDevice = new OmemoDevice(contact, sessionEntry.getKey());
|
|
try {
|
|
T_IdKey identityKey = loadOmemoIdentityKey(omemoManager, omemoDevice);
|
|
if (identityKey != null) {
|
|
sessions.put(omemoDevice, createOmemoSession(omemoManager, omemoDevice, identityKey));
|
|
} else {
|
|
LOGGER.log(Level.WARNING, "IdentityKey of " + omemoDevice + " is null. Is this even possible at this point?");
|
|
}
|
|
} catch (CorruptedOmemoKeyException e1) {
|
|
LOGGER.log(Level.WARNING, "buildOmemoSessionFor could not create a session for " + omemoDevice +
|
|
": " + e1.getMessage());
|
|
}
|
|
}
|
|
return sessions;
|
|
}
|
|
|
|
// *sigh*
|
|
|
|
/**
|
|
* Return the id of the last generated preKey.
|
|
* This is used to generate new preKeys without preKeyId collisions.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @return id of the last preKey
|
|
*/
|
|
public abstract int loadLastPreKeyId(OmemoManager omemoManager);
|
|
|
|
/**
|
|
* Store the id of the last preKey we generated.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param currentPreKeyId the id of the last generated PreKey
|
|
*/
|
|
public abstract void storeLastPreKeyId(OmemoManager omemoManager, int currentPreKeyId);
|
|
|
|
/**
|
|
* Generate a new IdentityKeyPair. We should always have only one pair and usually keep this for a long time.
|
|
*
|
|
* @return identityKeyPair
|
|
*/
|
|
public T_IdKeyPair generateOmemoIdentityKeyPair() {
|
|
return keyUtil().generateOmemoIdentityKeyPair();
|
|
}
|
|
|
|
/**
|
|
* Load our identityKeyPair from storage.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @return identityKeyPair
|
|
* @throws CorruptedOmemoKeyException Thrown, if the stored key is damaged (*hands up* not my fault!)
|
|
*/
|
|
public abstract T_IdKeyPair loadOmemoIdentityKeyPair(OmemoManager omemoManager) throws CorruptedOmemoKeyException;
|
|
|
|
/**
|
|
* Store our identityKeyPair in storage. It would be a cool feature, if the key could be stored in a encrypted
|
|
* database or something similar.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param identityKeyPair identityKeyPair
|
|
*/
|
|
public abstract void storeOmemoIdentityKeyPair(OmemoManager omemoManager, T_IdKeyPair identityKeyPair);
|
|
|
|
/**
|
|
* Load the public identityKey of the device.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device
|
|
* @return identityKey
|
|
* @throws CorruptedOmemoKeyException when the key in question is corrupted and cant be deserialized.
|
|
*/
|
|
public abstract T_IdKey loadOmemoIdentityKey(OmemoManager omemoManager, OmemoDevice device) throws CorruptedOmemoKeyException;
|
|
|
|
/**
|
|
* Store the public identityKey of the device.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device
|
|
* @param key identityKey
|
|
*/
|
|
public abstract void storeOmemoIdentityKey(OmemoManager omemoManager, OmemoDevice device, T_IdKey key);
|
|
|
|
/**
|
|
* Decide, whether a identityKey of a device is trusted or not.
|
|
* If you want to use this module, you should memorize, whether the user has trusted this key or not, since
|
|
* the owner of the identityKey will be able to read sent messages when this method returned 'true' for their
|
|
* identityKey. Either you let the user decide whether you trust a key every time you see a new key, or you
|
|
* implement something like 'blind trust' (see https://gultsch.de/trust.html).
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device Owner of the key
|
|
* @param identityKey identityKey
|
|
* @return true, if the user trusts the key and wants to send messages to it, otherwise false
|
|
*/
|
|
public boolean isTrustedOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) {
|
|
return isTrustedOmemoIdentity(omemoManager, device, keyUtil().getFingerprint(identityKey));
|
|
}
|
|
|
|
public abstract boolean isTrustedOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, OmemoFingerprint fingerprint);
|
|
|
|
/**
|
|
* Did the user yet made a decision about whether to trust or distrust this device?
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device
|
|
* @param identityKey IdentityKey
|
|
* @return true, if the user either trusted or distrusted the device. Return false, if the user did not yet decide.
|
|
*/
|
|
public boolean isDecidedOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) {
|
|
return isDecidedOmemoIdentity(omemoManager, device, keyUtil().getFingerprint(identityKey));
|
|
}
|
|
|
|
public abstract boolean isDecidedOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, OmemoFingerprint fingerprint);
|
|
|
|
/**
|
|
* Trust an OmemoIdentity. This involves marking the key as trusted.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device
|
|
* @param identityKey identityKey
|
|
*/
|
|
public void trustOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) {
|
|
trustOmemoIdentity(omemoManager, device, keyUtil().getFingerprint(identityKey));
|
|
}
|
|
|
|
public abstract void trustOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, OmemoFingerprint identityKeyFingerprint);
|
|
|
|
/**
|
|
* Distrust an OmemoIdentity. This involved marking the key as distrusted.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device
|
|
* @param identityKey identityKey
|
|
*/
|
|
public void distrustOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) {
|
|
distrustOmemoIdentity(omemoManager, device, keyUtil().getFingerprint(identityKey));
|
|
}
|
|
|
|
public abstract void distrustOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, OmemoFingerprint fingerprint);
|
|
|
|
/**
|
|
* Set the date in millis of the last message that was received from device 'from' to 'date'.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param from device in question
|
|
* @param date date of the last received message
|
|
*/
|
|
public abstract void setDateOfLastReceivedMessage(OmemoManager omemoManager, OmemoDevice from, Date date);
|
|
|
|
/**
|
|
* Set the date in millis of the last message that was received from device 'from' to now.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param from device in question
|
|
*/
|
|
public void setDateOfLastReceivedMessage(OmemoManager omemoManager, OmemoDevice from) {
|
|
this.setDateOfLastReceivedMessage(omemoManager, from, new Date());
|
|
}
|
|
|
|
/**
|
|
* Return the date in millis of the last message that was received from device 'from'.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param from device in question
|
|
* @return date if existent as long, otherwise -1
|
|
*/
|
|
public abstract Date getDateOfLastReceivedMessage(OmemoManager omemoManager, OmemoDevice from);
|
|
|
|
/**
|
|
* Set the date in millis of the last time the signed preKey was renewed.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param date date
|
|
*/
|
|
public abstract void setDateOfLastSignedPreKeyRenewal(OmemoManager omemoManager, Date date);
|
|
|
|
/**
|
|
* Store the date of the last preKey renewal in the omemoStore.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
*/
|
|
public void setDateOfLastSignedPreKeyRenewal(OmemoManager omemoManager) {
|
|
setDateOfLastSignedPreKeyRenewal(omemoManager, new Date());
|
|
}
|
|
|
|
/**
|
|
* Get the date in millis of the last time the signed preKey was renewed.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @return date if existent, otherwise null
|
|
*/
|
|
public abstract Date getDateOfLastSignedPreKeyRenewal(OmemoManager omemoManager);
|
|
|
|
/**
|
|
* Generate 'count' new PreKeys beginning with id 'startId'.
|
|
* These preKeys are published and can be used by contacts to establish sessions with us.
|
|
*
|
|
* @param startId start id
|
|
* @param count how many keys do we want to generate
|
|
* @return Map of new preKeys
|
|
*/
|
|
public HashMap<Integer, T_PreKey> generateOmemoPreKeys(int startId, int count) {
|
|
return keyUtil().generateOmemoPreKeys(startId, count);
|
|
}
|
|
|
|
/**
|
|
* Load the preKey with id 'preKeyId' from storage.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param preKeyId id of the key to be loaded
|
|
* @return loaded preKey
|
|
*/
|
|
public abstract T_PreKey loadOmemoPreKey(OmemoManager omemoManager, int preKeyId);
|
|
|
|
/**
|
|
* Store a PreKey in storage.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param preKeyId id of the key
|
|
* @param preKey key
|
|
*/
|
|
public abstract void storeOmemoPreKey(OmemoManager omemoManager, int preKeyId, T_PreKey preKey);
|
|
|
|
/**
|
|
* Store a whole bunch of preKeys.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param preKeyHashMap HashMap of preKeys
|
|
*/
|
|
public void storeOmemoPreKeys(OmemoManager omemoManager, HashMap<Integer, T_PreKey> preKeyHashMap) {
|
|
for (Map.Entry<Integer, T_PreKey> e : preKeyHashMap.entrySet()) {
|
|
storeOmemoPreKey(omemoManager, e.getKey(), e.getValue());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* remove a preKey from storage. This is called, when a contact used one of our preKeys to establish a session
|
|
* with us.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param preKeyId id of the used key that will be deleted
|
|
*/
|
|
public abstract void removeOmemoPreKey(OmemoManager omemoManager, int preKeyId);
|
|
|
|
/**
|
|
* Return the id of the currently used signed preKey.
|
|
* This is used to avoid collisions when generating a new signedPreKey.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @return id
|
|
*/
|
|
public abstract int loadCurrentSignedPreKeyId(OmemoManager omemoManager);
|
|
|
|
/**
|
|
* Store the id of the currently used signedPreKey.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param currentSignedPreKeyId if of the signedPreKey that is currently in use
|
|
*/
|
|
public abstract void storeCurrentSignedPreKeyId(OmemoManager omemoManager, int currentSignedPreKeyId);
|
|
|
|
/**
|
|
* Return all our current OmemoPreKeys.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @return Map containing our preKeys
|
|
*/
|
|
public abstract HashMap<Integer, T_PreKey> loadOmemoPreKeys(OmemoManager omemoManager);
|
|
|
|
/**
|
|
* Return the signedPreKey with the id 'singedPreKeyId'.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param signedPreKeyId id of the key
|
|
* @return key
|
|
*/
|
|
public abstract T_SigPreKey loadOmemoSignedPreKey(OmemoManager omemoManager, int signedPreKeyId);
|
|
|
|
/**
|
|
* Load all our signed PreKeys.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @return HashMap of our singedPreKeys
|
|
*/
|
|
public abstract HashMap<Integer, T_SigPreKey> loadOmemoSignedPreKeys(OmemoManager omemoManager);
|
|
|
|
/**
|
|
* Generate a new signed preKey.
|
|
*
|
|
* @param identityKeyPair identityKeyPair used to sign the preKey
|
|
* @param signedPreKeyId id that the preKey will have
|
|
* @return signedPreKey
|
|
* @throws CorruptedOmemoKeyException when something goes wrong
|
|
*/
|
|
public T_SigPreKey generateOmemoSignedPreKey(T_IdKeyPair identityKeyPair, int signedPreKeyId) throws CorruptedOmemoKeyException {
|
|
return keyUtil().generateOmemoSignedPreKey(identityKeyPair, signedPreKeyId);
|
|
}
|
|
|
|
/**
|
|
* Store a signedPreKey in storage.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param signedPreKeyId id of the signedPreKey
|
|
* @param signedPreKey the key itself
|
|
*/
|
|
public abstract void storeOmemoSignedPreKey(OmemoManager omemoManager, int signedPreKeyId, T_SigPreKey signedPreKey);
|
|
|
|
/**
|
|
* Remove a signedPreKey from storage.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param signedPreKeyId id of the key that will be removed
|
|
*/
|
|
public abstract void removeOmemoSignedPreKey(OmemoManager omemoManager, int signedPreKeyId);
|
|
|
|
/**
|
|
* Load the crypto-lib specific session object of the device from storage.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device whose session we want to load
|
|
* @return crypto related session
|
|
*/
|
|
public abstract T_Sess loadRawSession(OmemoManager omemoManager, OmemoDevice device);
|
|
|
|
/**
|
|
* Load all crypto-lib specific session objects of contact 'contact'.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param contact BareJid of the contact we want to get all sessions from
|
|
* @return HashMap of deviceId and sessions of the contact
|
|
*/
|
|
public abstract HashMap<Integer, T_Sess> loadAllRawSessionsOf(OmemoManager omemoManager, BareJid contact);
|
|
|
|
/**
|
|
* Store a crypto-lib specific session to storage.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device OmemoDevice whose session we want to store
|
|
* @param session session
|
|
*/
|
|
public abstract void storeRawSession(OmemoManager omemoManager, OmemoDevice device, T_Sess session);
|
|
|
|
/**
|
|
* Remove a crypto-lib specific session from storage.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device whose session we want to delete
|
|
*/
|
|
public abstract void removeRawSession(OmemoManager omemoManager, OmemoDevice device);
|
|
|
|
/**
|
|
* Remove all crypto-lib specific session of a contact.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param contact BareJid of the contact
|
|
*/
|
|
public abstract void removeAllRawSessionsOf(OmemoManager omemoManager, BareJid contact);
|
|
|
|
/**
|
|
* Return true, if we have a session with the device, otherwise false.
|
|
* Hint for Signal: Do not try 'return getSession() != null' since this will create a new session.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device
|
|
* @return true if we have session, otherwise false
|
|
*/
|
|
public abstract boolean containsRawSession(OmemoManager omemoManager, OmemoDevice device);
|
|
|
|
/**
|
|
* Load a list of deviceIds from contact 'contact' from the local cache.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param contact contact we want to get the deviceList of
|
|
* @return CachedDeviceList of the contact
|
|
*/
|
|
public abstract CachedDeviceList loadCachedDeviceList(OmemoManager omemoManager, BareJid contact);
|
|
|
|
/**
|
|
* Store the DeviceList of the contact in local storage.
|
|
* See this as a cache.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param contact Contact
|
|
* @param deviceList list of the contacts devices' ids.
|
|
*/
|
|
public abstract void storeCachedDeviceList(OmemoManager omemoManager, BareJid contact, CachedDeviceList deviceList);
|
|
|
|
/**
|
|
* Delete this device's IdentityKey, PreKeys, SignedPreKeys and Sessions.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
*/
|
|
public abstract void purgeOwnDeviceKeys(OmemoManager omemoManager);
|
|
|
|
/**
|
|
* Return a concrete KeyUtil object that we can use as a utility to create keys etc.
|
|
*
|
|
* @return KeyUtil object
|
|
*/
|
|
public abstract OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph> keyUtil();
|
|
|
|
/**
|
|
* Return our identityKeys fingerprint.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @return fingerprint of our identityKeyPair
|
|
*/
|
|
public OmemoFingerprint getFingerprint(OmemoManager omemoManager) {
|
|
try {
|
|
return keyUtil().getFingerprint(keyUtil().identityKeyFromPair(loadOmemoIdentityKeyPair(omemoManager)));
|
|
|
|
} catch (CorruptedOmemoKeyException e) {
|
|
LOGGER.log(Level.WARNING, "getFingerprint failed due to corrupted identityKeyPair: " + e.getMessage());
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the default deviceId for a user.
|
|
* The defaultDeviceId will be used when the OmemoManager gets instantiated without passing a specific deviceId.
|
|
* If no default id is set, return -1;
|
|
*
|
|
* @param user user
|
|
* @return defaultDeviceId or -1
|
|
*/
|
|
public abstract int getDefaultDeviceId(BareJid user);
|
|
|
|
/**
|
|
* Set the default deviceId of a user.
|
|
*
|
|
* @param user user
|
|
* @param defaultDeviceId defaultDeviceId
|
|
*/
|
|
public abstract void setDefaultDeviceId(BareJid user, int defaultDeviceId);
|
|
|
|
/**
|
|
* Return the fingerprint of the given devices announced identityKey.
|
|
*
|
|
* @param omemoManager omemoManager of our device.
|
|
* @param device device
|
|
* @throws CannotEstablishOmemoSessionException if we cannot establish a session
|
|
* @return fingerprint of the identityKey
|
|
*/
|
|
public OmemoFingerprint getFingerprint(OmemoManager omemoManager, OmemoDevice device) throws CannotEstablishOmemoSessionException {
|
|
T_IdKey idKey;
|
|
|
|
try {
|
|
idKey = loadOmemoIdentityKey(omemoManager, device);
|
|
if (idKey == null) {
|
|
OmemoService.getInstance().buildSessionFromOmemoBundle(omemoManager, device, true);
|
|
}
|
|
idKey = loadOmemoIdentityKey(omemoManager, device);
|
|
} catch (CorruptedOmemoKeyException e) {
|
|
LOGGER.log(Level.WARNING, "getFingerprint failed due to corrupted identityKey: " + e.getMessage());
|
|
return null;
|
|
}
|
|
return keyUtil().getFingerprint(idKey);
|
|
}
|
|
}
|