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.List;
|
||||||
import java.util.TreeMap;
|
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.exceptions.CorruptedOmemoKeyException;
|
||||||
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
|
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
|
||||||
import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;
|
import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;
|
||||||
|
@ -141,7 +141,7 @@ public class SignalOmemoKeyUtil extends OmemoKeyUtil<IdentityKeyPair, IdentityKe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PreKeyBundle bundleFromOmemoBundle(OmemoBundleVAxolotlElement bundle, OmemoDevice contact, int preKeyId)
|
public PreKeyBundle bundleFromOmemoBundle(OmemoBundleElement bundle, OmemoDevice contact, int preKeyId)
|
||||||
throws CorruptedOmemoKeyException
|
throws CorruptedOmemoKeyException
|
||||||
{
|
{
|
||||||
return new PreKeyBundle(0,
|
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.MultiUserChat;
|
||||||
import org.jivesoftware.smackx.muc.MultiUserChatManager;
|
import org.jivesoftware.smackx.muc.MultiUserChatManager;
|
||||||
import org.jivesoftware.smackx.muc.RoomInfo;
|
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.OmemoElement;
|
||||||
import org.jivesoftware.smackx.omemo.element.OmemoVAxolotlElement;
|
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
|
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
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.
|
* 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
|
* If there was an OmemoManager for the connection and id before, return it. Otherwise create a new OmemoManager
|
||||||
* instance and return it.
|
* instance and return it.
|
||||||
|
*
|
||||||
* @param connection XmppConnection.
|
* @param connection XmppConnection.
|
||||||
* @param deviceId MUST NOT be null and MUST be greater than 0.
|
* @param deviceId MUST NOT be null and MUST be greater than 0.
|
||||||
* @return
|
*
|
||||||
|
* @return manager
|
||||||
*/
|
*/
|
||||||
public synchronized static OmemoManager getInstanceFor(XMPPConnection connection, Integer deviceId) {
|
public synchronized static OmemoManager getInstanceFor(XMPPConnection connection, Integer deviceId) {
|
||||||
if (deviceId == null || deviceId < 1) {
|
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
|
* Returns an OmemoManager instance for the given connection. If there was one manager for the connection before,
|
||||||
* before, create a new one. If there was one before, return it. If there were multiple managers before, return the
|
* return it. If there were multiple managers before, return the one with the lowest deviceId.
|
||||||
* 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.
|
* @param connection XmppConnection.
|
||||||
|
*
|
||||||
* @return manager
|
* @return manager
|
||||||
*/
|
*/
|
||||||
public synchronized static OmemoManager getInstanceFor(XMPPConnection connection) {
|
public synchronized static OmemoManager getInstanceFor(XMPPConnection connection) {
|
||||||
|
@ -201,7 +206,9 @@ public final class OmemoManager extends Manager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a TrustCallback for this particular OmemoManager.
|
* 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) {
|
public void setTrustCallback(TrustCallback callback) {
|
||||||
if (trustCallback != null) {
|
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
|
* 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.
|
* 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) {
|
public void initializeAsync(final FinishedCallback finishedCallback) {
|
||||||
Async.go(new Runnable() {
|
Async.go(new Runnable() {
|
||||||
|
@ -257,7 +265,7 @@ public final class OmemoManager extends Manager {
|
||||||
* OMEMO encrypt a cleartext message for a single recipient.
|
* OMEMO encrypt a cleartext message for a single recipient.
|
||||||
* Note that this method does NOT set the 'to' attribute of the message.
|
* 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
|
* @param message text to encrypt
|
||||||
* @return encrypted message
|
* @return encrypted message
|
||||||
* @throws CryptoFailedException when something crypto related fails
|
* @throws CryptoFailedException when something crypto related fails
|
||||||
|
@ -278,7 +286,7 @@ public final class OmemoManager extends Manager {
|
||||||
LoggedInOmemoManager guard = new LoggedInOmemoManager(this);
|
LoggedInOmemoManager guard = new LoggedInOmemoManager(this);
|
||||||
Message plaintext = new Message();
|
Message plaintext = new Message();
|
||||||
plaintext.setBody(message);
|
plaintext.setBody(message);
|
||||||
OmemoVAxolotlElement encrypted = getOmemoService().processSendingMessage(guard, to, plaintext);
|
OmemoElement encrypted = getOmemoService().processSendingMessage(guard, to, plaintext);
|
||||||
return finishMessage(encrypted);
|
return finishMessage(encrypted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,7 +314,7 @@ public final class OmemoManager extends Manager {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
Message m = new Message();
|
Message m = new Message();
|
||||||
m.setBody(message);
|
m.setBody(message);
|
||||||
OmemoVAxolotlElement encrypted = getOmemoService().processSendingMessage(
|
OmemoElement encrypted = getOmemoService().processSendingMessage(
|
||||||
new LoggedInOmemoManager(this), recipients, m);
|
new LoggedInOmemoManager(this), recipients, m);
|
||||||
return finishMessage(encrypted);
|
return finishMessage(encrypted);
|
||||||
}
|
}
|
||||||
|
@ -368,7 +376,7 @@ public final class OmemoManager extends Manager {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
Message m = new Message();
|
Message m = new Message();
|
||||||
m.setBody(message);
|
m.setBody(message);
|
||||||
OmemoVAxolotlElement encrypted = getOmemoService()
|
OmemoElement encrypted = getOmemoService()
|
||||||
.encryptOmemoMessage(new LoggedInOmemoManager(this), exception.getSuccesses(), m);
|
.encryptOmemoMessage(new LoggedInOmemoManager(this), exception.getSuccesses(), m);
|
||||||
return finishMessage(encrypted);
|
return finishMessage(encrypted);
|
||||||
}
|
}
|
||||||
|
@ -482,43 +490,6 @@ public final class OmemoManager extends Manager {
|
||||||
return trustCallback.getTrust(device, fingerprint) != TrustState.undecided;
|
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
|
* Send a ratchet update message. This can be used to advance the ratchet of a session in order to maintain forward
|
||||||
* secrecy.
|
* secrecy.
|
||||||
|
@ -552,7 +523,7 @@ public final class OmemoManager extends Manager {
|
||||||
* @throws CryptoFailedException When something fails with the crypto
|
* @throws CryptoFailedException When something fails with the crypto
|
||||||
* @throws CannotEstablishOmemoSessionException When we can't establish a session with the recipient
|
* @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,
|
throws UndecidedOmemoIdentityException, CorruptedOmemoKeyException, CryptoFailedException,
|
||||||
CannotEstablishOmemoSessionException, SmackException.NotLoggedInException
|
CannotEstablishOmemoSessionException, SmackException.NotLoggedInException
|
||||||
{
|
{
|
||||||
|
@ -571,7 +542,7 @@ public final class OmemoManager extends Manager {
|
||||||
* @param encrypted OmemoMessageElement
|
* @param encrypted OmemoMessageElement
|
||||||
* @return Message containing the OMEMO element and some additional information
|
* @return Message containing the OMEMO element and some additional information
|
||||||
*/
|
*/
|
||||||
Message finishMessage(OmemoVAxolotlElement encrypted) {
|
Message finishMessage(OmemoElement encrypted) {
|
||||||
if (encrypted == null) {
|
if (encrypted == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -794,8 +765,7 @@ public final class OmemoManager extends Manager {
|
||||||
// generate key
|
// generate key
|
||||||
getOmemoService().getOmemoStoreBackend().changeSignedPreKey(getOwnDevice());
|
getOmemoService().getOmemoStoreBackend().changeSignedPreKey(getOwnDevice());
|
||||||
// publish
|
// publish
|
||||||
getOmemoService().publishDeviceIdIfNeeded(managerGuard, false);
|
getOmemoService().publish(managerGuard);
|
||||||
getOmemoService().publishBundle(managerGuard);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -805,7 +775,7 @@ public final class OmemoManager extends Manager {
|
||||||
* @return true if stanza has extension 'encrypted'
|
* @return true if stanza has extension 'encrypted'
|
||||||
*/
|
*/
|
||||||
public static boolean stanzaContainsOmemoElement(Stanza stanza) {
|
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;
|
PayloadItem<?> payloadItem = (PayloadItem<?>) item;
|
||||||
|
|
||||||
if (!(payloadItem.getPayload() instanceof OmemoDeviceListVAxolotlElement)) {
|
if (!(payloadItem.getPayload() instanceof OmemoDeviceListElement_VAxolotl)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Device List <list>
|
// Device List <list>
|
||||||
OmemoDeviceListVAxolotlElement omemoDeviceListElement =
|
OmemoDeviceListElement_VAxolotl omemoDeviceListElement =
|
||||||
(OmemoDeviceListVAxolotlElement) payloadItem.getPayload();
|
(OmemoDeviceListElement_VAxolotl) payloadItem.getPayload();
|
||||||
Integer ourDeviceId = getDeviceId();
|
Integer ourDeviceId = getDeviceId();
|
||||||
|
|
||||||
getOmemoService().getOmemoStoreBackend()
|
getOmemoService().getOmemoStoreBackend()
|
||||||
|
@ -1047,8 +1017,8 @@ public final class OmemoManager extends Manager {
|
||||||
|
|
||||||
// enroll at the deviceList
|
// enroll at the deviceList
|
||||||
deviceListIds.add(ourDeviceId);
|
deviceListIds.add(ourDeviceId);
|
||||||
final OmemoDeviceListVAxolotlElement newOmemoDeviceListElement =
|
final OmemoDeviceListElement_VAxolotl newOmemoDeviceListElement =
|
||||||
new OmemoDeviceListVAxolotlElement(deviceListIds);
|
new OmemoDeviceListElement_VAxolotl(deviceListIds);
|
||||||
|
|
||||||
// PEPListener is a synchronous listener.
|
// PEPListener is a synchronous listener.
|
||||||
// Avoid any deadlocks by using an async task to update the device list.
|
// 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.packet.Message;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smackx.omemo.element.OmemoElement;
|
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.CorruptedOmemoKeyException;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.MultipleCryptoFailedException;
|
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();
|
int keyId = omemoManager.getDeviceId();
|
||||||
byte[] unpackedKey = null;
|
byte[] unpackedKey = null;
|
||||||
List<CryptoFailedException> decryptExceptions = new ArrayList<>();
|
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.
|
// Find key with our ID.
|
||||||
for (OmemoElement.OmemoHeader.Key k : keys) {
|
for (OmemoKeyElement k : keys) {
|
||||||
if (k.getId() == keyId) {
|
if (k.getId() == keyId) {
|
||||||
try {
|
try {
|
||||||
unpackedKey = doubleRatchetDecrypt(sender, k.getData());
|
unpackedKey = doubleRatchetDecrypt(sender, k.getData());
|
||||||
|
|
|
@ -30,7 +30,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.MultiUserChat;
|
||||||
import org.jivesoftware.smackx.muc.MultiUserChatManager;
|
import org.jivesoftware.smackx.muc.MultiUserChatManager;
|
||||||
import org.jivesoftware.smackx.omemo.element.OmemoBundleElement;
|
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.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.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.CannotEstablishOmemoSessionException;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
||||||
|
@ -206,6 +204,10 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
checkAvailableAlgorithms();
|
checkAvailableAlgorithms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the OmemoManager known to the OmemoService.
|
||||||
|
* @param manager manager.
|
||||||
|
*/
|
||||||
void registerManager(OmemoManager manager) {
|
void registerManager(OmemoManager manager) {
|
||||||
omemoRatchets.put(manager, instantiateOmemoRatchet(manager, getOmemoStoreBackend()));
|
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 XMPPException.XMPPErrorException
|
||||||
* @throws SmackException.NotConnectedException
|
* @throws SmackException.NotConnectedException
|
||||||
* @throws SmackException.NoResponseException
|
* @throws SmackException.NoResponseException
|
||||||
* @throws SmackException.NotLoggedInException
|
|
||||||
* @throws PubSubException.NotALeafNodeException
|
* @throws PubSubException.NotALeafNodeException
|
||||||
*/
|
*/
|
||||||
void publish(OmemoManager.LoggedInOmemoManager managerGuard)
|
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,
|
SmackException.NotConnectedException, SmackException.NoResponseException,
|
||||||
PubSubException.NotALeafNodeException
|
PubSubException.NotALeafNodeException
|
||||||
{
|
{
|
||||||
|
OmemoManager manager = managerGuard.get();
|
||||||
|
OmemoDevice userDevice = manager.getOwnDevice();
|
||||||
|
|
||||||
// Create new keys if necessary and publish to the server.
|
// Create new keys if necessary and publish to the server.
|
||||||
publishBundle(managerGuard);
|
publishBundle(managerGuard);
|
||||||
|
|
||||||
// Get fresh device list from server
|
// Get fresh device list from server
|
||||||
refreshOwnDeviceList(managerGuard);
|
CachedDeviceList list = refreshOwnDeviceList(managerGuard);
|
||||||
publishDeviceIdIfNeeded(managerGuard, false);
|
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, "");
|
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.
|
* 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));
|
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.
|
* Remove stale devices from our device list.
|
||||||
* This does only delete devices, if that's configured in OmemoConfiguration.
|
* This does only delete devices, if that's configured in OmemoConfiguration.
|
||||||
|
@ -432,11 +350,11 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
*omemoManager.getOwnJid()
|
*omemoManager.getOwnJid()
|
||||||
* @param managerGuard OmemoManager
|
* @param managerGuard OmemoManager
|
||||||
* @param deviceList list of deviceIDs
|
* @param deviceList list of deviceIDs
|
||||||
* @throws InterruptedException Exception
|
* @throws InterruptedException Exception
|
||||||
* @throws XMPPException.XMPPErrorException Exception
|
* @throws XMPPException.XMPPErrorException Exception
|
||||||
* @throws SmackException.NotConnectedException Exception
|
* @throws SmackException.NotConnectedException Exception
|
||||||
* @throws SmackException.NoResponseException Exception
|
* @throws SmackException.NoResponseException Exception
|
||||||
* @throws PubSubException.NotALeafNodeException Exception
|
* @throws PubSubException.NotALeafNodeException Exception
|
||||||
*/
|
*/
|
||||||
static void publishDeviceIds(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDeviceListElement deviceList)
|
static void publishDeviceIds(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDeviceListElement deviceList)
|
||||||
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
|
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
|
||||||
|
@ -482,39 +400,17 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @throws NotAPubSubNodeException
|
* @throws NotAPubSubNodeException
|
||||||
*/
|
*/
|
||||||
static OmemoDeviceListElement fetchDeviceList(OmemoManager.LoggedInOmemoManager managerGuard, BareJid contact)
|
static OmemoDeviceListElement fetchDeviceList(OmemoManager.LoggedInOmemoManager managerGuard, BareJid contact)
|
||||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
throws InterruptedException, SmackException.NotConnectedException, SmackException.NoResponseException,
|
||||||
SmackException.NoResponseException, PubSubException.NotALeafNodeException, NotAPubSubNodeException
|
XMPPException.XMPPErrorException {
|
||||||
{
|
|
||||||
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 {
|
try {
|
||||||
getOmemoStoreBackend().mergeCachedDeviceList(userDevice, userDevice.getJid(),
|
return extractDeviceListFrom(fetchDeviceListNode(managerGuard, contact));
|
||||||
fetchDeviceList(managerGuard, omemoManager.getOwnJid()));
|
}
|
||||||
|
|
||||||
} catch (XMPPException.XMPPErrorException e) {
|
catch (XMPPException.XMPPErrorException e) {
|
||||||
|
|
||||||
if (e.getXMPPError().getCondition() == StanzaError.Condition.item_not_found) {
|
if (e.getXMPPError().getCondition() == StanzaError.Condition.item_not_found) {
|
||||||
LOGGER.log(Level.WARNING, "Could not refresh own deviceList, because the node did not exist: "
|
LOGGER.log(Level.WARNING, "Could not refresh own deviceList, because the node did not exist: "
|
||||||
+ e.getMessage());
|
+ e.getMessage());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -522,15 +418,35 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
} catch (PubSubException.NotALeafNodeException e) {
|
} catch (PubSubException.NotALeafNodeException e) {
|
||||||
LOGGER.log(Level.WARNING, "Could not refresh own deviceList, because the Node is not a LeafNode: " +
|
LOGGER.log(Level.WARNING, "Could not refresh own deviceList, because the Node is not a LeafNode: " +
|
||||||
e.getMessage());
|
e.getMessage());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (PubSubException.NotAPubSubNodeException e) {
|
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.");
|
"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 InterruptedException
|
||||||
* @throws SmackException.NoResponseException
|
* @throws SmackException.NoResponseException
|
||||||
*/
|
*/
|
||||||
void refreshDeviceList(OmemoManager.LoggedInOmemoManager managerGuard, BareJid contact)
|
CachedDeviceList refreshDeviceList(OmemoManager.LoggedInOmemoManager managerGuard, BareJid contact)
|
||||||
throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException
|
throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException
|
||||||
{
|
{
|
||||||
OmemoDeviceListElement omemoDeviceListElement;
|
OmemoDeviceListElement omemoDeviceListElement = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
omemoDeviceListElement = fetchDeviceList(managerGuard, contact);
|
omemoDeviceListElement = fetchDeviceList(managerGuard, contact);
|
||||||
|
} catch (XMPPException.XMPPErrorException e) {
|
||||||
} catch (PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | NotAPubSubNodeException e) {
|
|
||||||
LOGGER.log(Level.WARNING, "Could not fetch device list of " + contact + ": " + 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,13 +484,13 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @throws PubSubException.NotALeafNodeException when the bundles node is not a LeafNode
|
* @throws PubSubException.NotALeafNodeException when the bundles node is not a LeafNode
|
||||||
* @throws NotAPubSubNodeException
|
* @throws NotAPubSubNodeException
|
||||||
*/
|
*/
|
||||||
static OmemoBundleVAxolotlElement fetchBundle(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contact)
|
static OmemoBundleElement fetchBundle(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contact)
|
||||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||||
SmackException.NoResponseException, PubSubException.NotALeafNodeException, NotAPubSubNodeException
|
SmackException.NoResponseException, PubSubException.NotALeafNodeException, NotAPubSubNodeException
|
||||||
{
|
{
|
||||||
OmemoManager omemoManager = managerGuard.get();
|
OmemoManager omemoManager = managerGuard.get();
|
||||||
LeafNode node = PubSubManager.getInstance(omemoManager.getConnection(), contact.getJid()).getLeafNode(
|
LeafNode node = PubSubManager.getInstance(omemoManager.getConnection(), contact.getJid()).getLeafNode(
|
||||||
PEP_NODE_BUNDLE_FROM_DEVICE_ID(contact.getDeviceId()));
|
PEP_NODE_BUNDLE_FROM_DEVICE_ID(contact.getDeviceId()));
|
||||||
return extractBundleFrom(node);
|
return extractBundleFrom(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,22 +504,26 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @throws InterruptedException goes
|
* @throws InterruptedException goes
|
||||||
* @throws SmackException.NoResponseException wrong
|
* @throws SmackException.NoResponseException wrong
|
||||||
*/
|
*/
|
||||||
private static OmemoBundleVAxolotlElement extractBundleFrom(LeafNode node)
|
private static OmemoBundleElement extractBundleFrom(LeafNode node)
|
||||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||||
SmackException.NoResponseException
|
SmackException.NoResponseException
|
||||||
{
|
{
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
return (OmemoBundleVAxolotlElement) ((PayloadItem<?>) node.getItems().get(0)).getPayload();
|
List<PayloadItem<OmemoBundleElement>> bundleItems = node.getItems();
|
||||||
} catch (IndexOutOfBoundsException e) {
|
if (bundleItems.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bundleItems.get(0).getPayload();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the OmemoDeviceListElement of a contact from a node containing his OmemoDeviceListElement.
|
* 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
|
* @param node typically a LeafNode containing the OmemoDeviceListElement of a contact
|
||||||
* @return the extracted OmemoDeviceListElement.
|
* @return the extracted OmemoDeviceListElement.
|
||||||
|
@ -623,11 +541,10 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<?> items = node.getItems();
|
List<PayloadItem<OmemoDeviceListElement>> items = node.getItems();
|
||||||
if (items.size() > 0) {
|
if (items.size() > 0) {
|
||||||
|
|
||||||
OmemoDeviceListVAxolotlElement listElement =
|
OmemoDeviceListElement listElement = items.get(items.size() - 1).getPayload();
|
||||||
(OmemoDeviceListVAxolotlElement) ((PayloadItem<?>) items.get(items.size() - 1)).getPayload();
|
|
||||||
|
|
||||||
if (items.size() > 1) {
|
if (items.size() > 1) {
|
||||||
node.deleteAllItems();
|
node.deleteAllItems();
|
||||||
|
@ -638,7 +555,42 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<Integer> emptySet = Collections.emptySet();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OmemoBundleVAxolotlElement bundle;
|
OmemoBundleElement bundle;
|
||||||
try {
|
try {
|
||||||
bundle = fetchBundle(managerGuard, contactsDevice);
|
bundle = fetchBundle(managerGuard, contactsDevice);
|
||||||
} catch (SmackException | XMPPException.XMPPErrorException | InterruptedException e) {
|
} 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.
|
* device, return null.
|
||||||
*
|
*
|
||||||
* @param contactsDevice OmemoDevice of the sender of the message
|
* @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
|
* @param information OmemoMessageInformation object which will contain meta data about the decrypted message
|
||||||
* @return decrypted message or null
|
* @return decrypted message or null
|
||||||
* @throws NoRawSessionException
|
* @throws NoRawSessionException
|
||||||
|
@ -771,7 +723,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
*/
|
*/
|
||||||
private Message processReceivingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
private Message processReceivingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||||
OmemoDevice contactsDevice,
|
OmemoDevice contactsDevice,
|
||||||
OmemoElement message,
|
OmemoElement omemoElement,
|
||||||
final OmemoMessageInformation information)
|
final OmemoMessageInformation information)
|
||||||
throws NoRawSessionException, InterruptedException, SmackException.NoResponseException,
|
throws NoRawSessionException, InterruptedException, SmackException.NoResponseException,
|
||||||
SmackException.NotConnectedException, CryptoFailedException, XMPPException.XMPPErrorException,
|
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();
|
OmemoManager omemoManager = managerGuard.get();
|
||||||
OmemoDevice userDevice = omemoManager.getOwnDevice();
|
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?
|
// 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
|
// Only decrypt with our deviceID
|
||||||
if (k.getId() != omemoManager.getDeviceId()) {
|
if (k.getId() != omemoManager.getDeviceId()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message decrypted = decryptOmemoMessageElement(managerGuard, contactsDevice, message, information);
|
Message decrypted = decryptOmemoMessageElement(managerGuard, contactsDevice, omemoElement, information);
|
||||||
if (contactsDevice.equals(omemoManager.getOwnJid()) && decrypted != null) {
|
if (contactsDevice.equals(omemoManager.getOwnJid()) && decrypted != null) {
|
||||||
getOmemoStoreBackend().setDateOfLastReceivedMessage(userDevice, contactsDevice, new Date());
|
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
|
CryptoFailedException, XMPPException.XMPPErrorException, CorruptedOmemoKeyException, NoRawSessionException
|
||||||
{
|
{
|
||||||
if (OmemoManager.stanzaContainsOmemoElement(message)) {
|
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();
|
OmemoMessageInformation info = new OmemoMessageInformation();
|
||||||
Message decrypted = processReceivingMessage(managerGuard,
|
Message decrypted = processReceivingMessage(managerGuard,
|
||||||
new OmemoDevice(sender, omemoMessageElement.getHeader().getSid()),
|
new OmemoDevice(sender, omemoMessageElement.getHeader().getSid()),
|
||||||
|
@ -847,9 +803,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @throws UndecidedOmemoIdentityException
|
* @throws UndecidedOmemoIdentityException
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
OmemoVAxolotlElement processSendingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
OmemoElement processSendingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||||
BareJid recipient,
|
BareJid recipient,
|
||||||
Message message)
|
Message message)
|
||||||
throws CryptoFailedException, UndecidedOmemoIdentityException, NoSuchAlgorithmException,
|
throws CryptoFailedException, UndecidedOmemoIdentityException, NoSuchAlgorithmException,
|
||||||
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
|
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
|
||||||
CannotEstablishOmemoSessionException
|
CannotEstablishOmemoSessionException
|
||||||
|
@ -871,9 +827,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @throws UndecidedOmemoIdentityException
|
* @throws UndecidedOmemoIdentityException
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
OmemoVAxolotlElement processSendingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
OmemoElement processSendingMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||||
ArrayList<BareJid> recipients,
|
ArrayList<BareJid> recipients,
|
||||||
Message message)
|
Message message)
|
||||||
throws CryptoFailedException, UndecidedOmemoIdentityException, NoSuchAlgorithmException,
|
throws CryptoFailedException, UndecidedOmemoIdentityException, NoSuchAlgorithmException,
|
||||||
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
|
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
|
||||||
CannotEstablishOmemoSessionException
|
CannotEstablishOmemoSessionException
|
||||||
|
@ -1042,9 +998,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
*
|
*
|
||||||
* @return OmemoMessageElement
|
* @return OmemoMessageElement
|
||||||
*/
|
*/
|
||||||
OmemoVAxolotlElement encryptOmemoMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
OmemoElement encryptOmemoMessage(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||||
HashMap<BareJid, ArrayList<OmemoDevice>> recipients,
|
HashMap<BareJid, ArrayList<OmemoDevice>> recipients,
|
||||||
Message message)
|
Message message)
|
||||||
throws CryptoFailedException, UndecidedOmemoIdentityException
|
throws CryptoFailedException, UndecidedOmemoIdentityException
|
||||||
{
|
{
|
||||||
OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>
|
OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>
|
||||||
|
@ -1095,8 +1051,8 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @throws CorruptedOmemoKeyException
|
* @throws CorruptedOmemoKeyException
|
||||||
* @throws CannotEstablishOmemoSessionException
|
* @throws CannotEstablishOmemoSessionException
|
||||||
*/
|
*/
|
||||||
OmemoVAxolotlElement prepareOmemoKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard,
|
OmemoElement prepareOmemoKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||||
OmemoDevice... recipients)
|
OmemoDevice... recipients)
|
||||||
throws CryptoFailedException, UndecidedOmemoIdentityException, CorruptedOmemoKeyException,
|
throws CryptoFailedException, UndecidedOmemoIdentityException, CorruptedOmemoKeyException,
|
||||||
CannotEstablishOmemoSessionException
|
CannotEstablishOmemoSessionException
|
||||||
{
|
{
|
||||||
|
@ -1130,10 +1086,10 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @throws CorruptedOmemoKeyException
|
* @throws CorruptedOmemoKeyException
|
||||||
* @throws CannotEstablishOmemoSessionException
|
* @throws CannotEstablishOmemoSessionException
|
||||||
*/
|
*/
|
||||||
OmemoVAxolotlElement prepareOmemoKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard,
|
OmemoElement prepareOmemoKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||||
byte[] aesKey,
|
byte[] aesKey,
|
||||||
byte[] iv,
|
byte[] iv,
|
||||||
OmemoDevice... recipients)
|
OmemoDevice... recipients)
|
||||||
throws CryptoFailedException, UndecidedOmemoIdentityException, CorruptedOmemoKeyException,
|
throws CryptoFailedException, UndecidedOmemoIdentityException, CorruptedOmemoKeyException,
|
||||||
CannotEstablishOmemoSessionException
|
CannotEstablishOmemoSessionException
|
||||||
{
|
{
|
||||||
|
@ -1177,7 +1133,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
buildSessionWithDevice(managerGuard, recipient, true);
|
buildSessionWithDevice(managerGuard, recipient, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
OmemoVAxolotlElement keyTransportElement = prepareOmemoKeyTransportElement(managerGuard, recipient);
|
OmemoElement keyTransportElement = prepareOmemoKeyTransportElement(managerGuard, recipient);
|
||||||
Message ratchetUpdateMessage = managerGuard.get().finishMessage(keyTransportElement);
|
Message ratchetUpdateMessage = managerGuard.get().finishMessage(keyTransportElement);
|
||||||
ratchetUpdateMessage.setTo(recipient.getJid());
|
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,
|
private static OmemoDevice getSender(OmemoManager.LoggedInOmemoManager managerGuard,
|
||||||
Stanza stanza) {
|
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();
|
Jid sender = stanza.getFrom();
|
||||||
if (isMucMessage(managerGuard, stanza)) {
|
if (isMucMessage(managerGuard, stanza)) {
|
||||||
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(managerGuard.get().getConnection());
|
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) {
|
public void onOmemoMessageStanzaReceived(Stanza stanza, OmemoManager.LoggedInOmemoManager managerGuard) {
|
||||||
OmemoManager omemoManager = managerGuard.get();
|
OmemoManager omemoManager = managerGuard.get();
|
||||||
Message decrypted;
|
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();
|
OmemoMessageInformation messageInfo = new OmemoMessageInformation();
|
||||||
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(omemoManager.getConnection());
|
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(omemoManager.getConnection());
|
||||||
OmemoDevice senderDevice = getSender(managerGuard, stanza);
|
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);
|
final OmemoDevice senderDevice = getSender(managerGuard, carbonCopy);
|
||||||
Message decrypted;
|
Message decrypted;
|
||||||
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(omemoManager.getConnection());
|
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();
|
OmemoMessageInformation messageInfo = new OmemoMessageInformation();
|
||||||
|
|
||||||
if (CarbonExtension.Direction.received.equals(direction)) {
|
if (CarbonExtension.Direction.received.equals(direction)) {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.omemo;
|
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.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -26,7 +26,7 @@ import java.util.TreeMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
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.element.OmemoDeviceListElement;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
|
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
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 contact Contact we received the list from.
|
||||||
* @param list List we received.
|
* @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);
|
CachedDeviceList cached = loadCachedDeviceList(userDevice, contact);
|
||||||
|
|
||||||
if (cached == null) {
|
if (cached == null) {
|
||||||
|
@ -108,8 +108,10 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
||||||
|
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
cached.merge(list.getDeviceIds());
|
cached.merge(list.getDeviceIds());
|
||||||
|
storeCachedDeviceList(userDevice, contact, cached);
|
||||||
}
|
}
|
||||||
storeCachedDeviceList(userDevice, contact, cached);
|
|
||||||
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,13 +167,30 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
|
||||||
/**
|
/**
|
||||||
* Pack a OmemoBundleElement containing our key material.
|
* 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.
|
* 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.
|
* @param userDevice our OmemoDevice.
|
||||||
* @return OmemoBundleElement
|
* @return OmemoBundleElement
|
||||||
* @throws CorruptedOmemoKeyException when a key could not be loaded
|
* @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
|
throws CorruptedOmemoKeyException
|
||||||
{
|
{
|
||||||
T_IdKeyPair identityKeyPair = loadOmemoIdentityKeyPair(userDevice);
|
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);
|
TreeMap<Integer, T_SigPreKey> signedPreKeys = loadOmemoSignedPreKeys(userDevice);
|
||||||
if (signedPreKeys.size() == 0) {
|
if (signedPreKeys.size() == 0) {
|
||||||
changeSignedPreKey(userDevice);
|
changeSignedPreKey(userDevice);
|
||||||
signedPreKeys = loadOmemoSignedPreKeys(userDevice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentSignedPreKeyId = signedPreKeys.lastKey();
|
|
||||||
T_SigPreKey currentSignedPreKey = signedPreKeys.get(currentSignedPreKeyId);
|
|
||||||
|
|
||||||
TreeMap<Integer, T_PreKey> preKeys = loadOmemoPreKeys(userDevice);
|
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();
|
int startId = preKeys.size() == 0 ? 0 : preKeys.lastKey();
|
||||||
|
|
||||||
if (newKeysCount > 0) {
|
if (newKeysCount > 0) {
|
||||||
TreeMap<Integer, T_PreKey> newKeys = generateOmemoPreKeys(startId + 1, newKeysCount);
|
TreeMap<Integer, T_PreKey> newKeys = generateOmemoPreKeys(startId + 1, newKeysCount);
|
||||||
storeOmemoPreKeys(userDevice, newKeys);
|
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*
|
// *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 abstract T_SigPreKey loadOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId);
|
||||||
|
|
||||||
|
public int loadCurrentOmemoSignedPreKeyId(OmemoDevice userDevice) {
|
||||||
|
return loadOmemoSignedPreKeys(userDevice).lastKey();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load all our signed PreKeys.
|
* 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);
|
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.
|
* Store the DeviceList of the contact in local storage.
|
||||||
* See this as a cache.
|
* See this as a cache.
|
||||||
|
|
|
@ -16,12 +16,15 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.omemo.element;
|
package org.jivesoftware.smackx.omemo.element;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that represents an OMEMO Bundle element.
|
* Class that represents an OMEMO Bundle element.
|
||||||
* TODO: Move functionality to here.
|
|
||||||
*
|
*
|
||||||
* @author Paul Schaub
|
* @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_PUB = "preKeyPublic";
|
||||||
public static final String PRE_KEY_ID = "preKeyId";
|
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
|
@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
|
@Override
|
||||||
public boolean equals(Object other) {
|
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
|
* @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);
|
super(deviceIds);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.omemo.element;
|
package org.jivesoftware.smackx.omemo.element;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||||
import org.jivesoftware.smack.packet.NamedElement;
|
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that represents an OmemoElement.
|
* Class that represents an OmemoElement.
|
||||||
* TODO: Move functionality here.
|
|
||||||
*
|
*
|
||||||
* @author Paul Schaub
|
* @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_PREKEY_MESSAGE = 1;
|
||||||
public static final int TYPE_OMEMO_MESSAGE = 0;
|
public static final int TYPE_OMEMO_MESSAGE = 0;
|
||||||
|
|
||||||
public static final String ENCRYPTED = "encrypted";
|
public static final String NAME_ENCRYPTED = "encrypted";
|
||||||
public static final String HEADER = "header";
|
public static final String ATTR_PAYLOAD = "payload";
|
||||||
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";
|
|
||||||
|
|
||||||
protected final OmemoElement.OmemoHeader header;
|
private final OmemoHeaderElement header;
|
||||||
protected final byte[] payload;
|
private final byte[] payload;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new OmemoMessageElement from a header and a 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 header header of the message
|
||||||
* @param payload payload
|
* @param payload payload
|
||||||
*/
|
*/
|
||||||
public OmemoElement(OmemoElement.OmemoHeader header, byte[] payload) {
|
public OmemoElement(OmemoHeaderElement header, byte[] payload) {
|
||||||
this.header = Objects.requireNonNull(header);
|
this.header = Objects.requireNonNull(header);
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OmemoElement.OmemoHeader getHeader() {
|
public OmemoHeaderElement getHeader() {
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,113 +72,22 @@ public abstract class OmemoElement implements ExtensionElement {
|
||||||
return payload != null;
|
return payload != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Header element of the message. The header contains information about the sender and the encrypted keys for
|
public XmlStringBuilder toXML(String enclosingNamespace) {
|
||||||
* the recipients, as well as the iv element for AES.
|
XmlStringBuilder sb = new XmlStringBuilder(this, enclosingNamespace).rightAngleBracket();
|
||||||
*/
|
|
||||||
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) {
|
sb.element(header);
|
||||||
this.sid = sid;
|
|
||||||
this.keys = keys;
|
if (payload != null) {
|
||||||
this.iv = iv;
|
sb.openElement(ATTR_PAYLOAD).append(Base64.encodeToString(payload)).closeElement(ATTR_PAYLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
sb.closeElement(this);
|
||||||
* Return the deviceId of the sender of the message.
|
return sb;
|
||||||
*
|
}
|
||||||
* @return senders id
|
|
||||||
*/
|
|
||||||
public int getSid() {
|
|
||||||
return sid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<OmemoHeader.Key> getKeys() {
|
@Override
|
||||||
return new ArrayList<>(keys);
|
public String getElementName() {
|
||||||
}
|
return NAME_ENCRYPTED;
|
||||||
|
|
||||||
public byte[] getIv() {
|
|
||||||
return iv != null ? iv.clone() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getElementName() {
|
|
||||||
return HEADER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, HashMap<OmemoDevice, Throwable>> failures = new HashMap<>();
|
||||||
private final HashMap<BareJid, ArrayList<OmemoDevice>> successes = new HashMap<>();
|
private final HashMap<BareJid, ArrayList<OmemoDevice>> successes = new HashMap<>();
|
||||||
|
|
||||||
|
public CannotEstablishOmemoSessionException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
public CannotEstablishOmemoSessionException(OmemoDevice failed, Throwable reason) {
|
public CannotEstablishOmemoSessionException(OmemoDevice failed, Throwable reason) {
|
||||||
super();
|
super();
|
||||||
getFailsOfContact(failed.getJid()).put(failed, reason);
|
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
|
* @param deviceId deviceId that will be added
|
||||||
*/
|
*/
|
||||||
public void addDevice(int deviceId) {
|
public void addDevice(int deviceId) {
|
||||||
activeDevices.add(deviceId);
|
activeDevices.add(deviceId);
|
||||||
|
inactiveDevices.remove(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -118,6 +119,10 @@ public class CachedDeviceList implements Serializable {
|
||||||
return activeDevices.contains(deviceId) || inactiveDevices.contains(deviceId);
|
return activeDevices.contains(deviceId) || inactiveDevices.contains(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isActive(int deviceId) {
|
||||||
|
return getActiveDevices().contains(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String out = "active: [";
|
String out = "active: [";
|
||||||
|
|
|
@ -31,7 +31,7 @@ import java.util.HashMap;
|
||||||
|
|
||||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
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;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
@ -40,9 +40,9 @@ import org.xmlpull.v1.XmlPullParser;
|
||||||
*
|
*
|
||||||
* @author Paul Schaub
|
* @author Paul Schaub
|
||||||
*/
|
*/
|
||||||
public class OmemoBundleVAxolotlProvider extends ExtensionElementProvider<OmemoBundleVAxolotlElement> {
|
public class OmemoBundleVAxolotlProvider extends ExtensionElementProvider<OmemoBundleElement_VAxolotl> {
|
||||||
@Override
|
@Override
|
||||||
public OmemoBundleVAxolotlElement parse(XmlPullParser parser, int initialDepth) throws Exception {
|
public OmemoBundleElement_VAxolotl parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||||
boolean stop = false;
|
boolean stop = false;
|
||||||
boolean inPreKeys = false;
|
boolean inPreKeys = false;
|
||||||
|
|
||||||
|
@ -96,6 +96,6 @@ public class OmemoBundleVAxolotlProvider extends ExtensionElementProvider<OmemoB
|
||||||
break;
|
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.smack.provider.ExtensionElementProvider;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListVAxolotlElement;
|
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement_VAxolotl;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@ import org.xmlpull.v1.XmlPullParser;
|
||||||
*
|
*
|
||||||
* @author Paul Schaub
|
* @author Paul Schaub
|
||||||
*/
|
*/
|
||||||
public class OmemoDeviceListVAxolotlProvider extends ExtensionElementProvider<OmemoDeviceListVAxolotlElement> {
|
public class OmemoDeviceListVAxolotlProvider extends ExtensionElementProvider<OmemoDeviceListElement_VAxolotl> {
|
||||||
|
|
||||||
@Override
|
@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<>();
|
Set<Integer> deviceListIds = new HashSet<>();
|
||||||
boolean stop = false;
|
boolean stop = false;
|
||||||
while (!stop) {
|
while (!stop) {
|
||||||
|
@ -63,6 +63,6 @@ public class OmemoDeviceListVAxolotlProvider extends ExtensionElementProvider<Om
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new OmemoDeviceListVAxolotlElement(deviceListIds);
|
return new OmemoDeviceListElement_VAxolotl(deviceListIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.omemo.provider;
|
package org.jivesoftware.smackx.omemo.provider;
|
||||||
|
|
||||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.ENCRYPTED;
|
import static org.jivesoftware.smackx.omemo.element.OmemoElement.ATTR_PAYLOAD;
|
||||||
import static org.jivesoftware.smackx.omemo.element.OmemoElement.HEADER;
|
import static org.jivesoftware.smackx.omemo.element.OmemoElement.NAME_ENCRYPTED;
|
||||||
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.xmlpull.v1.XmlPullParser.END_TAG;
|
import static org.xmlpull.v1.XmlPullParser.END_TAG;
|
||||||
import static org.xmlpull.v1.XmlPullParser.START_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.provider.ExtensionElementProvider;
|
||||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||||
|
import org.jivesoftware.smackx.omemo.element.OmemoElement_VAxolotl;
|
||||||
import org.jivesoftware.smackx.omemo.element.OmemoVAxolotlElement;
|
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;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
@ -41,13 +37,13 @@ import org.xmlpull.v1.XmlPullParser;
|
||||||
*
|
*
|
||||||
* @author Paul Schaub
|
* @author Paul Schaub
|
||||||
*/
|
*/
|
||||||
public class OmemoVAxolotlProvider extends ExtensionElementProvider<OmemoVAxolotlElement> {
|
public class OmemoVAxolotlProvider extends ExtensionElementProvider<OmemoElement_VAxolotl> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OmemoVAxolotlElement parse(XmlPullParser parser, int initialDepth) throws Exception {
|
public OmemoElement_VAxolotl parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||||
boolean inEncrypted = true;
|
boolean inEncrypted = true;
|
||||||
int sid = -1;
|
int sid = -1;
|
||||||
ArrayList<OmemoVAxolotlElement.OmemoHeader.Key> keys = new ArrayList<>();
|
ArrayList<OmemoKeyElement> keys = new ArrayList<>();
|
||||||
byte[] iv = null;
|
byte[] iv = null;
|
||||||
byte[] payload = null;
|
byte[] payload = null;
|
||||||
|
|
||||||
|
@ -57,41 +53,41 @@ public class OmemoVAxolotlProvider extends ExtensionElementProvider<OmemoVAxolot
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case START_TAG:
|
case START_TAG:
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case HEADER:
|
case OmemoHeaderElement.NAME_HEADER:
|
||||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
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));
|
sid = Integer.parseInt(parser.getAttributeValue(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY:
|
case OmemoKeyElement.NAME_KEY:
|
||||||
boolean prekey = false;
|
boolean prekey = false;
|
||||||
int rid = -1;
|
int rid = -1;
|
||||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
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));
|
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));
|
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;
|
break;
|
||||||
case IV:
|
case OmemoHeaderElement.ATTR_IV:
|
||||||
iv = Base64.decode(parser.nextText());
|
iv = Base64.decode(parser.nextText());
|
||||||
break;
|
break;
|
||||||
case PAYLOAD:
|
case ATTR_PAYLOAD:
|
||||||
payload = Base64.decode(parser.nextText());
|
payload = Base64.decode(parser.nextText());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case END_TAG:
|
case END_TAG:
|
||||||
if (name.equals(ENCRYPTED)) {
|
if (name.equals(NAME_ENCRYPTED)) {
|
||||||
inEncrypted = false;
|
inEncrypted = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OmemoVAxolotlElement.OmemoHeader header = new OmemoVAxolotlElement.OmemoHeader(sid, keys, iv);
|
OmemoHeaderElement_VAxolotl header = new OmemoHeaderElement_VAxolotl(sid, keys, iv);
|
||||||
return new OmemoVAxolotlElement(header, payload);
|
return new OmemoElement_VAxolotl(header, payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ public final class OmemoConstants {
|
||||||
/**
|
/**
|
||||||
* How many preKeys do we want to publish?
|
* 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.
|
* 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;
|
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.
|
* 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.Level;
|
||||||
import java.util.logging.Logger;
|
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.exceptions.CorruptedOmemoKeyException;
|
||||||
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
|
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
|
||||||
import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;
|
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
|
* @return identityKey
|
||||||
* @throws CorruptedOmemoKeyException if the key is damaged/malformed
|
* @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());
|
return identityKeyFromBytes(bundle.getIdentityKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @return singedPreKey
|
* @return singedPreKey
|
||||||
* @throws CorruptedOmemoKeyException if the key is damaged/malformed
|
* @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());
|
return signedPreKeyPublicFromBytes(bundle.getSignedPreKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @param bundle OmemoBundleElement
|
* @param bundle OmemoBundleElement
|
||||||
* @return signedPreKeyId
|
* @return signedPreKeyId
|
||||||
*/
|
*/
|
||||||
public int signedPreKeyId(OmemoBundleVAxolotlElement bundle) {
|
public int signedPreKeyId(OmemoBundleElement bundle) {
|
||||||
return bundle.getSignedPreKeyId();
|
return bundle.getSignedPreKeyId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @param bundle OmemoBundleElement
|
* @param bundle OmemoBundleElement
|
||||||
* @return signature
|
* @return signature
|
||||||
*/
|
*/
|
||||||
public byte[] signedPreKeySignature(OmemoBundleVAxolotlElement bundle) {
|
public byte[] signedPreKeySignature(OmemoBundleElement bundle) {
|
||||||
return bundle.getSignedPreKeySignature();
|
return bundle.getSignedPreKeySignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @return the preKey
|
* @return the preKey
|
||||||
* @throws CorruptedOmemoKeyException when the key cannot be parsed from bytes
|
* @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));
|
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
|
* @return a HashMap with one T_Bundle per preKey and the preKeyId as key
|
||||||
* @throws CorruptedOmemoKeyException when one of the keys cannot be parsed
|
* @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<>();
|
HashMap<Integer, T_Bundle> bundles = new HashMap<>();
|
||||||
for (int deviceId : bundle.getPreKeys().keySet()) {
|
for (int deviceId : bundle.getPreKeys().keySet()) {
|
||||||
try {
|
try {
|
||||||
|
@ -255,7 +255,7 @@ public abstract class OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
|
||||||
* @return PreKeyBundle (T_PreKey)
|
* @return PreKeyBundle (T_PreKey)
|
||||||
* @throws CorruptedOmemoKeyException if some key is damaged or malformed
|
* @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.
|
* Extract the signature from a signedPreKey.
|
||||||
|
|
|
@ -41,7 +41,10 @@ import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smackx.omemo.OmemoManager;
|
import org.jivesoftware.smackx.omemo.OmemoManager;
|
||||||
import org.jivesoftware.smackx.omemo.OmemoRatchet;
|
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.CannotEstablishOmemoSessionException;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
|
||||||
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
|
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[] initializationVector = generateIv();
|
||||||
|
|
||||||
private byte[] ciphertextMessage;
|
private byte[] ciphertextMessage;
|
||||||
private final ArrayList<OmemoVAxolotlElement.OmemoHeader.Key> keys = new ArrayList<>();
|
private final ArrayList<OmemoKeyElement> keys = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a OmemoMessageBuilder.
|
* 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)) {
|
if (ignoreTrust || managerGuard.get().isTrustedOmemoIdentity(contactsDevice, fingerprint)) {
|
||||||
// Encrypt key and save to header
|
// Encrypt key and save to header
|
||||||
CiphertextTuple encryptedKey = ratchet.doubleRatchetEncrypt(contactsDevice, messageKey);
|
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
|
* @return OmemoMessageElement
|
||||||
*/
|
*/
|
||||||
public OmemoVAxolotlElement finish() {
|
public OmemoElement finish() {
|
||||||
OmemoVAxolotlElement.OmemoHeader header = new OmemoVAxolotlElement.OmemoHeader(
|
OmemoHeaderElement_VAxolotl header = new OmemoHeaderElement_VAxolotl(
|
||||||
managerGuard.get().getDeviceId(),
|
managerGuard.get().getDeviceId(),
|
||||||
keys,
|
keys,
|
||||||
initializationVector
|
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.StringUtils;
|
||||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
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.jivesoftware.smackx.omemo.provider.OmemoBundleVAxolotlProvider;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -50,7 +50,7 @@ public class OmemoBundleVAxolotlElementTest extends SmackTestSuite {
|
||||||
preKeysB64.put(preKeyId1, preKey1B64);
|
preKeysB64.put(preKeyId1, preKey1B64);
|
||||||
preKeysB64.put(preKeyId2, preKey2B64);
|
preKeysB64.put(preKeyId2, preKey2B64);
|
||||||
|
|
||||||
OmemoBundleVAxolotlElement bundle = new OmemoBundleVAxolotlElement(signedPreKeyId,
|
OmemoBundleElement_VAxolotl bundle = new OmemoBundleElement_VAxolotl(signedPreKeyId,
|
||||||
signedPreKeyB64, signedPreKeySigB64, identityKeyB64, preKeysB64);
|
signedPreKeyB64, signedPreKeySigB64, identityKeyB64, preKeysB64);
|
||||||
|
|
||||||
assertEquals("ElementName must match.", "bundle", bundle.getElementName());
|
assertEquals("ElementName must match.", "bundle", bundle.getElementName());
|
||||||
|
@ -85,7 +85,7 @@ public class OmemoBundleVAxolotlElementTest extends SmackTestSuite {
|
||||||
byte[] firstPreKey = "FirstPreKey".getBytes(StringUtils.UTF8);
|
byte[] firstPreKey = "FirstPreKey".getBytes(StringUtils.UTF8);
|
||||||
byte[] secondPreKey = "SecondPreKey".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()));
|
assertTrue("B64-decoded signedPreKey must match.", Arrays.equals(signedPreKey, parsed.getSignedPreKey()));
|
||||||
assertEquals("SignedPreKeyId must match", signedPreKeyId, parsed.getSignedPreKeyId());
|
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.SmackTestSuite;
|
||||||
import org.jivesoftware.smack.test.util.TestUtils;
|
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.jivesoftware.smackx.omemo.provider.OmemoDeviceListVAxolotlProvider;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -41,11 +41,11 @@ public class OmemoDeviceListVAxolotlElementTest extends SmackTestSuite {
|
||||||
ids.add(1234);
|
ids.add(1234);
|
||||||
ids.add(9876);
|
ids.add(9876);
|
||||||
|
|
||||||
OmemoDeviceListVAxolotlElement element = new OmemoDeviceListVAxolotlElement(ids);
|
OmemoDeviceListElement_VAxolotl element = new OmemoDeviceListElement_VAxolotl(ids);
|
||||||
String xml = element.toXML(null).toString();
|
String xml = element.toXML(null).toString();
|
||||||
|
|
||||||
XmlPullParser parser = TestUtils.getParser(xml);
|
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()));
|
assertTrue("Parsed element must equal the original.", parsed.getDeviceIds().equals(element.getDeviceIds()));
|
||||||
assertEquals("Generated XML must match.",
|
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.test.util.TestUtils;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||||
|
import org.jivesoftware.smackx.omemo.element.OmemoElement_VAxolotl;
|
||||||
import org.jivesoftware.smackx.omemo.element.OmemoElement;
|
import org.jivesoftware.smackx.omemo.element.OmemoHeaderElement_VAxolotl;
|
||||||
import org.jivesoftware.smackx.omemo.element.OmemoVAxolotlElement;
|
import org.jivesoftware.smackx.omemo.element.OmemoKeyElement;
|
||||||
import org.jivesoftware.smackx.omemo.provider.OmemoVAxolotlProvider;
|
import org.jivesoftware.smackx.omemo.provider.OmemoVAxolotlProvider;
|
||||||
import org.jivesoftware.smackx.omemo.util.OmemoMessageBuilder;
|
import org.jivesoftware.smackx.omemo.util.OmemoMessageBuilder;
|
||||||
|
|
||||||
|
@ -47,12 +47,12 @@ public class OmemoVAxolotlElementTest extends SmackTestSuite {
|
||||||
int sid = 12131415;
|
int sid = 12131415;
|
||||||
byte[] iv = OmemoMessageBuilder.generateIv();
|
byte[] iv = OmemoMessageBuilder.generateIv();
|
||||||
|
|
||||||
ArrayList<OmemoElement.OmemoHeader.Key> keys = new ArrayList<>();
|
ArrayList<OmemoKeyElement> keys = new ArrayList<>();
|
||||||
keys.add(new OmemoElement.OmemoHeader.Key(keyData1, keyId1));
|
keys.add(new OmemoKeyElement(keyData1, keyId1));
|
||||||
keys.add(new OmemoElement.OmemoHeader.Key(keyData2, keyId2, true));
|
keys.add(new OmemoKeyElement(keyData2, keyId2, true));
|
||||||
|
|
||||||
OmemoVAxolotlElement.OmemoHeader header = new OmemoElement.OmemoHeader(sid, keys, iv);
|
OmemoHeaderElement_VAxolotl header = new OmemoHeaderElement_VAxolotl(sid, keys, iv);
|
||||||
OmemoVAxolotlElement element = new OmemoVAxolotlElement(header, payload);
|
OmemoElement_VAxolotl element = new OmemoElement_VAxolotl(header, payload);
|
||||||
|
|
||||||
String expected =
|
String expected =
|
||||||
"<encrypted xmlns='eu.siacs.conversations.axolotl'>" +
|
"<encrypted xmlns='eu.siacs.conversations.axolotl'>" +
|
||||||
|
@ -69,7 +69,9 @@ public class OmemoVAxolotlElementTest extends SmackTestSuite {
|
||||||
String actual = element.toXML(null).toString();
|
String actual = element.toXML(null).toString();
|
||||||
assertEquals("Serialized xml of OmemoElement must match.", expected, actual);
|
assertEquals("Serialized xml of OmemoElement must match.", expected, actual);
|
||||||
|
|
||||||
OmemoVAxolotlElement parsed = new OmemoVAxolotlProvider().parse(TestUtils.getParser(actual));
|
OmemoElement_VAxolotl parsed = new OmemoVAxolotlProvider().parse(TestUtils.getParser(actual));
|
||||||
assertEquals("Parsed OmemoElement must equal the original.", element.toXML(null).toString(), parsed.toXML(null).toString());
|
assertEquals("Parsed OmemoElement must equal the original.",
|
||||||
|
element.toXML(null).toString(),
|
||||||
|
parsed.toXML(null).toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue