add automatic session completion
This commit is contained in:
parent
cf17a2ac6d
commit
ac2866a682
|
@ -96,6 +96,9 @@ public class AxolotlService extends AbstractAccountService {
|
|||
throws NoSessionException {
|
||||
final var session = getExistingSession(axolotlAddress);
|
||||
if (session == null) {
|
||||
// TODO When receiving a message that is not an OMEMOKeyExchange from a device there is
|
||||
// no session with, clients SHOULD create a session with that device and notify it about
|
||||
// the new session by responding with an empty OMEMO message as per Sending a message.
|
||||
throw new NoSessionException(
|
||||
String.format("No session for %s", axolotlAddress.toString()));
|
||||
}
|
||||
|
@ -166,15 +169,15 @@ public class AxolotlService extends AbstractAccountService {
|
|||
new AxolotlAddress(from.asBareJid(), header.getSourceDevice().get()));
|
||||
keyWithAuthTag = session.sessionCipher.decrypt(signalMessage);
|
||||
}
|
||||
if (keyWithAuthTag.length < 32) {
|
||||
throw new OutdatedSenderException(
|
||||
"Key did not contain auth tag. Sender needs to update their OMEMO client");
|
||||
}
|
||||
final var inDeviceList = database.axolotlDao().hasDeviceId(account, session.axolotlAddress);
|
||||
if (payload == null) {
|
||||
return new AxolotlPayload(
|
||||
session.axolotlAddress, session.identityKey, preKeyMessage, inDeviceList, null);
|
||||
}
|
||||
if (keyWithAuthTag.length < 32) {
|
||||
throw new OutdatedSenderException(
|
||||
"Key did not contain auth tag. Sender needs to update their OMEMO client");
|
||||
}
|
||||
final byte[] key = new byte[16];
|
||||
final byte[] authTag = new byte[16];
|
||||
final byte[] iv = header.getIv();
|
||||
|
|
|
@ -31,7 +31,7 @@ public class EncryptionBuilder {
|
|||
|
||||
private Long sourceDeviceId;
|
||||
|
||||
private ArrayList<AxolotlSession> sessions;
|
||||
private final ArrayList<AxolotlSession> sessions = new ArrayList<>();
|
||||
|
||||
private byte[] payload;
|
||||
|
||||
|
@ -76,6 +76,33 @@ public class EncryptionBuilder {
|
|||
return encrypted;
|
||||
}
|
||||
|
||||
public Encrypted buildKeyTransport() throws AxolotlEncryptionException {
|
||||
try {
|
||||
return buildKeyTransportOrThrow();
|
||||
} catch (final UntrustedIdentityException e) {
|
||||
throw new AxolotlEncryptionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Encrypted buildKeyTransportOrThrow() throws UntrustedIdentityException {
|
||||
final long sourceDeviceId =
|
||||
Preconditions.checkNotNull(this.sourceDeviceId, "Specify a source device id");
|
||||
Preconditions.checkState(
|
||||
this.payload == null, "A key transport message should not have a payload");
|
||||
// TODO key transport messages in twomemo (omemo:1) use 32 bytes of zeros instead of a key
|
||||
// TODO if we are not using this using this for actual key transport we can do this in siacs
|
||||
// omemo too (and get rid of the IV)
|
||||
final var sessions = ImmutableList.copyOf(this.sessions);
|
||||
final var key = generateKey();
|
||||
final var iv = generateIv();
|
||||
final var header = buildHeader(sessions, key);
|
||||
header.addIv(iv);
|
||||
header.setSourceDevice(sourceDeviceId);
|
||||
final var encrypted = new Encrypted();
|
||||
encrypted.addExtension(header);
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
public EncryptionBuilder payload(final String payload) {
|
||||
this.payload = payload.getBytes(StandardCharsets.UTF_8);
|
||||
return this;
|
||||
|
@ -97,6 +124,7 @@ public class EncryptionBuilder {
|
|||
for (final AxolotlSession session : sessions) {
|
||||
final var cipherMessage = session.sessionCipher.encrypt(keyWithAuthTag);
|
||||
final var key = header.addExtension(new Key());
|
||||
key.setRemoteDeviceId(session.axolotlAddress.getDeviceId());
|
||||
key.setContent(cipherMessage.serialize());
|
||||
key.setIsPreKey(cipherMessage.getType() == CiphertextMessage.PREKEY_TYPE);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import im.conversations.android.xmpp.model.axolotl.Bundle;
|
|||
import im.conversations.android.xmpp.model.axolotl.DeviceList;
|
||||
import im.conversations.android.xmpp.model.axolotl.Encrypted;
|
||||
import im.conversations.android.xmpp.model.pubsub.Items;
|
||||
import im.conversations.android.xmpp.model.stanza.Message;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
|
@ -503,7 +504,40 @@ public class AxolotlManager extends AbstractManager implements AxolotlService.Po
|
|||
"fresh session from {}/{}",
|
||||
axolotlAddress.getJid(),
|
||||
axolotlAddress.getDeviceId());
|
||||
// After receiving an OMEMOKeyExchange and successfully building a new session, the
|
||||
// receiving device SHOULD automatically respond with an empty OMEMO message (as per
|
||||
// Sending a message) to the source of the OMEMOKeyExchange. This is to notify the
|
||||
// device that the session initiation was completed successfully and that the device can
|
||||
// stop sending OMEMOKeyExchanges.
|
||||
sendKeyTransportToCompleteSession(axolotlAddress);
|
||||
}
|
||||
// TODO republish device bundle
|
||||
}
|
||||
|
||||
private void sendKeyTransportToCompleteSession(final AxolotlAddress axolotlAddress) {
|
||||
final var existingSession = axolotlService.getExistingSession(axolotlAddress);
|
||||
if (existingSession == null) {
|
||||
return;
|
||||
}
|
||||
final Encrypted encrypted;
|
||||
try {
|
||||
encrypted =
|
||||
new EncryptionBuilder()
|
||||
.session(existingSession)
|
||||
.sourceDeviceId(signalProtocolStore().getLocalRegistrationId())
|
||||
.buildKeyTransport();
|
||||
} catch (final AxolotlEncryptionException e) {
|
||||
LOGGER.error("Could not create key transport message to complete session", e);
|
||||
return;
|
||||
}
|
||||
final var message = new Message(Message.Type.NORMAL);
|
||||
message.setTo(axolotlAddress.getJid());
|
||||
message.addExtension(encrypted);
|
||||
LOGGER.info(
|
||||
"Sending KeyTransport Message to {}/{}",
|
||||
axolotlAddress.getJid(),
|
||||
axolotlAddress.getDeviceId());
|
||||
connection.sendMessagePacket(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue