mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-23 20:42:06 +01:00
Temp commit
This commit is contained in:
parent
0530449e7e
commit
b0acf0bcc3
27 changed files with 740 additions and 744 deletions
|
@ -24,7 +24,7 @@ import java.io.IOException;
|
|||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleElement;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
|
||||
import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;
|
||||
|
@ -141,7 +141,7 @@ public class SignalOmemoKeyUtil extends OmemoKeyUtil<IdentityKeyPair, IdentityKe
|
|||
}
|
||||
|
||||
@Override
|
||||
public PreKeyBundle bundleFromOmemoBundle(OmemoBundleVAxolotlElement bundle, OmemoDevice contact, int preKeyId)
|
||||
public PreKeyBundle bundleFromOmemoBundle(OmemoBundleElement bundle, OmemoDevice contact, int preKeyId)
|
||||
throws CorruptedOmemoKeyException
|
||||
{
|
||||
return new PreKeyBundle(0,
|
||||
|
|
|
@ -55,9 +55,8 @@ import org.jivesoftware.smackx.mam.MamManager;
|
|||
import org.jivesoftware.smackx.muc.MultiUserChat;
|
||||
import org.jivesoftware.smackx.muc.MultiUserChatManager;
|
||||
import org.jivesoftware.smackx.muc.RoomInfo;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
||||
|
@ -148,9 +147,11 @@ public final class OmemoManager extends Manager {
|
|||
* Return an OmemoManager instance for the given connection and deviceId.
|
||||
* If there was an OmemoManager for the connection and id before, return it. Otherwise create a new OmemoManager
|
||||
* instance and return it.
|
||||
*
|
||||
* @param connection XmppConnection.
|
||||
* @param deviceId MUST NOT be null and MUST be greater than 0.
|
||||
* @return
|
||||
*
|
||||
* @return manager
|
||||
*/
|
||||
public synchronized static OmemoManager getInstanceFor(XMPPConnection connection, Integer deviceId) {
|
||||
if (deviceId == null || deviceId < 1) {
|
||||
|
@ -173,10 +174,14 @@ public final class OmemoManager extends Manager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns an OmemoManager instance for the given connection. If there was no OmemoManager for that connection
|
||||
* before, create a new one. If there was one before, return it. If there were multiple managers before, return the
|
||||
* one with the lowest deviceId.
|
||||
* Returns an OmemoManager instance for the given connection. If there was one manager for the connection before,
|
||||
* return it. If there were multiple managers before, return the one with the lowest deviceId.
|
||||
* If there was no manager before, return a new one. As soon as the connection gets authenticated, the manager
|
||||
* will look for local deviceIDs and select the lowest one as its id. If there are not local deviceIds, the manager
|
||||
* will assign itself a random id.
|
||||
*
|
||||
* @param connection XmppConnection.
|
||||
*
|
||||
* @return manager
|
||||
*/
|
||||
public synchronized static OmemoManager getInstanceFor(XMPPConnection connection) {
|
||||
|
@ -201,7 +206,9 @@ public final class OmemoManager extends Manager {
|
|||
|
||||
/**
|
||||
* Set a TrustCallback for this particular OmemoManager.
|
||||
* @param callback trustCallback used to query and modify trust states.
|
||||
* TrustCallbacks are used to query and modify trust decisions.
|
||||
*
|
||||
* @param callback trustCallback.
|
||||
*/
|
||||
public void setTrustCallback(TrustCallback callback) {
|
||||
if (trustCallback != null) {
|
||||
|
@ -237,7 +244,8 @@ public final class OmemoManager extends Manager {
|
|||
/**
|
||||
* Initialize the manager without blocking. Once the manager is successfully initialized, the finishedCallback will
|
||||
* be notified. It will also get notified, if an error occurs.
|
||||
* @param finishedCallback
|
||||
*
|
||||
* @param finishedCallback callback that gets called once the manager is initialized.
|
||||
*/
|
||||
public void initializeAsync(final FinishedCallback finishedCallback) {
|
||||
Async.go(new Runnable() {
|
||||
|
@ -257,7 +265,7 @@ public final class OmemoManager extends Manager {
|
|||
* OMEMO encrypt a cleartext message for a single recipient.
|
||||
* Note that this method does NOT set the 'to' attribute of the message.
|
||||
*
|
||||
* @param to recipients barejid
|
||||
* @param to recipients bareJid
|
||||
* @param message text to encrypt
|
||||
* @return encrypted message
|
||||
* @throws CryptoFailedException when something crypto related fails
|
||||
|
@ -278,7 +286,7 @@ public final class OmemoManager extends Manager {
|
|||
LoggedInOmemoManager guard = new LoggedInOmemoManager(this);
|
||||
Message plaintext = new Message();
|
||||
plaintext.setBody(message);
|
||||
OmemoVAxolotlElement encrypted = getOmemoService().processSendingMessage(guard, to, plaintext);
|
||||
OmemoElement encrypted = getOmemoService().processSendingMessage(guard, to, plaintext);
|
||||
return finishMessage(encrypted);
|
||||
}
|
||||
}
|
||||
|
@ -306,7 +314,7 @@ public final class OmemoManager extends Manager {
|
|||
synchronized (LOCK) {
|
||||
Message m = new Message();
|
||||
m.setBody(message);
|
||||
OmemoVAxolotlElement encrypted = getOmemoService().processSendingMessage(
|
||||
OmemoElement encrypted = getOmemoService().processSendingMessage(
|
||||
new LoggedInOmemoManager(this), recipients, m);
|
||||
return finishMessage(encrypted);
|
||||
}
|
||||
|
@ -368,7 +376,7 @@ public final class OmemoManager extends Manager {
|
|||
synchronized (LOCK) {
|
||||
Message m = new Message();
|
||||
m.setBody(message);
|
||||
OmemoVAxolotlElement encrypted = getOmemoService()
|
||||
OmemoElement encrypted = getOmemoService()
|
||||
.encryptOmemoMessage(new LoggedInOmemoManager(this), exception.getSuccesses(), m);
|
||||
return finishMessage(encrypted);
|
||||
}
|
||||
|
@ -482,43 +490,6 @@ public final class OmemoManager extends Manager {
|
|||
return trustCallback.getTrust(device, fingerprint) != TrustState.undecided;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all other devices except this one from our device list and republish the list.
|
||||
*
|
||||
* @throws InterruptedException
|
||||
* @throws SmackException
|
||||
* @throws XMPPException.XMPPErrorException
|
||||
* @throws CorruptedOmemoKeyException
|
||||
*/
|
||||
public void purgeDeviceList()
|
||||
throws SmackException, InterruptedException, XMPPException.XMPPErrorException, CorruptedOmemoKeyException
|
||||
{
|
||||
synchronized (LOCK) {
|
||||
LoggedInOmemoManager managerGuard = new LoggedInOmemoManager(this);
|
||||
getOmemoService().publishDeviceIdIfNeeded(managerGuard, true);
|
||||
getOmemoService().publishBundle(managerGuard);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate fresh identity keys and bundle and publish it to the server.
|
||||
* @throws SmackException
|
||||
* @throws InterruptedException
|
||||
* @throws XMPPException.XMPPErrorException
|
||||
* @throws CorruptedOmemoKeyException
|
||||
*/
|
||||
public void regenerateIdentity()
|
||||
throws SmackException, InterruptedException, XMPPException.XMPPErrorException, CorruptedOmemoKeyException
|
||||
{
|
||||
synchronized (LOCK) {
|
||||
LoggedInOmemoManager managerGuard = new LoggedInOmemoManager(this);
|
||||
// create a new identity and publish new keys to the server
|
||||
getOmemoService().regenerate(managerGuard);
|
||||
getOmemoService().publishDeviceIdIfNeeded(managerGuard, false);
|
||||
getOmemoService().publishBundle(managerGuard);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a ratchet update message. This can be used to advance the ratchet of a session in order to maintain forward
|
||||
* secrecy.
|
||||
|
@ -552,7 +523,7 @@ public final class OmemoManager extends Manager {
|
|||
* @throws CryptoFailedException When something fails with the crypto
|
||||
* @throws CannotEstablishOmemoSessionException When we can't establish a session with the recipient
|
||||
*/
|
||||
public OmemoVAxolotlElement createKeyTransportElement(byte[] aesKey, byte[] iv, OmemoDevice ... to)
|
||||
public OmemoElement createKeyTransportElement(byte[] aesKey, byte[] iv, OmemoDevice ... to)
|
||||
throws UndecidedOmemoIdentityException, CorruptedOmemoKeyException, CryptoFailedException,
|
||||
CannotEstablishOmemoSessionException, SmackException.NotLoggedInException
|
||||
{
|
||||
|
@ -571,7 +542,7 @@ public final class OmemoManager extends Manager {
|
|||
* @param encrypted OmemoMessageElement
|
||||
* @return Message containing the OMEMO element and some additional information
|
||||
*/
|
||||
Message finishMessage(OmemoVAxolotlElement encrypted) {
|
||||
Message finishMessage(OmemoElement encrypted) {
|
||||
if (encrypted == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -794,8 +765,7 @@ public final class OmemoManager extends Manager {
|
|||
// generate key
|
||||
getOmemoService().getOmemoStoreBackend().changeSignedPreKey(getOwnDevice());
|
||||
// publish
|
||||
getOmemoService().publishDeviceIdIfNeeded(managerGuard, false);
|
||||
getOmemoService().publishBundle(managerGuard);
|
||||
getOmemoService().publish(managerGuard);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -805,7 +775,7 @@ public final class OmemoManager extends Manager {
|
|||
* @return true if stanza has extension 'encrypted'
|
||||
*/
|
||||
public static boolean stanzaContainsOmemoElement(Stanza stanza) {
|
||||
return stanza.hasExtension(OmemoElement.ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
return stanza.hasExtension(OmemoElement.NAME_ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1013,13 +983,13 @@ public final class OmemoManager extends Manager {
|
|||
|
||||
PayloadItem<?> payloadItem = (PayloadItem<?>) item;
|
||||
|
||||
if (!(payloadItem.getPayload() instanceof OmemoDeviceListVAxolotlElement)) {
|
||||
if (!(payloadItem.getPayload() instanceof OmemoDeviceListElement_VAxolotl)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Device List <list>
|
||||
OmemoDeviceListVAxolotlElement omemoDeviceListElement =
|
||||
(OmemoDeviceListVAxolotlElement) payloadItem.getPayload();
|
||||
OmemoDeviceListElement_VAxolotl omemoDeviceListElement =
|
||||
(OmemoDeviceListElement_VAxolotl) payloadItem.getPayload();
|
||||
Integer ourDeviceId = getDeviceId();
|
||||
|
||||
getOmemoService().getOmemoStoreBackend()
|
||||
|
@ -1047,8 +1017,8 @@ public final class OmemoManager extends Manager {
|
|||
|
||||
// enroll at the deviceList
|
||||
deviceListIds.add(ourDeviceId);
|
||||
final OmemoDeviceListVAxolotlElement newOmemoDeviceListElement =
|
||||
new OmemoDeviceListVAxolotlElement(deviceListIds);
|
||||
final OmemoDeviceListElement_VAxolotl newOmemoDeviceListElement =
|
||||
new OmemoDeviceListElement_VAxolotl(deviceListIds);
|
||||
|
||||
// PEPListener is a synchronous listener.
|
||||
// Avoid any deadlocks by using an async task to update the device list.
|
||||
|
|
|
@ -27,6 +27,7 @@ import javax.crypto.IllegalBlockSizeException;
|
|||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoKeyElement;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.MultipleCryptoFailedException;
|
||||
|
@ -67,9 +68,13 @@ public abstract class OmemoRatchet<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
int keyId = omemoManager.getDeviceId();
|
||||
byte[] unpackedKey = null;
|
||||
List<CryptoFailedException> decryptExceptions = new ArrayList<>();
|
||||
List<OmemoElement.OmemoHeader.Key> keys = element.getHeader().getKeys();
|
||||
// CHECKSTYLE: OFF
|
||||
@SuppressWarnings("unchecked")
|
||||
List<OmemoKeyElement> keys = element.getHeader().getKeys();
|
||||
// CHECKSTYLE: ON
|
||||
|
||||
// Find key with our ID.
|
||||
for (OmemoElement.OmemoHeader.Key k : keys) {
|
||||
for (OmemoKeyElement k : keys) {
|
||||
if (k.getId() == keyId) {
|
||||
try {
|
||||
unpackedKey = doubleRatchetDecrypt(sender, k.getData());
|
||||
|
|
|
@ -30,7 +30,6 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -56,11 +55,10 @@ import org.jivesoftware.smackx.mam.MamManager;
|
|||
import org.jivesoftware.smackx.muc.MultiUserChat;
|
||||
import org.jivesoftware.smackx.muc.MultiUserChatManager;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoKeyElement;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
||||
|
@ -206,6 +204,10 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
checkAvailableAlgorithms();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the OmemoManager known to the OmemoService.
|
||||
* @param manager manager.
|
||||
*/
|
||||
void registerManager(OmemoManager manager) {
|
||||
omemoRatchets.put(manager, instantiateOmemoRatchet(manager, getOmemoStoreBackend()));
|
||||
}
|
||||
|
@ -219,7 +221,6 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @throws XMPPException.XMPPErrorException
|
||||
* @throws SmackException.NotConnectedException
|
||||
* @throws SmackException.NoResponseException
|
||||
* @throws SmackException.NotLoggedInException
|
||||
* @throws PubSubException.NotALeafNodeException
|
||||
*/
|
||||
void publish(OmemoManager.LoggedInOmemoManager managerGuard)
|
||||
|
@ -227,12 +228,19 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
SmackException.NotConnectedException, SmackException.NoResponseException,
|
||||
PubSubException.NotALeafNodeException
|
||||
{
|
||||
OmemoManager manager = managerGuard.get();
|
||||
OmemoDevice userDevice = manager.getOwnDevice();
|
||||
|
||||
// Create new keys if necessary and publish to the server.
|
||||
publishBundle(managerGuard);
|
||||
|
||||
// Get fresh device list from server
|
||||
refreshOwnDeviceList(managerGuard);
|
||||
publishDeviceIdIfNeeded(managerGuard, false);
|
||||
CachedDeviceList list = refreshOwnDeviceList(managerGuard);
|
||||
if (!list.isActive(userDevice.getDeviceId())) {
|
||||
list.addDevice(userDevice.getDeviceId());
|
||||
}
|
||||
|
||||
publishDeviceIds(managerGuard, new OmemoDeviceListElement_VAxolotl(list.getActiveDevices()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -256,32 +264,6 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
new OmemoMessageBuilder<>(null, null, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new unique deviceId and regenerate new keys.
|
||||
*
|
||||
* @param managerGuard OmemoManager we want to regenerate.
|
||||
* @throws CorruptedOmemoKeyException when freshly generated identityKey is invalid
|
||||
* (should never ever happen *crosses fingers*)
|
||||
*/
|
||||
void regenerate(OmemoManager.LoggedInOmemoManager managerGuard)
|
||||
throws CorruptedOmemoKeyException, InterruptedException, PubSubException.NotALeafNodeException,
|
||||
XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException {
|
||||
OmemoManager omemoManager = managerGuard.get();
|
||||
OmemoDevice userDevice = omemoManager.getOwnDevice();
|
||||
|
||||
int nDeviceId = OmemoManager.randomDeviceId();
|
||||
|
||||
// Generate unique ID that is not already taken
|
||||
while (!getOmemoStoreBackend().isAvailableDeviceId(userDevice, nDeviceId)) {
|
||||
nDeviceId = OmemoManager.randomDeviceId();
|
||||
}
|
||||
|
||||
getOmemoStoreBackend().purgeOwnDeviceKeys(userDevice);
|
||||
omemoManager.setDeviceId(nDeviceId);
|
||||
|
||||
publish(managerGuard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a bundle to the server.
|
||||
*
|
||||
|
@ -319,70 +301,6 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
new PayloadItem<>(bundleElement));
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish our deviceId in case it is not on the list already.
|
||||
* This method calls publishDeviceIdIfNeeded(omemoManager, deleteOtherDevices, false).
|
||||
* @param managerGuard OmemoManager
|
||||
* @param deleteOtherDevices Do we want to remove other devices from the list?
|
||||
* @throws InterruptedException
|
||||
* @throws PubSubException.NotALeafNodeException
|
||||
* @throws XMPPException.XMPPErrorException
|
||||
* @throws SmackException.NotConnectedException
|
||||
* @throws SmackException.NoResponseException
|
||||
*/
|
||||
void publishDeviceIdIfNeeded(OmemoManager.LoggedInOmemoManager managerGuard, boolean deleteOtherDevices)
|
||||
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
|
||||
SmackException.NotConnectedException, SmackException.NoResponseException
|
||||
{
|
||||
publishDeviceIdIfNeeded(managerGuard, deleteOtherDevices, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish our deviceId in case it is not on the list already.
|
||||
*
|
||||
* @param managerGuard OmemoManager
|
||||
* @param deleteOtherDevices Do we want to remove other devices from the list?
|
||||
* If we do, publish the list with only our id, regardless if we were on the list
|
||||
* already.
|
||||
* @param publish Do we want to force publishing our id?
|
||||
* @throws SmackException.NotConnectedException
|
||||
* @throws InterruptedException
|
||||
* @throws SmackException.NoResponseException
|
||||
* @throws XMPPException.XMPPErrorException
|
||||
* @throws PubSubException.NotALeafNodeException
|
||||
*/
|
||||
void publishDeviceIdIfNeeded(OmemoManager.LoggedInOmemoManager managerGuard, boolean deleteOtherDevices, boolean publish)
|
||||
throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
|
||||
XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException
|
||||
{
|
||||
OmemoManager omemoManager = managerGuard.get();
|
||||
OmemoDevice userDevice = omemoManager.getOwnDevice();
|
||||
|
||||
CachedDeviceList deviceList = getOmemoStoreBackend().loadCachedDeviceList(userDevice, userDevice.getJid());
|
||||
|
||||
Set<Integer> deviceListIds;
|
||||
if (deviceList == null) {
|
||||
deviceListIds = new HashSet<>();
|
||||
} else {
|
||||
deviceListIds = new HashSet<>(deviceList.getActiveDevices());
|
||||
}
|
||||
|
||||
if (deleteOtherDevices) {
|
||||
deviceListIds.clear();
|
||||
}
|
||||
|
||||
int ourDeviceId = omemoManager.getDeviceId();
|
||||
if (deviceListIds.add(ourDeviceId)) {
|
||||
publish = true;
|
||||
}
|
||||
|
||||
publish |= removeStaleDevicesIfNeeded(managerGuard, deviceListIds);
|
||||
|
||||
if (publish) {
|
||||
publishDeviceIds(managerGuard, new OmemoDeviceListVAxolotlElement(deviceListIds));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove stale devices from our device list.
|
||||
* This does only delete devices, if that's configured in OmemoConfiguration.
|
||||
|
@ -482,39 +400,17 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @throws NotAPubSubNodeException
|
||||
*/
|
||||
static OmemoDeviceListElement fetchDeviceList(OmemoManager.LoggedInOmemoManager managerGuard, BareJid contact)
|
||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||
SmackException.NoResponseException, PubSubException.NotALeafNodeException, NotAPubSubNodeException
|
||||
{
|
||||
throws InterruptedException, SmackException.NotConnectedException, SmackException.NoResponseException,
|
||||
XMPPException.XMPPErrorException {
|
||||
try {
|
||||
return extractDeviceListFrom(fetchDeviceListNode(managerGuard, contact));
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh our deviceList from the server.
|
||||
*
|
||||
* @param managerGuard omemoManager
|
||||
* @return true, if we should publish our device list again (because its broken or not existent...)
|
||||
*
|
||||
* @throws SmackException.NotConnectedException
|
||||
* @throws InterruptedException
|
||||
* @throws SmackException.NoResponseException
|
||||
*/
|
||||
private boolean refreshOwnDeviceList(OmemoManager.LoggedInOmemoManager managerGuard)
|
||||
throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
|
||||
XMPPException.XMPPErrorException
|
||||
{
|
||||
OmemoManager omemoManager = managerGuard.get();
|
||||
OmemoDevice userDevice = omemoManager.getOwnDevice();
|
||||
|
||||
try {
|
||||
getOmemoStoreBackend().mergeCachedDeviceList(userDevice, userDevice.getJid(),
|
||||
fetchDeviceList(managerGuard, omemoManager.getOwnJid()));
|
||||
|
||||
} catch (XMPPException.XMPPErrorException e) {
|
||||
catch (XMPPException.XMPPErrorException e) {
|
||||
|
||||
if (e.getXMPPError().getCondition() == StanzaError.Condition.item_not_found) {
|
||||
LOGGER.log(Level.WARNING, "Could not refresh own deviceList, because the node did not exist: "
|
||||
+ e.getMessage());
|
||||
return true;
|
||||
}
|
||||
|
||||
throw e;
|
||||
|
@ -522,15 +418,35 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
} catch (PubSubException.NotALeafNodeException e) {
|
||||
LOGGER.log(Level.WARNING, "Could not refresh own deviceList, because the Node is not a LeafNode: " +
|
||||
e.getMessage());
|
||||
return true;
|
||||
}
|
||||
|
||||
catch (PubSubException.NotAPubSubNodeException e) {
|
||||
LOGGER.log(Level.WARNING, "Caught a PubSubAssertionError when fetching a deviceList node. " +
|
||||
LOGGER.log(Level.WARNING, "Caught a NotAPubSubNodeException when fetching a deviceList node. " +
|
||||
"This probably means that we're dealing with an ejabberd server and the LeafNode does not exist.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh our deviceList from the server.
|
||||
*
|
||||
* @param managerGuard omemoManager
|
||||
* @return true, if we should publish our device list again (because its broken or not existent or
|
||||
* doesn't contain our id...)
|
||||
*
|
||||
* @throws SmackException.NotConnectedException
|
||||
* @throws InterruptedException
|
||||
* @throws SmackException.NoResponseException
|
||||
*/
|
||||
private CachedDeviceList refreshOwnDeviceList(OmemoManager.LoggedInOmemoManager managerGuard)
|
||||
throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
|
||||
XMPPException.XMPPErrorException
|
||||
{
|
||||
OmemoManager omemoManager = managerGuard.get();
|
||||
OmemoDevice userDevice = omemoManager.getOwnDevice();
|
||||
|
||||
OmemoDeviceListElement list = fetchDeviceList(managerGuard, omemoManager.getOwnJid());
|
||||
return getOmemoStoreBackend().mergeCachedDeviceList(userDevice, userDevice.getJid(), list);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -541,20 +457,18 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @throws InterruptedException
|
||||
* @throws SmackException.NoResponseException
|
||||
*/
|
||||
void refreshDeviceList(OmemoManager.LoggedInOmemoManager managerGuard, BareJid contact)
|
||||
CachedDeviceList refreshDeviceList(OmemoManager.LoggedInOmemoManager managerGuard, BareJid contact)
|
||||
throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException
|
||||
{
|
||||
OmemoDeviceListElement omemoDeviceListElement;
|
||||
OmemoDeviceListElement omemoDeviceListElement = null;
|
||||
|
||||
try {
|
||||
omemoDeviceListElement = fetchDeviceList(managerGuard, contact);
|
||||
|
||||
} catch (PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | NotAPubSubNodeException e) {
|
||||
} catch (XMPPException.XMPPErrorException e) {
|
||||
LOGGER.log(Level.WARNING, "Could not fetch device list of " + contact + ": " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
getOmemoStoreBackend().mergeCachedDeviceList(managerGuard.get().getOwnDevice(), contact, omemoDeviceListElement);
|
||||
return getOmemoStoreBackend().mergeCachedDeviceList(managerGuard.get().getOwnDevice(), contact, omemoDeviceListElement);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -570,7 +484,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @throws PubSubException.NotALeafNodeException when the bundles node is not a LeafNode
|
||||
* @throws NotAPubSubNodeException
|
||||
*/
|
||||
static OmemoBundleVAxolotlElement fetchBundle(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contact)
|
||||
static OmemoBundleElement fetchBundle(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contact)
|
||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||
SmackException.NoResponseException, PubSubException.NotALeafNodeException, NotAPubSubNodeException
|
||||
{
|
||||
|
@ -590,22 +504,26 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @throws InterruptedException goes
|
||||
* @throws SmackException.NoResponseException wrong
|
||||
*/
|
||||
private static OmemoBundleVAxolotlElement extractBundleFrom(LeafNode node)
|
||||
private static OmemoBundleElement extractBundleFrom(LeafNode node)
|
||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||
SmackException.NoResponseException
|
||||
{
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (OmemoBundleVAxolotlElement) ((PayloadItem<?>) node.getItems().get(0)).getPayload();
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
|
||||
List<PayloadItem<OmemoBundleElement>> bundleItems = node.getItems();
|
||||
if (bundleItems.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return bundleItems.get(0).getPayload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the OmemoDeviceListElement of a contact from a node containing his OmemoDeviceListElement.
|
||||
* This method also ensures, that the node only contains one item. If there are more than one item in the node,
|
||||
* all items are deleted and the list gets published again.
|
||||
*
|
||||
* @param node typically a LeafNode containing the OmemoDeviceListElement of a contact
|
||||
* @return the extracted OmemoDeviceListElement.
|
||||
|
@ -623,11 +541,10 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
return null;
|
||||
}
|
||||
|
||||
List<?> items = node.getItems();
|
||||
List<PayloadItem<OmemoDeviceListElement>> items = node.getItems();
|
||||
if (items.size() > 0) {
|
||||
|
||||
OmemoDeviceListVAxolotlElement listElement =
|
||||
(OmemoDeviceListVAxolotlElement) ((PayloadItem<?>) items.get(items.size() - 1)).getPayload();
|
||||
OmemoDeviceListElement listElement = items.get(items.size() - 1).getPayload();
|
||||
|
||||
if (items.size() > 1) {
|
||||
node.deleteAllItems();
|
||||
|
@ -638,7 +555,42 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
}
|
||||
|
||||
Set<Integer> emptySet = Collections.emptySet();
|
||||
return new OmemoDeviceListVAxolotlElement(emptySet);
|
||||
return new OmemoDeviceListElement_VAxolotl(emptySet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build sessions for all devices of the contacts in the list, of which we have no session yet.
|
||||
* When there are devices, this method throws a {@link CannotEstablishOmemoSessionException} which contains all
|
||||
* those devices, while still establishing sessions with all other devices.
|
||||
*
|
||||
* @param managerGuard manager
|
||||
* @param jids list of BareJids
|
||||
* @throws SmackException.NotConnectedException
|
||||
* @throws InterruptedException
|
||||
* @throws SmackException.NoResponseException
|
||||
* @throws CannotEstablishOmemoSessionException if we cannot create sessions with some devices.
|
||||
*/
|
||||
void buildMissingOmemoSessions(OmemoManager.LoggedInOmemoManager managerGuard, List<BareJid> jids)
|
||||
throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
|
||||
CannotEstablishOmemoSessionException {
|
||||
|
||||
CannotEstablishOmemoSessionException ex = null;
|
||||
|
||||
for (BareJid jid : jids) {
|
||||
try {
|
||||
buildMissingOmemoSessions(managerGuard, jid);
|
||||
} catch (CannotEstablishOmemoSessionException e) {
|
||||
if (ex == null) {
|
||||
ex = e;
|
||||
} else {
|
||||
ex.addFailures(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ex != null) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -724,7 +676,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
return;
|
||||
}
|
||||
|
||||
OmemoBundleVAxolotlElement bundle;
|
||||
OmemoBundleElement bundle;
|
||||
try {
|
||||
bundle = fetchBundle(managerGuard, contactsDevice);
|
||||
} catch (SmackException | XMPPException.XMPPErrorException | InterruptedException e) {
|
||||
|
@ -758,7 +710,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* device, return null.
|
||||
*
|
||||
* @param contactsDevice OmemoDevice of the sender of the message
|
||||
* @param message the encrypted message
|
||||
* @param omemoElement the encrypted message
|
||||
* @param information OmemoMessageInformation object which will contain meta data about the decrypted message
|
||||
* @return decrypted message or null
|
||||
* @throws NoRawSessionException
|
||||
|
@ -771,7 +723,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
*/
|
||||
private Message processReceivingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
OmemoDevice contactsDevice,
|
||||
OmemoElement message,
|
||||
OmemoElement omemoElement,
|
||||
final OmemoMessageInformation information)
|
||||
throws NoRawSessionException, InterruptedException, SmackException.NoResponseException,
|
||||
SmackException.NotConnectedException, CryptoFailedException, XMPPException.XMPPErrorException,
|
||||
|
@ -780,15 +732,19 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
OmemoManager omemoManager = managerGuard.get();
|
||||
OmemoDevice userDevice = omemoManager.getOwnDevice();
|
||||
|
||||
ArrayList<OmemoVAxolotlElement.OmemoHeader.Key> messageRecipientKeys = message.getHeader().getKeys();
|
||||
// CHECKSTYLE: OFF
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<OmemoKeyElement> messageRecipientKeys = omemoElement.getHeader().getKeys();
|
||||
// CHECKSTYLE: ON
|
||||
|
||||
// Do we have a key with our ID in the message?
|
||||
for (OmemoVAxolotlElement.OmemoHeader.Key k : messageRecipientKeys) {
|
||||
for (OmemoKeyElement k : messageRecipientKeys) {
|
||||
// Only decrypt with our deviceID
|
||||
if (k.getId() != omemoManager.getDeviceId()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Message decrypted = decryptOmemoMessageElement(managerGuard, contactsDevice, message, information);
|
||||
Message decrypted = decryptOmemoMessageElement(managerGuard, contactsDevice, omemoElement, information);
|
||||
if (contactsDevice.equals(omemoManager.getOwnJid()) && decrypted != null) {
|
||||
getOmemoStoreBackend().setDateOfLastReceivedMessage(userDevice, contactsDevice, new Date());
|
||||
}
|
||||
|
@ -823,7 +779,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
CryptoFailedException, XMPPException.XMPPErrorException, CorruptedOmemoKeyException, NoRawSessionException
|
||||
{
|
||||
if (OmemoManager.stanzaContainsOmemoElement(message)) {
|
||||
OmemoElement omemoMessageElement = message.getExtension(OmemoElement.ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
OmemoElement omemoMessageElement = message.getExtension(OmemoElement.NAME_ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
OmemoMessageInformation info = new OmemoMessageInformation();
|
||||
Message decrypted = processReceivingMessage(managerGuard,
|
||||
new OmemoDevice(sender, omemoMessageElement.getHeader().getSid()),
|
||||
|
@ -847,7 +803,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @throws UndecidedOmemoIdentityException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
OmemoVAxolotlElement processSendingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
OmemoElement processSendingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
BareJid recipient,
|
||||
Message message)
|
||||
throws CryptoFailedException, UndecidedOmemoIdentityException, NoSuchAlgorithmException,
|
||||
|
@ -871,7 +827,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @throws UndecidedOmemoIdentityException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
OmemoVAxolotlElement processSendingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
OmemoElement processSendingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
ArrayList<BareJid> recipients,
|
||||
Message message)
|
||||
throws CryptoFailedException, UndecidedOmemoIdentityException, NoSuchAlgorithmException,
|
||||
|
@ -1042,7 +998,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
*
|
||||
* @return OmemoMessageElement
|
||||
*/
|
||||
OmemoVAxolotlElement encryptOmemoMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
OmemoElement encryptOmemoMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
HashMap<BareJid, ArrayList<OmemoDevice>> recipients,
|
||||
Message message)
|
||||
throws CryptoFailedException, UndecidedOmemoIdentityException
|
||||
|
@ -1095,7 +1051,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @throws CorruptedOmemoKeyException
|
||||
* @throws CannotEstablishOmemoSessionException
|
||||
*/
|
||||
OmemoVAxolotlElement prepareOmemoKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
OmemoElement prepareOmemoKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
OmemoDevice... recipients)
|
||||
throws CryptoFailedException, UndecidedOmemoIdentityException, CorruptedOmemoKeyException,
|
||||
CannotEstablishOmemoSessionException
|
||||
|
@ -1130,7 +1086,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @throws CorruptedOmemoKeyException
|
||||
* @throws CannotEstablishOmemoSessionException
|
||||
*/
|
||||
OmemoVAxolotlElement prepareOmemoKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
OmemoElement prepareOmemoKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
byte[] aesKey,
|
||||
byte[] iv,
|
||||
OmemoDevice... recipients)
|
||||
|
@ -1177,7 +1133,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
buildSessionWithDevice(managerGuard, recipient, true);
|
||||
}
|
||||
|
||||
OmemoVAxolotlElement keyTransportElement = prepareOmemoKeyTransportElement(managerGuard, recipient);
|
||||
OmemoElement keyTransportElement = prepareOmemoKeyTransportElement(managerGuard, recipient);
|
||||
Message ratchetUpdateMessage = managerGuard.get().finishMessage(keyTransportElement);
|
||||
ratchetUpdateMessage.setTo(recipient.getJid());
|
||||
|
||||
|
@ -1262,7 +1218,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
*/
|
||||
private static OmemoDevice getSender(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||
Stanza stanza) {
|
||||
OmemoElement omemoElement = stanza.getExtension(OmemoElement.ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
OmemoElement omemoElement = stanza.getExtension(OmemoElement.NAME_ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
Jid sender = stanza.getFrom();
|
||||
if (isMucMessage(managerGuard, stanza)) {
|
||||
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(managerGuard.get().getConnection());
|
||||
|
@ -1292,7 +1248,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
public void onOmemoMessageStanzaReceived(Stanza stanza, OmemoManager.LoggedInOmemoManager managerGuard) {
|
||||
OmemoManager omemoManager = managerGuard.get();
|
||||
Message decrypted;
|
||||
OmemoElement omemoMessage = stanza.getExtension(OmemoElement.ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
OmemoElement omemoMessage = stanza.getExtension(OmemoElement.NAME_ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
OmemoMessageInformation messageInfo = new OmemoMessageInformation();
|
||||
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(omemoManager.getConnection());
|
||||
OmemoDevice senderDevice = getSender(managerGuard, stanza);
|
||||
|
@ -1372,7 +1328,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
final OmemoDevice senderDevice = getSender(managerGuard, carbonCopy);
|
||||
Message decrypted;
|
||||
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(omemoManager.getConnection());
|
||||
OmemoElement omemoMessage = carbonCopy.getExtension(OmemoElement.ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
OmemoElement omemoMessage = carbonCopy.getExtension(OmemoElement.NAME_ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
|
||||
OmemoMessageInformation messageInfo = new OmemoMessageInformation();
|
||||
|
||||
if (CarbonExtension.Direction.received.equals(direction)) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
package org.jivesoftware.smackx.omemo;
|
||||
|
||||
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.TARGET_PRE_KEY_COUNT;
|
||||
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.PRE_KEY_COUNT_PER_BUNDLE;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
@ -26,7 +26,7 @@ import java.util.TreeMap;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||
|
@ -99,7 +99,7 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
|||
* @param contact Contact we received the list from.
|
||||
* @param list List we received.
|
||||
*/
|
||||
void mergeCachedDeviceList(OmemoDevice userDevice, BareJid contact, OmemoDeviceListElement list) {
|
||||
CachedDeviceList mergeCachedDeviceList(OmemoDevice userDevice, BareJid contact, OmemoDeviceListElement list) {
|
||||
CachedDeviceList cached = loadCachedDeviceList(userDevice, contact);
|
||||
|
||||
if (cached == null) {
|
||||
|
@ -108,10 +108,12 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
|||
|
||||
if (list != null) {
|
||||
cached.merge(list.getDeviceIds());
|
||||
}
|
||||
storeCachedDeviceList(userDevice, contact, cached);
|
||||
}
|
||||
|
||||
return 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).
|
||||
|
@ -165,13 +167,30 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
|||
/**
|
||||
* 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.
|
||||
* We should always publish PRE_KEY_COUNT_PER_BUNDLE keys.
|
||||
*
|
||||
* @param userDevice our OmemoDevice.
|
||||
* @return OmemoBundleElement
|
||||
* @throws CorruptedOmemoKeyException when a key could not be loaded
|
||||
*/
|
||||
OmemoBundleVAxolotlElement packOmemoBundle(OmemoDevice userDevice)
|
||||
OmemoBundleElement_VAxolotl packOmemoBundle(OmemoDevice userDevice)
|
||||
throws CorruptedOmemoKeyException
|
||||
{
|
||||
createMissingKeys(userDevice);
|
||||
|
||||
int currentSignedPreKeyId = loadCurrentOmemoSignedPreKeyId(userDevice);
|
||||
T_SigPreKey currentSignedPreKey = loadOmemoSignedPreKeys(userDevice).get(currentSignedPreKeyId);
|
||||
|
||||
return new OmemoBundleElement_VAxolotl(
|
||||
currentSignedPreKeyId,
|
||||
keyUtil().signedPreKeyPublicForBundle(currentSignedPreKey),
|
||||
keyUtil().signedPreKeySignatureFromKey(currentSignedPreKey),
|
||||
keyUtil().identityKeyForBundle(keyUtil().identityKeyFromPair(loadOmemoIdentityKeyPair(userDevice))),
|
||||
keyUtil().preKeyPublicKeysForBundle(loadOmemoPreKeys(userDevice))
|
||||
);
|
||||
}
|
||||
|
||||
private void createMissingKeys(OmemoDevice userDevice)
|
||||
throws CorruptedOmemoKeyException
|
||||
{
|
||||
T_IdKeyPair identityKeyPair = loadOmemoIdentityKeyPair(userDevice);
|
||||
|
@ -183,29 +202,16 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
|||
TreeMap<Integer, T_SigPreKey> signedPreKeys = loadOmemoSignedPreKeys(userDevice);
|
||||
if (signedPreKeys.size() == 0) {
|
||||
changeSignedPreKey(userDevice);
|
||||
signedPreKeys = loadOmemoSignedPreKeys(userDevice);
|
||||
}
|
||||
|
||||
int currentSignedPreKeyId = signedPreKeys.lastKey();
|
||||
T_SigPreKey currentSignedPreKey = signedPreKeys.get(currentSignedPreKeyId);
|
||||
|
||||
TreeMap<Integer, T_PreKey> preKeys = loadOmemoPreKeys(userDevice);
|
||||
int newKeysCount = TARGET_PRE_KEY_COUNT - preKeys.size();
|
||||
int newKeysCount = PRE_KEY_COUNT_PER_BUNDLE - preKeys.size();
|
||||
int startId = preKeys.size() == 0 ? 0 : preKeys.lastKey();
|
||||
|
||||
if (newKeysCount > 0) {
|
||||
TreeMap<Integer, T_PreKey> newKeys = generateOmemoPreKeys(startId + 1, newKeysCount);
|
||||
storeOmemoPreKeys(userDevice, newKeys);
|
||||
preKeys.putAll(newKeys);
|
||||
}
|
||||
|
||||
return new OmemoBundleVAxolotlElement(
|
||||
currentSignedPreKeyId,
|
||||
keyUtil().signedPreKeyPublicForBundle(currentSignedPreKey),
|
||||
keyUtil().signedPreKeySignatureFromKey(currentSignedPreKey),
|
||||
keyUtil().identityKeyForBundle(keyUtil().identityKeyFromPair(identityKeyPair)),
|
||||
keyUtil().preKeyPublicKeysForBundle(preKeys)
|
||||
);
|
||||
}
|
||||
|
||||
// *sigh*
|
||||
|
@ -374,6 +380,10 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
|||
*/
|
||||
public abstract T_SigPreKey loadOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId);
|
||||
|
||||
public int loadCurrentOmemoSignedPreKeyId(OmemoDevice userDevice) {
|
||||
return loadOmemoSignedPreKeys(userDevice).lastKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all our signed PreKeys.
|
||||
*
|
||||
|
@ -475,6 +485,15 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
|||
*/
|
||||
public abstract CachedDeviceList loadCachedDeviceList(OmemoDevice userDevice, BareJid contact);
|
||||
|
||||
/**
|
||||
* Load a list of deviceIds from our own devices.
|
||||
* @param userDevice
|
||||
* @return
|
||||
*/
|
||||
public CachedDeviceList loadCachedDeviceList(OmemoDevice userDevice) {
|
||||
return loadCachedDeviceList(userDevice, userDevice.getJid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the DeviceList of the contact in local storage.
|
||||
* See this as a cache.
|
||||
|
|
|
@ -16,12 +16,15 @@
|
|||
*/
|
||||
package org.jivesoftware.smackx.omemo.element;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
/**
|
||||
* Class that represents an OMEMO Bundle element.
|
||||
* TODO: Move functionality to here.
|
||||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
|
@ -36,8 +39,173 @@ public abstract class OmemoBundleElement implements ExtensionElement {
|
|||
public static final String PRE_KEY_PUB = "preKeyPublic";
|
||||
public static final String PRE_KEY_ID = "preKeyId";
|
||||
|
||||
private final int signedPreKeyId;
|
||||
private final String signedPreKeyB64;
|
||||
private byte[] signedPreKey;
|
||||
private final String signedPreKeySignatureB64;
|
||||
private byte[] signedPreKeySignature;
|
||||
private final String identityKeyB64;
|
||||
private byte[] identityKey;
|
||||
private final HashMap<Integer, String> preKeysB64;
|
||||
private HashMap<Integer, byte[]> preKeys;
|
||||
|
||||
/**
|
||||
* Constructor to create a Bundle Element from base64 Strings.
|
||||
*
|
||||
* @param signedPreKeyId id
|
||||
* @param signedPreKeyB64 base64 encoded signedPreKey
|
||||
* @param signedPreKeySigB64 base64 encoded signedPreKeySignature
|
||||
* @param identityKeyB64 base64 encoded identityKey
|
||||
* @param preKeysB64 HashMap of base64 encoded preKeys
|
||||
*/
|
||||
public OmemoBundleElement(int signedPreKeyId, String signedPreKeyB64, String signedPreKeySigB64, String identityKeyB64, HashMap<Integer, String> preKeysB64) {
|
||||
this.signedPreKeyId = signedPreKeyId;
|
||||
this.signedPreKeyB64 = signedPreKeyB64;
|
||||
this.signedPreKeySignatureB64 = signedPreKeySigB64;
|
||||
this.identityKeyB64 = identityKeyB64;
|
||||
this.preKeysB64 = preKeysB64;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to create a Bundle Element from decoded byte arrays.
|
||||
*
|
||||
* @param signedPreKeyId id
|
||||
* @param signedPreKey signedPreKey
|
||||
* @param signedPreKeySig signedPreKeySignature
|
||||
* @param identityKey identityKey
|
||||
* @param preKeys HashMap of preKeys
|
||||
*/
|
||||
public OmemoBundleElement(int signedPreKeyId, byte[] signedPreKey, byte[] signedPreKeySig, byte[] identityKey, HashMap<Integer, byte[]> preKeys) {
|
||||
this.signedPreKeyId = signedPreKeyId;
|
||||
|
||||
this.signedPreKey = signedPreKey;
|
||||
this.signedPreKeyB64 = Base64.encodeToString(signedPreKey);
|
||||
|
||||
this.signedPreKeySignature = signedPreKeySig;
|
||||
this.signedPreKeySignatureB64 = Base64.encodeToString(signedPreKeySignature);
|
||||
|
||||
this.identityKey = identityKey;
|
||||
this.identityKeyB64 = Base64.encodeToString(identityKey);
|
||||
|
||||
this.preKeys = preKeys;
|
||||
this.preKeysB64 = new HashMap<>();
|
||||
for (int id : preKeys.keySet()) {
|
||||
preKeysB64.put(id, Base64.encodeToString(preKeys.get(id)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the signedPreKey of the OmemoBundleElement.
|
||||
*
|
||||
* @return signedPreKey as byte array
|
||||
*/
|
||||
public byte[] getSignedPreKey() {
|
||||
if (signedPreKey == null) {
|
||||
signedPreKey = Base64.decode(signedPreKeyB64);
|
||||
}
|
||||
return this.signedPreKey.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the id of the signedPreKey in the bundle.
|
||||
*
|
||||
* @return id of signedPreKey
|
||||
*/
|
||||
public int getSignedPreKeyId() {
|
||||
return this.signedPreKeyId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the signature of the signedPreKey.
|
||||
*
|
||||
* @return signature as byte array
|
||||
*/
|
||||
public byte[] getSignedPreKeySignature() {
|
||||
if (signedPreKeySignature == null) {
|
||||
signedPreKeySignature = Base64.decode(signedPreKeySignatureB64);
|
||||
}
|
||||
return signedPreKeySignature.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the public identityKey of the bundles owner.
|
||||
* This can be used to check the signedPreKeys signature.
|
||||
* The fingerprint of this key is, what the user has to verify.
|
||||
*
|
||||
* @return public identityKey as byte array
|
||||
*/
|
||||
public byte[] getIdentityKey() {
|
||||
if (identityKey == null) {
|
||||
identityKey = Base64.decode(identityKeyB64);
|
||||
}
|
||||
return this.identityKey.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HashMap of preKeys in the bundle.
|
||||
* The map uses the preKeys ids as key and the preKeys as value.
|
||||
*
|
||||
* @return preKeys
|
||||
*/
|
||||
public HashMap<Integer, byte[]> getPreKeys() {
|
||||
if (preKeys == null) {
|
||||
preKeys = new HashMap<>();
|
||||
for (int id : preKeysB64.keySet()) {
|
||||
preKeys.put(id, Base64.decode(preKeysB64.get(id)));
|
||||
}
|
||||
}
|
||||
return this.preKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a single preKey from the map.
|
||||
*
|
||||
* @param id id of the preKey
|
||||
* @return the preKey
|
||||
*/
|
||||
public byte[] getPreKey(int id) {
|
||||
return getPreKeys().get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract XmlStringBuilder toXML(String enclosingNamespace);
|
||||
public String getElementName() {
|
||||
return BUNDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML(String enclosingNamespace) {
|
||||
XmlStringBuilder sb = new XmlStringBuilder(this, enclosingNamespace).rightAngleBracket();
|
||||
|
||||
sb.halfOpenElement(SIGNED_PRE_KEY_PUB).attribute(SIGNED_PRE_KEY_ID, signedPreKeyId).rightAngleBracket()
|
||||
.append(signedPreKeyB64).closeElement(SIGNED_PRE_KEY_PUB);
|
||||
|
||||
sb.openElement(SIGNED_PRE_KEY_SIG).append(signedPreKeySignatureB64).closeElement(SIGNED_PRE_KEY_SIG);
|
||||
|
||||
sb.openElement(IDENTITY_KEY).append(identityKeyB64).closeElement(IDENTITY_KEY);
|
||||
|
||||
sb.openElement(PRE_KEYS);
|
||||
for (Map.Entry<Integer, String> p : this.preKeysB64.entrySet()) {
|
||||
sb.halfOpenElement(PRE_KEY_PUB).attribute(PRE_KEY_ID, p.getKey()).rightAngleBracket()
|
||||
.append(p.getValue()).closeElement(PRE_KEY_PUB);
|
||||
}
|
||||
sb.closeElement(PRE_KEYS);
|
||||
|
||||
sb.closeElement(this);
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String out = "OmemoBundleElement[\n";
|
||||
out += SIGNED_PRE_KEY_PUB + " " + SIGNED_PRE_KEY_ID + "=" + signedPreKeyId + ": " + signedPreKeyB64 + "\n";
|
||||
out += SIGNED_PRE_KEY_SIG + ": " + signedPreKeySignatureB64 + "\n";
|
||||
out += IDENTITY_KEY + ": " + identityKeyB64 + "\n";
|
||||
out += PRE_KEYS + " (" + preKeysB64.size() + ")\n";
|
||||
for (Map.Entry<Integer, String> e : preKeysB64.entrySet()) {
|
||||
out += PRE_KEY_PUB + " " + PRE_KEY_ID + "=" + e.getKey() + ": " + e.getValue() + "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
*
|
||||
* 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.element;
|
||||
|
||||
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* OMEMO device bundle as described here:
|
||||
* https://xmpp.org/extensions/xep-0384.html#usecases-announcing (Example 3).
|
||||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
public class OmemoBundleElement_VAxolotl extends OmemoBundleElement {
|
||||
|
||||
public OmemoBundleElement_VAxolotl(int signedPreKeyId, String signedPreKeyB64, String signedPreKeySigB64, String identityKeyB64, HashMap<Integer, String> preKeysB64) {
|
||||
super(signedPreKeyId, signedPreKeyB64, signedPreKeySigB64, identityKeyB64, preKeysB64);
|
||||
}
|
||||
|
||||
public OmemoBundleElement_VAxolotl(int signedPreKeyId, byte[] signedPreKey, byte[] signedPreKeySig, byte[] identityKey, HashMap<Integer, byte[]> preKeys) {
|
||||
super(signedPreKeyId, signedPreKey, signedPreKeySig, identityKey, preKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return OMEMO_NAMESPACE_V_AXOLOTL;
|
||||
}
|
||||
}
|
|
@ -1,207 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* 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.element;
|
||||
|
||||
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
/**
|
||||
* OMEMO device bundle as described here:
|
||||
* https://xmpp.org/extensions/xep-0384.html#usecases-announcing (Example 3).
|
||||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
public class OmemoBundleVAxolotlElement extends OmemoBundleElement {
|
||||
|
||||
private final int signedPreKeyId;
|
||||
private final String signedPreKeyB64;
|
||||
private byte[] signedPreKey;
|
||||
private final String signedPreKeySignatureB64;
|
||||
private byte[] signedPreKeySignature;
|
||||
private final String identityKeyB64;
|
||||
private byte[] identityKey;
|
||||
private final HashMap<Integer, String> preKeysB64;
|
||||
private HashMap<Integer, byte[]> preKeys;
|
||||
|
||||
/**
|
||||
* Constructor to create a Bundle Element from base64 Strings.
|
||||
*
|
||||
* @param signedPreKeyId id
|
||||
* @param signedPreKeyB64 base64 encoded signedPreKey
|
||||
* @param signedPreKeySigB64 base64 encoded signedPreKeySignature
|
||||
* @param identityKeyB64 base64 encoded identityKey
|
||||
* @param preKeysB64 HashMap of base64 encoded preKeys
|
||||
*/
|
||||
public OmemoBundleVAxolotlElement(int signedPreKeyId, String signedPreKeyB64, String signedPreKeySigB64, String identityKeyB64, HashMap<Integer, String> preKeysB64) {
|
||||
this.signedPreKeyId = signedPreKeyId;
|
||||
this.signedPreKeyB64 = signedPreKeyB64;
|
||||
this.signedPreKeySignatureB64 = signedPreKeySigB64;
|
||||
this.identityKeyB64 = identityKeyB64;
|
||||
this.preKeysB64 = preKeysB64;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to create a Bundle Element from decoded byte arrays.
|
||||
*
|
||||
* @param signedPreKeyId id
|
||||
* @param signedPreKey signedPreKey
|
||||
* @param signedPreKeySig signedPreKeySignature
|
||||
* @param identityKey identityKey
|
||||
* @param preKeys HashMap of preKeys
|
||||
*/
|
||||
public OmemoBundleVAxolotlElement(int signedPreKeyId, byte[] signedPreKey, byte[] signedPreKeySig, byte[] identityKey, HashMap<Integer, byte[]> preKeys) {
|
||||
this.signedPreKeyId = signedPreKeyId;
|
||||
|
||||
this.signedPreKey = signedPreKey;
|
||||
this.signedPreKeyB64 = Base64.encodeToString(signedPreKey);
|
||||
|
||||
this.signedPreKeySignature = signedPreKeySig;
|
||||
this.signedPreKeySignatureB64 = Base64.encodeToString(signedPreKeySignature);
|
||||
|
||||
this.identityKey = identityKey;
|
||||
this.identityKeyB64 = Base64.encodeToString(identityKey);
|
||||
|
||||
this.preKeys = preKeys;
|
||||
this.preKeysB64 = new HashMap<>();
|
||||
for (int id : preKeys.keySet()) {
|
||||
preKeysB64.put(id, Base64.encodeToString(preKeys.get(id)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the signedPreKey of the OmemoBundleElement.
|
||||
*
|
||||
* @return signedPreKey as byte array
|
||||
*/
|
||||
public byte[] getSignedPreKey() {
|
||||
if (signedPreKey == null) {
|
||||
signedPreKey = Base64.decode(signedPreKeyB64);
|
||||
}
|
||||
return this.signedPreKey.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the id of the signedPreKey in the bundle.
|
||||
*
|
||||
* @return id of signedPreKey
|
||||
*/
|
||||
public int getSignedPreKeyId() {
|
||||
return this.signedPreKeyId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the signature of the signedPreKey.
|
||||
*
|
||||
* @return signature as byte array
|
||||
*/
|
||||
public byte[] getSignedPreKeySignature() {
|
||||
if (signedPreKeySignature == null) {
|
||||
signedPreKeySignature = Base64.decode(signedPreKeySignatureB64);
|
||||
}
|
||||
return signedPreKeySignature.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the public identityKey of the bundles owner.
|
||||
* This can be used to check the signedPreKeys signature.
|
||||
* The fingerprint of this key is, what the user has to verify.
|
||||
*
|
||||
* @return public identityKey as byte array
|
||||
*/
|
||||
public byte[] getIdentityKey() {
|
||||
if (identityKey == null) {
|
||||
identityKey = Base64.decode(identityKeyB64);
|
||||
}
|
||||
return this.identityKey.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HashMap of preKeys in the bundle.
|
||||
* The map uses the preKeys ids as key and the preKeys as value.
|
||||
*
|
||||
* @return preKeys
|
||||
*/
|
||||
public HashMap<Integer, byte[]> getPreKeys() {
|
||||
if (preKeys == null) {
|
||||
preKeys = new HashMap<>();
|
||||
for (int id : preKeysB64.keySet()) {
|
||||
preKeys.put(id, Base64.decode(preKeysB64.get(id)));
|
||||
}
|
||||
}
|
||||
return this.preKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a single preKey from the map.
|
||||
*
|
||||
* @param id id of the preKey
|
||||
* @return the preKey
|
||||
*/
|
||||
public byte[] getPreKey(int id) {
|
||||
return getPreKeys().get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return BUNDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML(String enclosingNamespace) {
|
||||
XmlStringBuilder sb = new XmlStringBuilder(this).rightAngleBracket();
|
||||
|
||||
sb.halfOpenElement(SIGNED_PRE_KEY_PUB).attribute(SIGNED_PRE_KEY_ID, signedPreKeyId).rightAngleBracket()
|
||||
.append(signedPreKeyB64).closeElement(SIGNED_PRE_KEY_PUB);
|
||||
|
||||
sb.openElement(SIGNED_PRE_KEY_SIG).append(signedPreKeySignatureB64).closeElement(SIGNED_PRE_KEY_SIG);
|
||||
|
||||
sb.openElement(IDENTITY_KEY).append(identityKeyB64).closeElement(IDENTITY_KEY);
|
||||
|
||||
sb.openElement(PRE_KEYS);
|
||||
for (Map.Entry<Integer, String> p : this.preKeysB64.entrySet()) {
|
||||
sb.halfOpenElement(PRE_KEY_PUB).attribute(PRE_KEY_ID, p.getKey()).rightAngleBracket()
|
||||
.append(p.getValue()).closeElement(PRE_KEY_PUB);
|
||||
}
|
||||
sb.closeElement(PRE_KEYS);
|
||||
|
||||
sb.closeElement(this);
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return OMEMO_NAMESPACE_V_AXOLOTL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String out = "OmemoBundleElement[\n";
|
||||
out += SIGNED_PRE_KEY_PUB + " " + SIGNED_PRE_KEY_ID + "=" + signedPreKeyId + ": " + signedPreKeyB64 + "\n";
|
||||
out += SIGNED_PRE_KEY_SIG + ": " + signedPreKeySignatureB64 + "\n";
|
||||
out += IDENTITY_KEY + ": " + identityKeyB64 + "\n";
|
||||
out += PRE_KEYS + " (" + preKeysB64.size() + ")\n";
|
||||
for (Map.Entry<Integer, String> e : preKeysB64.entrySet()) {
|
||||
out += PRE_KEY_PUB + " " + PRE_KEY_ID + "=" + e.getKey() + ": " + e.getValue() + "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
|
@ -25,9 +25,9 @@ import java.util.Set;
|
|||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
public class OmemoDeviceListVAxolotlElement extends OmemoDeviceListElement {
|
||||
public class OmemoDeviceListElement_VAxolotl extends OmemoDeviceListElement {
|
||||
|
||||
public OmemoDeviceListVAxolotlElement(Set<Integer> deviceIds) {
|
||||
public OmemoDeviceListElement_VAxolotl(Set<Integer> deviceIds) {
|
||||
super(deviceIds);
|
||||
}
|
||||
|
|
@ -16,17 +16,13 @@
|
|||
*/
|
||||
package org.jivesoftware.smackx.omemo.element;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.NamedElement;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
/**
|
||||
* Class that represents an OmemoElement.
|
||||
* TODO: Move functionality here.
|
||||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
|
@ -35,17 +31,11 @@ public abstract class OmemoElement implements ExtensionElement {
|
|||
public static final int TYPE_OMEMO_PREKEY_MESSAGE = 1;
|
||||
public static final int TYPE_OMEMO_MESSAGE = 0;
|
||||
|
||||
public static final String ENCRYPTED = "encrypted";
|
||||
public static final String HEADER = "header";
|
||||
public static final String SID = "sid";
|
||||
public static final String KEY = "key";
|
||||
public static final String RID = "rid";
|
||||
public static final String PREKEY = "prekey";
|
||||
public static final String IV = "iv";
|
||||
public static final String PAYLOAD = "payload";
|
||||
public static final String NAME_ENCRYPTED = "encrypted";
|
||||
public static final String ATTR_PAYLOAD = "payload";
|
||||
|
||||
protected final OmemoElement.OmemoHeader header;
|
||||
protected final byte[] payload;
|
||||
private final OmemoHeaderElement header;
|
||||
private final byte[] payload;
|
||||
|
||||
/**
|
||||
* Create a new OmemoMessageElement from a header and a payload.
|
||||
|
@ -53,12 +43,12 @@ public abstract class OmemoElement implements ExtensionElement {
|
|||
* @param header header of the message
|
||||
* @param payload payload
|
||||
*/
|
||||
public OmemoElement(OmemoElement.OmemoHeader header, byte[] payload) {
|
||||
public OmemoElement(OmemoHeaderElement header, byte[] payload) {
|
||||
this.header = Objects.requireNonNull(header);
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public OmemoElement.OmemoHeader getHeader() {
|
||||
public OmemoHeaderElement getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
|
@ -82,113 +72,22 @@ public abstract class OmemoElement implements ExtensionElement {
|
|||
return payload != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Header element of the message. The header contains information about the sender and the encrypted keys for
|
||||
* the recipients, as well as the iv element for AES.
|
||||
*/
|
||||
public static class OmemoHeader implements NamedElement {
|
||||
private final int sid;
|
||||
private final ArrayList<Key> keys;
|
||||
private final byte[] iv;
|
||||
|
||||
public OmemoHeader(int sid, ArrayList<OmemoHeader.Key> keys, byte[] iv) {
|
||||
this.sid = sid;
|
||||
this.keys = keys;
|
||||
this.iv = iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the deviceId of the sender of the message.
|
||||
*
|
||||
* @return senders id
|
||||
*/
|
||||
public int getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public ArrayList<OmemoHeader.Key> getKeys() {
|
||||
return new ArrayList<>(keys);
|
||||
}
|
||||
|
||||
public byte[] getIv() {
|
||||
return iv != null ? iv.clone() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return HEADER;
|
||||
public XmlStringBuilder toXML(String enclosingNamespace) {
|
||||
XmlStringBuilder sb = new XmlStringBuilder(this, enclosingNamespace).rightAngleBracket();
|
||||
|
||||
sb.element(header);
|
||||
|
||||
if (payload != null) {
|
||||
sb.openElement(ATTR_PAYLOAD).append(Base64.encodeToString(payload)).closeElement(ATTR_PAYLOAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toXML(String enclosingNamespace) {
|
||||
XmlStringBuilder sb = new XmlStringBuilder(this);
|
||||
sb.attribute(SID, getSid()).rightAngleBracket();
|
||||
|
||||
for (OmemoHeader.Key k : getKeys()) {
|
||||
sb.element(k);
|
||||
}
|
||||
|
||||
sb.openElement(IV).append(Base64.encodeToString(getIv())).closeElement(IV);
|
||||
|
||||
return sb.closeElement(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Small class to collect key (byte[]), its id and whether its a prekey or not.
|
||||
*/
|
||||
public static class Key implements NamedElement {
|
||||
final byte[] data;
|
||||
final int id;
|
||||
final boolean preKey;
|
||||
|
||||
public Key(byte[] data, int id) {
|
||||
this.data = data;
|
||||
this.id = id;
|
||||
this.preKey = false;
|
||||
}
|
||||
|
||||
public Key(byte[] data, int id, boolean preKey) {
|
||||
this.data = data;
|
||||
this.id = id;
|
||||
this.preKey = preKey;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public boolean isPreKey() {
|
||||
return this.preKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Integer.toString(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toXML(String enclosingNamespace) {
|
||||
XmlStringBuilder sb = new XmlStringBuilder(this);
|
||||
|
||||
if (isPreKey()) {
|
||||
sb.attribute(PREKEY, true);
|
||||
}
|
||||
|
||||
sb.attribute(RID, getId());
|
||||
sb.rightAngleBracket();
|
||||
sb.append(Base64.encodeToString(getData()));
|
||||
sb.closeElement(this);
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return NAME_ENCRYPTED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
*
|
||||
* 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.element;
|
||||
|
||||
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL;
|
||||
|
||||
/**
|
||||
* An OMEMO (PreKey)WhisperMessage element.
|
||||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
public class OmemoElement_VAxolotl extends OmemoElement {
|
||||
|
||||
/**
|
||||
* Create a new OmemoMessageElement from a header and a payload.
|
||||
*
|
||||
* @param header header of the message
|
||||
* @param payload payload
|
||||
*/
|
||||
public OmemoElement_VAxolotl(OmemoHeaderElement_VAxolotl header, byte[] payload) {
|
||||
super(header, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return OMEMO_NAMESPACE_V_AXOLOTL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
*
|
||||
* 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.element;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.jivesoftware.smack.packet.NamedElement;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
/**
|
||||
* Header element of the message. The header contains information about the sender and the encrypted keys for
|
||||
* the recipients, as well as the iv element for AES.
|
||||
*/
|
||||
public abstract class OmemoHeaderElement implements NamedElement {
|
||||
|
||||
public static final String NAME_HEADER = "header";
|
||||
public static final String ATTR_SID = "sid";
|
||||
public static final String ATTR_IV = "iv";
|
||||
|
||||
private final int sid;
|
||||
private final ArrayList<OmemoKeyElement> keys;
|
||||
private final byte[] iv;
|
||||
|
||||
public OmemoHeaderElement(int sid, ArrayList<OmemoKeyElement> keys, byte[] iv) {
|
||||
this.sid = sid;
|
||||
this.keys = keys;
|
||||
this.iv = iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the deviceId of the sender of the message.
|
||||
*
|
||||
* @return senders id
|
||||
*/
|
||||
public int getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public ArrayList<OmemoKeyElement> getKeys() {
|
||||
return new ArrayList<>(keys);
|
||||
}
|
||||
|
||||
public byte[] getIv() {
|
||||
return iv != null ? iv.clone() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return NAME_HEADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toXML() {
|
||||
XmlStringBuilder sb = new XmlStringBuilder(this);
|
||||
sb.attribute(ATTR_SID, getSid()).rightAngleBracket();
|
||||
|
||||
for (OmemoKeyElement k : getKeys()) {
|
||||
sb.element(k);
|
||||
}
|
||||
|
||||
sb.openElement(ATTR_IV).append(Base64.encodeToString(getIv())).closeElement(ATTR_IV);
|
||||
|
||||
return sb.closeElement(this);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
*
|
||||
* 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.element;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class OmemoHeaderElement_VAxolotl extends OmemoHeaderElement {
|
||||
|
||||
public OmemoHeaderElement_VAxolotl(int sid, ArrayList<OmemoKeyElement> keys, byte[] iv) {
|
||||
super(sid, keys, iv);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package org.jivesoftware.smackx.omemo.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.NamedElement;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
/**
|
||||
* Small class to collect key (byte[]), its id and whether its a preKey or not.
|
||||
*/
|
||||
public class OmemoKeyElement implements NamedElement {
|
||||
|
||||
public static final String NAME_KEY = "key";
|
||||
public static final String ATTR_RID = "rid";
|
||||
public static final String ATTR_PREKEY = "prekey";
|
||||
|
||||
private final byte[] data;
|
||||
private final int id;
|
||||
private final boolean preKey;
|
||||
|
||||
public OmemoKeyElement(byte[] data, int id) {
|
||||
this.data = data;
|
||||
this.id = id;
|
||||
this.preKey = false;
|
||||
}
|
||||
|
||||
public OmemoKeyElement(byte[] data, int id, boolean preKey) {
|
||||
this.data = data;
|
||||
this.id = id;
|
||||
this.preKey = preKey;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public boolean isPreKey() {
|
||||
return this.preKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Integer.toString(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return NAME_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toXML() {
|
||||
XmlStringBuilder sb = new XmlStringBuilder(this);
|
||||
|
||||
if (isPreKey()) {
|
||||
sb.attribute(ATTR_PREKEY, true);
|
||||
}
|
||||
|
||||
sb.attribute(ATTR_RID, getId());
|
||||
sb.rightAngleBracket();
|
||||
sb.append(Base64.encodeToString(getData()));
|
||||
sb.closeElement(this);
|
||||
return sb;
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* 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.element;
|
||||
|
||||
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
/**
|
||||
* An OMEMO (PreKey)WhisperMessage element.
|
||||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
public class OmemoVAxolotlElement extends OmemoElement {
|
||||
|
||||
/**
|
||||
* Create a new OmemoMessageElement from a header and a payload.
|
||||
*
|
||||
* @param header header of the message
|
||||
* @param payload payload
|
||||
*/
|
||||
public OmemoVAxolotlElement(OmemoHeader header, byte[] payload) {
|
||||
super(header, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return ENCRYPTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML(String enclosingNamespace) {
|
||||
XmlStringBuilder sb = new XmlStringBuilder(this).rightAngleBracket();
|
||||
|
||||
sb.element(header);
|
||||
|
||||
if (payload != null) {
|
||||
sb.openElement(PAYLOAD).append(Base64.encodeToString(payload)).closeElement(PAYLOAD);
|
||||
}
|
||||
|
||||
sb.closeElement(this);
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return OMEMO_NAMESPACE_V_AXOLOTL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
StringBuilder s = new StringBuilder("Encrypted:\n")
|
||||
.append(" header: sid: ").append(getHeader().getSid()).append('\n');
|
||||
for (OmemoHeader.Key k : getHeader().getKeys()) {
|
||||
s.append(" key: prekey: ").append(k.isPreKey()).append(" rid: ")
|
||||
.append(k.getId()).append(' ')
|
||||
.append(new String(k.getData(), StringUtils.UTF8)).append('\n');
|
||||
}
|
||||
s.append(" iv: ").append(new String(getHeader().getIv(), StringUtils.UTF8)).append('\n');
|
||||
s.append(" payload: ").append(new String(getPayload(), StringUtils.UTF8));
|
||||
return s.toString();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// UTF-8 must be supported on all platforms claiming to be java compatible.
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,6 +35,10 @@ public class CannotEstablishOmemoSessionException extends Exception {
|
|||
private final HashMap<BareJid, HashMap<OmemoDevice, Throwable>> failures = new HashMap<>();
|
||||
private final HashMap<BareJid, ArrayList<OmemoDevice>> successes = new HashMap<>();
|
||||
|
||||
public CannotEstablishOmemoSessionException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CannotEstablishOmemoSessionException(OmemoDevice failed, Throwable reason) {
|
||||
super();
|
||||
getFailsOfContact(failed.getJid()).put(failed, reason);
|
||||
|
|
|
@ -100,12 +100,13 @@ public class CachedDeviceList implements Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a device to the list of active devices.
|
||||
* Add a device to the list of active devices and remove it from inactive.
|
||||
*
|
||||
* @param deviceId deviceId that will be added
|
||||
*/
|
||||
public void addDevice(int deviceId) {
|
||||
activeDevices.add(deviceId);
|
||||
inactiveDevices.remove(deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,6 +119,10 @@ public class CachedDeviceList implements Serializable {
|
|||
return activeDevices.contains(deviceId) || inactiveDevices.contains(deviceId);
|
||||
}
|
||||
|
||||
public boolean isActive(int deviceId) {
|
||||
return getActiveDevices().contains(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String out = "active: [";
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.HashMap;
|
|||
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleElement_VAxolotl;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
|
@ -40,9 +40,9 @@ import org.xmlpull.v1.XmlPullParser;
|
|||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
public class OmemoBundleVAxolotlProvider extends ExtensionElementProvider<OmemoBundleVAxolotlElement> {
|
||||
public class OmemoBundleVAxolotlProvider extends ExtensionElementProvider<OmemoBundleElement_VAxolotl> {
|
||||
@Override
|
||||
public OmemoBundleVAxolotlElement parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
public OmemoBundleElement_VAxolotl parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
boolean stop = false;
|
||||
boolean inPreKeys = false;
|
||||
|
||||
|
@ -96,6 +96,6 @@ public class OmemoBundleVAxolotlProvider extends ExtensionElementProvider<OmemoB
|
|||
break;
|
||||
}
|
||||
}
|
||||
return new OmemoBundleVAxolotlElement(signedPreKeyId, signedPreKey, signedPreKeySignature, identityKey, preKeys);
|
||||
return new OmemoBundleElement_VAxolotl(signedPreKeyId, signedPreKey, signedPreKeySignature, identityKey, preKeys);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.Set;
|
|||
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement_VAxolotl;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
|
@ -36,10 +36,10 @@ import org.xmlpull.v1.XmlPullParser;
|
|||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
public class OmemoDeviceListVAxolotlProvider extends ExtensionElementProvider<OmemoDeviceListVAxolotlElement> {
|
||||
public class OmemoDeviceListVAxolotlProvider extends ExtensionElementProvider<OmemoDeviceListElement_VAxolotl> {
|
||||
|
||||
@Override
|
||||
public OmemoDeviceListVAxolotlElement parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
public OmemoDeviceListElement_VAxolotl parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
Set<Integer> deviceListIds = new HashSet<>();
|
||||
boolean stop = false;
|
||||
while (!stop) {
|
||||
|
@ -63,6 +63,6 @@ public class OmemoDeviceListVAxolotlProvider extends ExtensionElementProvider<Om
|
|||
break;
|
||||
}
|
||||
}
|
||||
return new OmemoDeviceListVAxolotlElement(deviceListIds);
|
||||
return new OmemoDeviceListElement_VAxolotl(deviceListIds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,8 @@
|
|||
*/
|
||||
package org.jivesoftware.smackx.omemo.provider;
|
||||
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.ENCRYPTED;
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.HEADER;
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.IV;
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.KEY;
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.PAYLOAD;
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.PREKEY;
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.RID;
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.SID;
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.ATTR_PAYLOAD;
|
||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.NAME_ENCRYPTED;
|
||||
import static org.xmlpull.v1.XmlPullParser.END_TAG;
|
||||
import static org.xmlpull.v1.XmlPullParser.START_TAG;
|
||||
|
||||
|
@ -31,8 +25,10 @@ import java.util.ArrayList;
|
|||
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoHeaderElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoHeaderElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoKeyElement;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
|
@ -41,13 +37,13 @@ import org.xmlpull.v1.XmlPullParser;
|
|||
*
|
||||
* @author Paul Schaub
|
||||
*/
|
||||
public class OmemoVAxolotlProvider extends ExtensionElementProvider<OmemoVAxolotlElement> {
|
||||
public class OmemoVAxolotlProvider extends ExtensionElementProvider<OmemoElement_VAxolotl> {
|
||||
|
||||
@Override
|
||||
public OmemoVAxolotlElement parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
public OmemoElement_VAxolotl parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
boolean inEncrypted = true;
|
||||
int sid = -1;
|
||||
ArrayList<OmemoVAxolotlElement.OmemoHeader.Key> keys = new ArrayList<>();
|
||||
ArrayList<OmemoKeyElement> keys = new ArrayList<>();
|
||||
byte[] iv = null;
|
||||
byte[] payload = null;
|
||||
|
||||
|
@ -57,41 +53,41 @@ public class OmemoVAxolotlProvider extends ExtensionElementProvider<OmemoVAxolot
|
|||
switch (tag) {
|
||||
case START_TAG:
|
||||
switch (name) {
|
||||
case HEADER:
|
||||
case OmemoHeaderElement.NAME_HEADER:
|
||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
||||
if (parser.getAttributeName(i).equals(SID)) {
|
||||
if (parser.getAttributeName(i).equals(OmemoHeaderElement.ATTR_SID)) {
|
||||
sid = Integer.parseInt(parser.getAttributeValue(i));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KEY:
|
||||
case OmemoKeyElement.NAME_KEY:
|
||||
boolean prekey = false;
|
||||
int rid = -1;
|
||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
||||
if (parser.getAttributeName(i).equals(PREKEY)) {
|
||||
if (parser.getAttributeName(i).equals(OmemoKeyElement.ATTR_PREKEY)) {
|
||||
prekey = Boolean.parseBoolean(parser.getAttributeValue(i));
|
||||
} else if (parser.getAttributeName(i).equals(RID)) {
|
||||
} else if (parser.getAttributeName(i).equals(OmemoKeyElement.ATTR_RID)) {
|
||||
rid = Integer.parseInt(parser.getAttributeValue(i));
|
||||
}
|
||||
}
|
||||
keys.add(new OmemoVAxolotlElement.OmemoHeader.Key(Base64.decode(parser.nextText()), rid, prekey));
|
||||
keys.add(new OmemoKeyElement(Base64.decode(parser.nextText()), rid, prekey));
|
||||
break;
|
||||
case IV:
|
||||
case OmemoHeaderElement.ATTR_IV:
|
||||
iv = Base64.decode(parser.nextText());
|
||||
break;
|
||||
case PAYLOAD:
|
||||
case ATTR_PAYLOAD:
|
||||
payload = Base64.decode(parser.nextText());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case END_TAG:
|
||||
if (name.equals(ENCRYPTED)) {
|
||||
if (name.equals(NAME_ENCRYPTED)) {
|
||||
inEncrypted = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
OmemoVAxolotlElement.OmemoHeader header = new OmemoVAxolotlElement.OmemoHeader(sid, keys, iv);
|
||||
return new OmemoVAxolotlElement(header, payload);
|
||||
OmemoHeaderElement_VAxolotl header = new OmemoHeaderElement_VAxolotl(sid, keys, iv);
|
||||
return new OmemoElement_VAxolotl(header, payload);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public final class OmemoConstants {
|
|||
/**
|
||||
* How many preKeys do we want to publish?
|
||||
*/
|
||||
public static final int TARGET_PRE_KEY_COUNT = 100;
|
||||
public static final int PRE_KEY_COUNT_PER_BUNDLE = 100;
|
||||
|
||||
/**
|
||||
* Return the node name of the PEP node containing the device bundle of the device with device id deviceId.
|
||||
|
@ -49,7 +49,7 @@ public final class OmemoConstants {
|
|||
return PEP_NODE_BUNDLES + ":" + deviceId;
|
||||
}
|
||||
|
||||
public static final String BODY_OMEMO_HINT = "I sent you an OMEMO encrypted message but your client doesn’t seem to support that. Find more information on https://conversations.im/omemo";
|
||||
public static final String BODY_OMEMO_HINT = "I sent you an OMEMO encrypted message but your client doesn't seem to support that. Find more information on https://conversations.im/omemo";
|
||||
|
||||
/**
|
||||
* Information about the keys used for message encryption.
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.util.TreeMap;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleElement;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
|
||||
import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;
|
||||
|
@ -59,7 +59,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @return identityKey
|
||||
* @throws CorruptedOmemoKeyException if the key is damaged/malformed
|
||||
*/
|
||||
public T_IdKey identityKey(OmemoBundleVAxolotlElement bundle) throws CorruptedOmemoKeyException {
|
||||
public T_IdKey identityKey(OmemoBundleElement bundle) throws CorruptedOmemoKeyException {
|
||||
return identityKeyFromBytes(bundle.getIdentityKey());
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @return singedPreKey
|
||||
* @throws CorruptedOmemoKeyException if the key is damaged/malformed
|
||||
*/
|
||||
public T_ECPub signedPreKeyPublic(OmemoBundleVAxolotlElement bundle) throws CorruptedOmemoKeyException {
|
||||
public T_ECPub signedPreKeyPublic(OmemoBundleElement bundle) throws CorruptedOmemoKeyException {
|
||||
return signedPreKeyPublicFromBytes(bundle.getSignedPreKey());
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @param bundle OmemoBundleElement
|
||||
* @return signedPreKeyId
|
||||
*/
|
||||
public int signedPreKeyId(OmemoBundleVAxolotlElement bundle) {
|
||||
public int signedPreKeyId(OmemoBundleElement bundle) {
|
||||
return bundle.getSignedPreKeyId();
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @param bundle OmemoBundleElement
|
||||
* @return signature
|
||||
*/
|
||||
public byte[] signedPreKeySignature(OmemoBundleVAxolotlElement bundle) {
|
||||
public byte[] signedPreKeySignature(OmemoBundleElement bundle) {
|
||||
return bundle.getSignedPreKeySignature();
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @return the preKey
|
||||
* @throws CorruptedOmemoKeyException when the key cannot be parsed from bytes
|
||||
*/
|
||||
public T_ECPub preKeyPublic(OmemoBundleVAxolotlElement bundle, int keyId) throws CorruptedOmemoKeyException {
|
||||
public T_ECPub preKeyPublic(OmemoBundleElement bundle, int keyId) throws CorruptedOmemoKeyException {
|
||||
return preKeyPublicFromBytes(bundle.getPreKey(keyId));
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @return a HashMap with one T_Bundle per preKey and the preKeyId as key
|
||||
* @throws CorruptedOmemoKeyException when one of the keys cannot be parsed
|
||||
*/
|
||||
public HashMap<Integer, T_Bundle> bundles(OmemoBundleVAxolotlElement bundle, OmemoDevice contact) throws CorruptedOmemoKeyException {
|
||||
public HashMap<Integer, T_Bundle> bundles(OmemoBundleElement bundle, OmemoDevice contact) throws CorruptedOmemoKeyException {
|
||||
HashMap<Integer, T_Bundle> bundles = new HashMap<>();
|
||||
for (int deviceId : bundle.getPreKeys().keySet()) {
|
||||
try {
|
||||
|
@ -255,7 +255,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
|||
* @return PreKeyBundle (T_PreKey)
|
||||
* @throws CorruptedOmemoKeyException if some key is damaged or malformed
|
||||
*/
|
||||
public abstract T_Bundle bundleFromOmemoBundle(OmemoBundleVAxolotlElement bundle, OmemoDevice contact, int keyId) throws CorruptedOmemoKeyException;
|
||||
public abstract T_Bundle bundleFromOmemoBundle(OmemoBundleElement bundle, OmemoDevice contact, int keyId) throws CorruptedOmemoKeyException;
|
||||
|
||||
/**
|
||||
* Extract the signature from a signedPreKey.
|
||||
|
|
|
@ -41,7 +41,10 @@ import org.jivesoftware.smack.SmackException;
|
|||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smackx.omemo.OmemoManager;
|
||||
import org.jivesoftware.smackx.omemo.OmemoRatchet;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoHeaderElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoKeyElement;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
||||
|
@ -73,7 +76,7 @@ public class OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
|||
private byte[] initializationVector = generateIv();
|
||||
|
||||
private byte[] ciphertextMessage;
|
||||
private final ArrayList<OmemoVAxolotlElement.OmemoHeader.Key> keys = new ArrayList<>();
|
||||
private final ArrayList<OmemoKeyElement> keys = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Create a OmemoMessageBuilder.
|
||||
|
@ -211,7 +214,7 @@ public class OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
|||
if (ignoreTrust || managerGuard.get().isTrustedOmemoIdentity(contactsDevice, fingerprint)) {
|
||||
// Encrypt key and save to header
|
||||
CiphertextTuple encryptedKey = ratchet.doubleRatchetEncrypt(contactsDevice, messageKey);
|
||||
keys.add(new OmemoVAxolotlElement.OmemoHeader.Key(encryptedKey.getCiphertext(), contactsDevice.getDeviceId(), encryptedKey.isPreKeyMessage()));
|
||||
keys.add(new OmemoKeyElement(encryptedKey.getCiphertext(), contactsDevice.getDeviceId(), encryptedKey.isPreKeyMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,13 +223,13 @@ public class OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
|||
*
|
||||
* @return OmemoMessageElement
|
||||
*/
|
||||
public OmemoVAxolotlElement finish() {
|
||||
OmemoVAxolotlElement.OmemoHeader header = new OmemoVAxolotlElement.OmemoHeader(
|
||||
public OmemoElement finish() {
|
||||
OmemoHeaderElement_VAxolotl header = new OmemoHeaderElement_VAxolotl(
|
||||
managerGuard.get().getDeviceId(),
|
||||
keys,
|
||||
initializationVector
|
||||
);
|
||||
return new OmemoVAxolotlElement(header, ciphertextMessage);
|
||||
return new OmemoElement_VAxolotl(header, ciphertextMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.jivesoftware.smack.test.util.TestUtils;
|
|||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.provider.OmemoBundleVAxolotlProvider;
|
||||
|
||||
import org.junit.Test;
|
||||
|
@ -50,7 +50,7 @@ public class OmemoBundleVAxolotlElementTest extends SmackTestSuite {
|
|||
preKeysB64.put(preKeyId1, preKey1B64);
|
||||
preKeysB64.put(preKeyId2, preKey2B64);
|
||||
|
||||
OmemoBundleVAxolotlElement bundle = new OmemoBundleVAxolotlElement(signedPreKeyId,
|
||||
OmemoBundleElement_VAxolotl bundle = new OmemoBundleElement_VAxolotl(signedPreKeyId,
|
||||
signedPreKeyB64, signedPreKeySigB64, identityKeyB64, preKeysB64);
|
||||
|
||||
assertEquals("ElementName must match.", "bundle", bundle.getElementName());
|
||||
|
@ -85,7 +85,7 @@ public class OmemoBundleVAxolotlElementTest extends SmackTestSuite {
|
|||
byte[] firstPreKey = "FirstPreKey".getBytes(StringUtils.UTF8);
|
||||
byte[] secondPreKey = "SecondPreKey".getBytes(StringUtils.UTF8);
|
||||
|
||||
OmemoBundleVAxolotlElement parsed = new OmemoBundleVAxolotlProvider().parse(TestUtils.getParser(actual));
|
||||
OmemoBundleElement_VAxolotl parsed = new OmemoBundleVAxolotlProvider().parse(TestUtils.getParser(actual));
|
||||
|
||||
assertTrue("B64-decoded signedPreKey must match.", Arrays.equals(signedPreKey, parsed.getSignedPreKey()));
|
||||
assertEquals("SignedPreKeyId must match", signedPreKeyId, parsed.getSignedPreKeyId());
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.HashSet;
|
|||
import org.jivesoftware.smack.test.util.SmackTestSuite;
|
||||
import org.jivesoftware.smack.test.util.TestUtils;
|
||||
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.provider.OmemoDeviceListVAxolotlProvider;
|
||||
|
||||
import org.junit.Test;
|
||||
|
@ -41,11 +41,11 @@ public class OmemoDeviceListVAxolotlElementTest extends SmackTestSuite {
|
|||
ids.add(1234);
|
||||
ids.add(9876);
|
||||
|
||||
OmemoDeviceListVAxolotlElement element = new OmemoDeviceListVAxolotlElement(ids);
|
||||
OmemoDeviceListElement_VAxolotl element = new OmemoDeviceListElement_VAxolotl(ids);
|
||||
String xml = element.toXML(null).toString();
|
||||
|
||||
XmlPullParser parser = TestUtils.getParser(xml);
|
||||
OmemoDeviceListVAxolotlElement parsed = new OmemoDeviceListVAxolotlProvider().parse(parser);
|
||||
OmemoDeviceListElement_VAxolotl parsed = new OmemoDeviceListVAxolotlProvider().parse(parser);
|
||||
|
||||
assertTrue("Parsed element must equal the original.", parsed.getDeviceIds().equals(element.getDeviceIds()));
|
||||
assertEquals("Generated XML must match.",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -24,9 +24,9 @@ import org.jivesoftware.smack.test.util.SmackTestSuite;
|
|||
import org.jivesoftware.smack.test.util.TestUtils;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoVAxolotlElement;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoHeaderElement_VAxolotl;
|
||||
import org.jivesoftware.smackx.omemo.element.OmemoKeyElement;
|
||||
import org.jivesoftware.smackx.omemo.provider.OmemoVAxolotlProvider;
|
||||
import org.jivesoftware.smackx.omemo.util.OmemoMessageBuilder;
|
||||
|
||||
|
@ -47,12 +47,12 @@ public class OmemoVAxolotlElementTest extends SmackTestSuite {
|
|||
int sid = 12131415;
|
||||
byte[] iv = OmemoMessageBuilder.generateIv();
|
||||
|
||||
ArrayList<OmemoElement.OmemoHeader.Key> keys = new ArrayList<>();
|
||||
keys.add(new OmemoElement.OmemoHeader.Key(keyData1, keyId1));
|
||||
keys.add(new OmemoElement.OmemoHeader.Key(keyData2, keyId2, true));
|
||||
ArrayList<OmemoKeyElement> keys = new ArrayList<>();
|
||||
keys.add(new OmemoKeyElement(keyData1, keyId1));
|
||||
keys.add(new OmemoKeyElement(keyData2, keyId2, true));
|
||||
|
||||
OmemoVAxolotlElement.OmemoHeader header = new OmemoElement.OmemoHeader(sid, keys, iv);
|
||||
OmemoVAxolotlElement element = new OmemoVAxolotlElement(header, payload);
|
||||
OmemoHeaderElement_VAxolotl header = new OmemoHeaderElement_VAxolotl(sid, keys, iv);
|
||||
OmemoElement_VAxolotl element = new OmemoElement_VAxolotl(header, payload);
|
||||
|
||||
String expected =
|
||||
"<encrypted xmlns='eu.siacs.conversations.axolotl'>" +
|
||||
|
@ -69,7 +69,9 @@ public class OmemoVAxolotlElementTest extends SmackTestSuite {
|
|||
String actual = element.toXML(null).toString();
|
||||
assertEquals("Serialized xml of OmemoElement must match.", expected, actual);
|
||||
|
||||
OmemoVAxolotlElement parsed = new OmemoVAxolotlProvider().parse(TestUtils.getParser(actual));
|
||||
assertEquals("Parsed OmemoElement must equal the original.", element.toXML(null).toString(), parsed.toXML(null).toString());
|
||||
OmemoElement_VAxolotl parsed = new OmemoVAxolotlProvider().parse(TestUtils.getParser(actual));
|
||||
assertEquals("Parsed OmemoElement must equal the original.",
|
||||
element.toXML(null).toString(),
|
||||
parsed.toXML(null).toString());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue