Refactor axolotl message processing workflow

XmppAxolotlMessage is now entirely responsible for handling encryption
and decryption of messages, only leveraging XmppAxolotlSession as a
packing/unpacking primitive for payload keys.

Removed pseudo-dead session generation code step from prepareMessage
function, as sessions have been created by invoking the
TrustKeysActivity for a while now.

Added prepareKeyTransportMessage function, which creates a message with
no payload. The key that is packed into the header keyElements can then
be used for other purposes (e.g. encrypted file transfer).
This commit is contained in:
Andreas Straub 2015-07-31 21:12:34 +02:00
parent 50b14434ee
commit 909f761ca1
7 changed files with 118 additions and 154 deletions

View file

@ -256,7 +256,7 @@ public class AxolotlService {
for (Integer deviceId : deviceIds) { for (Integer deviceId : deviceIds) {
AxolotlAddress ownDeviceAddress = new AxolotlAddress(jid.toBareJid().toString(), deviceId); AxolotlAddress ownDeviceAddress = new AxolotlAddress(jid.toBareJid().toString(), deviceId);
if (sessions.get(ownDeviceAddress) == null) { if (sessions.get(ownDeviceAddress) == null) {
buildSessionFromPEP(null, ownDeviceAddress, false); buildSessionFromPEP(ownDeviceAddress);
} }
} }
} }
@ -422,7 +422,7 @@ public class AxolotlService {
axolotlStore.setFingerprintTrust(fingerprint, trust); axolotlStore.setFingerprintTrust(fingerprint, trust);
} }
private void buildSessionFromPEP(final Conversation conversation, final AxolotlAddress address, final boolean flushWaitingQueueAfterFetch) { private void buildSessionFromPEP(final AxolotlAddress address) {
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building new sesstion for " + address.getDeviceId()); Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building new sesstion for " + address.getDeviceId());
try { try {
@ -434,15 +434,6 @@ public class AxolotlService {
AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toString(), 0); AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toString(), 0);
if (!fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING) if (!fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING)
&& !fetchStatusMap.getAll(address).containsValue(FetchStatus.PENDING)) { && !fetchStatusMap.getAll(address).containsValue(FetchStatus.PENDING)) {
if (flushWaitingQueueAfterFetch && conversation != null) {
conversation.findUnsentMessagesWithEncryption(Message.ENCRYPTION_AXOLOTL,
new Conversation.OnMessageFound() {
@Override
public void onMessageFound(Message message) {
processSending(message, false);
}
});
}
mXmppConnectionService.keyStatusUpdated(); mXmppConnectionService.keyStatusUpdated();
} }
} }
@ -537,7 +528,7 @@ public class AxolotlService {
return addresses; return addresses;
} }
public boolean createSessionsIfNeeded(final Conversation conversation, final boolean flushWaitingQueueAfterFetch) { public boolean createSessionsIfNeeded(final Conversation conversation) {
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Creating axolotl sessions if needed..."); Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Creating axolotl sessions if needed...");
boolean newSessions = false; boolean newSessions = false;
Set<AxolotlAddress> addresses = findDevicesWithoutSession(conversation); Set<AxolotlAddress> addresses = findDevicesWithoutSession(conversation);
@ -546,7 +537,9 @@ public class AxolotlService {
FetchStatus status = fetchStatusMap.get(address); FetchStatus status = fetchStatusMap.get(address);
if (status == null || status == FetchStatus.ERROR) { if (status == null || status == FetchStatus.ERROR) {
fetchStatusMap.put(address, FetchStatus.PENDING); fetchStatusMap.put(address, FetchStatus.PENDING);
this.buildSessionFromPEP(conversation, address, flushWaitingQueueAfterFetch); this.buildSessionFromPEP(address);
newSessions = true;
} else if (status == FetchStatus.PENDING) {
newSessions = true; newSessions = true;
} else { } else {
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Already fetching bundle for " + address.toString()); Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Already fetching bundle for " + address.toString());
@ -564,41 +557,53 @@ public class AxolotlService {
} }
@Nullable
private XmppAxolotlMessage buildHeader(Contact contact) {
final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(
contact.getJid().toBareJid(), getOwnDeviceId());
Set<XmppAxolotlSession> contactSessions = findSessionsforContact(contact);
Set<XmppAxolotlSession> ownSessions = findOwnSessions();
if (contactSessions.isEmpty()) {
return null;
}
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building axolotl foreign keyElements...");
for (XmppAxolotlSession session : contactSessions) {
Log.v(Config.LOGTAG, AxolotlService.getLogprefix(account) + session.getRemoteAddress().toString());
axolotlMessage.addDevice(session);
}
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building axolotl own keyElements...");
for (XmppAxolotlSession session : ownSessions) {
Log.v(Config.LOGTAG, AxolotlService.getLogprefix(account) + session.getRemoteAddress().toString());
axolotlMessage.addDevice(session);
}
return axolotlMessage;
}
@Nullable @Nullable
public XmppAxolotlMessage encrypt(Message message) { public XmppAxolotlMessage encrypt(Message message) {
XmppAxolotlMessage axolotlMessage = buildHeader(message.getContact());
if (axolotlMessage != null) {
final String content; final String content;
if (message.hasFileOnRemoteHost()) { if (message.hasFileOnRemoteHost()) {
content = message.getFileParams().url.toString(); content = message.getFileParams().url.toString();
} else { } else {
content = message.getBody(); content = message.getBody();
} }
final XmppAxolotlMessage axolotlMessage;
try { try {
axolotlMessage = new XmppAxolotlMessage(message.getContact().getJid().toBareJid(), axolotlMessage.encrypt(content);
getOwnDeviceId(), content);
} catch (CryptoFailedException e) { } catch (CryptoFailedException e) {
Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to encrypt message: " + e.getMessage()); Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to encrypt message: " + e.getMessage());
return null; return null;
} }
if (findSessionsforContact(message.getContact()).isEmpty()) {
return null;
}
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building axolotl foreign keyElements...");
for (XmppAxolotlSession session : findSessionsforContact(message.getContact())) {
Log.v(Config.LOGTAG, AxolotlService.getLogprefix(account) + session.getRemoteAddress().toString());
axolotlMessage.addKeyElement(session.processSending(axolotlMessage.getInnerKey()));
}
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building axolotl own keyElements...");
for (XmppAxolotlSession session : findOwnSessions()) {
Log.v(Config.LOGTAG, AxolotlService.getLogprefix(account) + session.getRemoteAddress().toString());
axolotlMessage.addKeyElement(session.processSending(axolotlMessage.getInnerKey()));
} }
return axolotlMessage; return axolotlMessage;
} }
private void processSending(final Message message, final boolean delay) { public void preparePayloadMessage(final Message message, final boolean delay) {
executor.execute(new Runnable() { executor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -615,13 +620,14 @@ public class AxolotlService {
}); });
} }
public void prepareMessage(final Message message, final boolean delay) { public void prepareKeyTransportMessage(final Contact contact, final OnMessageCreatedCallback onMessageCreatedCallback) {
if (!messageCache.containsKey(message.getUuid())) { executor.execute(new Runnable() {
boolean newSessions = createSessionsIfNeeded(message.getConversation(), true); @Override
if (!newSessions) { public void run() {
this.processSending(message, delay); XmppAxolotlMessage axolotlMessage = buildHeader(contact);
} onMessageCreatedCallback.run(axolotlMessage);
} }
});
} }
public XmppAxolotlMessage fetchAxolotlMessageFromCache(Message message) { public XmppAxolotlMessage fetchAxolotlMessageFromCache(Message message) {
@ -653,26 +659,15 @@ public class AxolotlService {
newSession = true; newSession = true;
} }
for (XmppAxolotlMessage.XmppAxolotlKeyElement keyElement : message.getKeyElements()) {
if (keyElement.getRecipientDeviceId() == getOwnDeviceId()) {
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Found axolotl keyElement matching own device ID, processing...");
byte[] payloadKey = session.processReceiving(keyElement);
if (payloadKey != null) {
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Got payload key from axolotl keyElement. Decrypting message...");
try { try {
plaintextMessage = message.decrypt(session, payloadKey, session.getFingerprint()); plaintextMessage = message.decrypt(session, getOwnDeviceId());
} catch (CryptoFailedException e) {
Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to decrypt message: " + e.getMessage());
break;
}
}
Integer preKeyId = session.getPreKeyId(); Integer preKeyId = session.getPreKeyId();
if (preKeyId != null) { if (preKeyId != null) {
publishBundlesIfNeeded(); publishBundlesIfNeeded();
session.resetPreKeyId(); session.resetPreKeyId();
} }
break; } catch (CryptoFailedException e) {
} Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to decrypt message: " + e.getMessage());
} }
if (newSession && plaintextMessage != null) { if (newSession && plaintextMessage != null) {

View file

@ -1,6 +1,5 @@
package eu.siacs.conversations.crypto.axolotl; package eu.siacs.conversations.crypto.axolotl;
import android.support.annotation.Nullable;
import android.util.Base64; import android.util.Base64;
import android.util.Log; import android.util.Log;
@ -9,8 +8,9 @@ import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.HashSet; import java.util.HashMap;
import java.util.Set; import java.util.List;
import java.util.Map;
import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException;
import javax.crypto.Cipher; import javax.crypto.Cipher;
@ -26,9 +26,11 @@ import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jid.Jid;
public class XmppAxolotlMessage { public class XmppAxolotlMessage {
public static final String TAGNAME = "encrypted"; public static final String CONTAINERTAG = "encrypted";
public static final String HEADER = "header"; public static final String HEADER = "header";
public static final String SOURCEID = "sid"; public static final String SOURCEID = "sid";
public static final String KEYTAG = "key";
public static final String REMOTEID = "rid";
public static final String IVTAG = "iv"; public static final String IVTAG = "iv";
public static final String PAYLOAD = "payload"; public static final String PAYLOAD = "payload";
@ -39,54 +41,15 @@ public class XmppAxolotlMessage {
private byte[] innerKey; private byte[] innerKey;
private byte[] ciphertext = null; private byte[] ciphertext = null;
private byte[] iv = null; private byte[] iv = null;
private final Set<XmppAxolotlKeyElement> keyElements; private final Map<Integer, byte[]> keys;
private final Jid from; private final Jid from;
private final int sourceDeviceId; private final int sourceDeviceId;
public static class XmppAxolotlKeyElement {
public static final String TAGNAME = "key";
public static final String REMOTEID = "rid";
private final int recipientDeviceId;
private final byte[] content;
public XmppAxolotlKeyElement(int deviceId, byte[] content) {
this.recipientDeviceId = deviceId;
this.content = content;
}
public XmppAxolotlKeyElement(Element keyElement) {
if (TAGNAME.equals(keyElement.getName())) {
this.recipientDeviceId = Integer.parseInt(keyElement.getAttribute(REMOTEID));
this.content = Base64.decode(keyElement.getContent(), Base64.DEFAULT);
} else {
throw new IllegalArgumentException("Argument not a <" + TAGNAME + "> Element!");
}
}
public int getRecipientDeviceId() {
return recipientDeviceId;
}
public byte[] getContents() {
return content;
}
public Element toXml() {
Element keyElement = new Element(TAGNAME);
keyElement.setAttribute(REMOTEID, getRecipientDeviceId());
keyElement.setContent(Base64.encodeToString(getContents(), Base64.DEFAULT));
return keyElement;
}
}
public static class XmppAxolotlPlaintextMessage { public static class XmppAxolotlPlaintextMessage {
private final XmppAxolotlSession session;
private final String plaintext; private final String plaintext;
private final String fingerprint; private final String fingerprint;
public XmppAxolotlPlaintextMessage(XmppAxolotlSession session, String plaintext, String fingerprint) { public XmppAxolotlPlaintextMessage(String plaintext, String fingerprint) {
this.session = session;
this.plaintext = plaintext; this.plaintext = plaintext;
this.fingerprint = fingerprint; this.fingerprint = fingerprint;
} }
@ -95,24 +58,28 @@ public class XmppAxolotlMessage {
return plaintext; return plaintext;
} }
public XmppAxolotlSession getSession() {
return session;
}
public String getFingerprint() { public String getFingerprint() {
return fingerprint; return fingerprint;
} }
} }
public XmppAxolotlMessage(Jid from, Element axolotlMessage) throws IllegalArgumentException { private XmppAxolotlMessage(final Element axolotlMessage, final Jid from) throws IllegalArgumentException {
this.from = from; this.from = from;
Element header = axolotlMessage.findChild(HEADER); Element header = axolotlMessage.findChild(HEADER);
this.sourceDeviceId = Integer.parseInt(header.getAttribute(SOURCEID)); this.sourceDeviceId = Integer.parseInt(header.getAttribute(SOURCEID));
this.keyElements = new HashSet<>(); List<Element> keyElements = header.getChildren();
for (Element keyElement : header.getChildren()) { this.keys = new HashMap<>(keyElements.size());
for (Element keyElement : keyElements) {
switch (keyElement.getName()) { switch (keyElement.getName()) {
case XmppAxolotlKeyElement.TAGNAME: case KEYTAG:
keyElements.add(new XmppAxolotlKeyElement(keyElement)); try {
Integer recipientId = Integer.parseInt(keyElement.getAttribute(REMOTEID));
byte[] key = Base64.decode(keyElement.getContent(), Base64.DEFAULT);
this.keys.put(recipientId, key);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(e);
}
break; break;
case IVTAG: case IVTAG:
if (this.iv != null) { if (this.iv != null) {
@ -134,14 +101,13 @@ public class XmppAxolotlMessage {
public XmppAxolotlMessage(Jid from, int sourceDeviceId) { public XmppAxolotlMessage(Jid from, int sourceDeviceId) {
this.from = from; this.from = from;
this.sourceDeviceId = sourceDeviceId; this.sourceDeviceId = sourceDeviceId;
this.keyElements = new HashSet<>(); this.keys = new HashMap<>();
this.iv = generateIv(); this.iv = generateIv();
this.innerKey = generateKey(); this.innerKey = generateKey();
} }
public XmppAxolotlMessage(Jid from, int sourceDeviceId, String plaintext) throws CryptoFailedException { public static XmppAxolotlMessage fromElement(Element element, Jid from) {
this(from, sourceDeviceId); return new XmppAxolotlMessage(element, from);
this.encrypt(plaintext);
} }
private static byte[] generateKey() { private static byte[] generateKey() {
@ -162,7 +128,7 @@ public class XmppAxolotlMessage {
return iv; return iv;
} }
private void encrypt(String plaintext) throws CryptoFailedException { public void encrypt(String plaintext) throws CryptoFailedException {
try { try {
SecretKey secretKey = new SecretKeySpec(innerKey, KEYTYPE); SecretKey secretKey = new SecretKeySpec(innerKey, KEYTYPE);
IvParameterSpec ivSpec = new IvParameterSpec(iv); IvParameterSpec ivSpec = new IvParameterSpec(iv);
@ -189,13 +155,10 @@ public class XmppAxolotlMessage {
return ciphertext; return ciphertext;
} }
public Set<XmppAxolotlKeyElement> getKeyElements() { public void addDevice(XmppAxolotlSession session) {
return keyElements; byte[] key = session.processSending(innerKey);
} if (key != null) {
keys.put(session.getRemoteAddress().getDeviceId(), key);
public void addKeyElement(@Nullable XmppAxolotlKeyElement keyElement) {
if (keyElement != null) {
keyElements.add(keyElement);
} }
} }
@ -207,12 +170,15 @@ public class XmppAxolotlMessage {
return this.iv; return this.iv;
} }
public Element toXml() { public Element toElement() {
Element encryptionElement = new Element(TAGNAME, AxolotlService.PEP_PREFIX); Element encryptionElement = new Element(CONTAINERTAG, AxolotlService.PEP_PREFIX);
Element headerElement = encryptionElement.addChild(HEADER); Element headerElement = encryptionElement.addChild(HEADER);
headerElement.setAttribute(SOURCEID, sourceDeviceId); headerElement.setAttribute(SOURCEID, sourceDeviceId);
for (XmppAxolotlKeyElement header : keyElements) { for (Map.Entry<Integer, byte[]> keyEntry : keys.entrySet()) {
headerElement.addChild(header.toXml()); Element keyElement = new Element(KEYTAG);
keyElement.setAttribute(REMOTEID, keyEntry.getKey());
keyElement.setContent(Base64.encodeToString(keyEntry.getValue(), Base64.DEFAULT));
headerElement.addChild(keyElement);
} }
headerElement.addChild(IVTAG).setContent(Base64.encodeToString(iv, Base64.DEFAULT)); headerElement.addChild(IVTAG).setContent(Base64.encodeToString(iv, Base64.DEFAULT));
if (ciphertext != null) { if (ciphertext != null) {
@ -222,11 +188,16 @@ public class XmppAxolotlMessage {
return encryptionElement; return encryptionElement;
} }
public byte[] unpackKey(XmppAxolotlSession session, Integer sourceDeviceId) {
byte[] encryptedKey = keys.get(sourceDeviceId);
return (encryptedKey != null) ? session.processReceiving(encryptedKey) : null;
}
public XmppAxolotlPlaintextMessage decrypt(XmppAxolotlSession session, byte[] key, String fingerprint) throws CryptoFailedException { public XmppAxolotlPlaintextMessage decrypt(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException {
XmppAxolotlPlaintextMessage plaintextMessage = null; XmppAxolotlPlaintextMessage plaintextMessage = null;
byte[] key = unpackKey(session, sourceDeviceId);
if (key != null) {
try { try {
Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER); Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER);
SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE); SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE);
IvParameterSpec ivSpec = new IvParameterSpec(iv); IvParameterSpec ivSpec = new IvParameterSpec(iv);
@ -234,13 +205,14 @@ public class XmppAxolotlMessage {
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
String plaintext = new String(cipher.doFinal(ciphertext)); String plaintext = new String(cipher.doFinal(ciphertext));
plaintextMessage = new XmppAxolotlPlaintextMessage(session, plaintext, fingerprint); plaintextMessage = new XmppAxolotlPlaintextMessage(plaintext, session.getFingerprint());
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| InvalidAlgorithmParameterException | IllegalBlockSizeException | InvalidAlgorithmParameterException | IllegalBlockSizeException
| BadPaddingException | NoSuchProviderException e) { | BadPaddingException | NoSuchProviderException e) {
throw new CryptoFailedException(e); throw new CryptoFailedException(e);
} }
}
return plaintextMessage; return plaintextMessage;
} }
} }

View file

@ -69,7 +69,7 @@ public class XmppAxolotlSession {
} }
@Nullable @Nullable
public byte[] processReceiving(XmppAxolotlMessage.XmppAxolotlKeyElement incomingHeader) { public byte[] processReceiving(byte[] encryptedKey) {
byte[] plaintext = null; byte[] plaintext = null;
SQLiteAxolotlStore.Trust trust = getTrust(); SQLiteAxolotlStore.Trust trust = getTrust();
switch (trust) { switch (trust) {
@ -79,7 +79,7 @@ public class XmppAxolotlSession {
case TRUSTED: case TRUSTED:
try { try {
try { try {
PreKeyWhisperMessage message = new PreKeyWhisperMessage(incomingHeader.getContents()); PreKeyWhisperMessage message = new PreKeyWhisperMessage(encryptedKey);
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId()); Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
String fingerprint = message.getIdentityKey().getFingerprint().replaceAll("\\s", ""); String fingerprint = message.getIdentityKey().getFingerprint().replaceAll("\\s", "");
if (this.fingerprint != null && !this.fingerprint.equals(fingerprint)) { if (this.fingerprint != null && !this.fingerprint.equals(fingerprint)) {
@ -93,7 +93,7 @@ public class XmppAxolotlSession {
} }
} catch (InvalidMessageException | InvalidVersionException e) { } catch (InvalidMessageException | InvalidVersionException e) {
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "WhisperMessage received"); Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "WhisperMessage received");
WhisperMessage message = new WhisperMessage(incomingHeader.getContents()); WhisperMessage message = new WhisperMessage(encryptedKey);
plaintext = cipher.decrypt(message); plaintext = cipher.decrypt(message);
} catch (InvalidKeyException | InvalidKeyIdException | UntrustedIdentityException e) { } catch (InvalidKeyException | InvalidKeyIdException | UntrustedIdentityException e) {
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage()); Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
@ -117,14 +117,11 @@ public class XmppAxolotlSession {
} }
@Nullable @Nullable
public XmppAxolotlMessage.XmppAxolotlKeyElement processSending(@NonNull byte[] outgoingMessage) { public byte[] processSending(@NonNull byte[] outgoingMessage) {
SQLiteAxolotlStore.Trust trust = getTrust(); SQLiteAxolotlStore.Trust trust = getTrust();
if (trust == SQLiteAxolotlStore.Trust.TRUSTED) { if (trust == SQLiteAxolotlStore.Trust.TRUSTED) {
CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage); CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage);
XmppAxolotlMessage.XmppAxolotlKeyElement header = return ciphertextMessage.serialize();
new XmppAxolotlMessage.XmppAxolotlKeyElement(remoteAddress.getDeviceId(),
ciphertextMessage.serialize());
return header;
} else { } else {
return null; return null;
} }

View file

@ -63,7 +63,7 @@ public class MessageGenerator extends AbstractGenerator {
if (axolotlMessage == null) { if (axolotlMessage == null) {
return null; return null;
} }
packet.setAxolotlMessage(axolotlMessage.toXml()); packet.setAxolotlMessage(axolotlMessage.toElement());
return packet; return packet;
} }

View file

@ -99,7 +99,7 @@ public class MessageParser extends AbstractParser implements
private Message parseAxolotlChat(Element axolotlMessage, Jid from, String id, Conversation conversation, int status) { private Message parseAxolotlChat(Element axolotlMessage, Jid from, String id, Conversation conversation, int status) {
Message finishedMessage = null; Message finishedMessage = null;
AxolotlService service = conversation.getAccount().getAxolotlService(); AxolotlService service = conversation.getAccount().getAxolotlService();
XmppAxolotlMessage xmppAxolotlMessage = new XmppAxolotlMessage(from.toBareJid(), axolotlMessage); XmppAxolotlMessage xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlMessage, from.toBareJid());
XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = service.processReceiving(xmppAxolotlMessage); XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = service.processReceiving(xmppAxolotlMessage);
if(plaintextMessage != null) { if(plaintextMessage != null) {
finishedMessage = new Message(conversation, plaintextMessage.getPlaintext(), Message.ENCRYPTION_AXOLOTL, status); finishedMessage = new Message(conversation, plaintextMessage.getPlaintext(), Message.ENCRYPTION_AXOLOTL, status);
@ -272,7 +272,7 @@ public class MessageParser extends AbstractParser implements
final String body = packet.getBody(); final String body = packet.getBody();
final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user"); final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user");
final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted"); final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted");
final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.TAGNAME, AxolotlService.PEP_PREFIX); final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX);
int status; int status;
final Jid counterpart; final Jid counterpart;
final Jid to = packet.getTo(); final Jid to = packet.getTo();

View file

@ -764,7 +764,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} else { } else {
XmppAxolotlMessage axolotlMessage = account.getAxolotlService().fetchAxolotlMessageFromCache(message); XmppAxolotlMessage axolotlMessage = account.getAxolotlService().fetchAxolotlMessageFromCache(message);
if (axolotlMessage == null) { if (axolotlMessage == null) {
account.getAxolotlService().prepareMessage(message,delay); account.getAxolotlService().preparePayloadMessage(message, delay);
message.setAxolotlFingerprint(account.getAxolotlService().getOwnPublicKey().getFingerprint().replaceAll("\\s", "")); message.setAxolotlFingerprint(account.getAxolotlService().getOwnPublicKey().getFingerprint().replaceAll("\\s", ""));
} else { } else {
packet = mMessageGenerator.generateAxolotlChat(message, axolotlMessage); packet = mMessageGenerator.generateAxolotlChat(message, axolotlMessage);

View file

@ -1265,7 +1265,7 @@ public class ConversationActivity extends XmppActivity
|| !axolotlService.findDevicesWithoutSession(mSelectedConversation).isEmpty(); || !axolotlService.findDevicesWithoutSession(mSelectedConversation).isEmpty();
boolean hasNoTrustedKeys = axolotlService.getNumTrustedKeys(mSelectedConversation.getContact()) == 0; boolean hasNoTrustedKeys = axolotlService.getNumTrustedKeys(mSelectedConversation.getContact()) == 0;
if( hasPendingKeys || hasNoTrustedKeys) { if( hasPendingKeys || hasNoTrustedKeys) {
axolotlService.createSessionsIfNeeded(mSelectedConversation, false); axolotlService.createSessionsIfNeeded(mSelectedConversation);
Intent intent = new Intent(getApplicationContext(), TrustKeysActivity.class); Intent intent = new Intent(getApplicationContext(), TrustKeysActivity.class);
intent.putExtra("contact", mSelectedConversation.getContact().getJid().toBareJid().toString()); intent.putExtra("contact", mSelectedConversation.getContact().getJid().toBareJid().toString());
intent.putExtra("account", mSelectedConversation.getAccount().getJid().toBareJid().toString()); intent.putExtra("account", mSelectedConversation.getAccount().getJid().toBareJid().toString());