fix: Fix receiving an old key exchange breaking decryption

This was mostly caused by Dart not copying values but referencing
them. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.

We know make some assumptions about received key exchanges, so this
needs some field testing.
This commit is contained in:
2022-10-02 14:56:20 +02:00
parent 7c3a9a75df
commit 2aa3674c4b
6 changed files with 125 additions and 97 deletions

View File

@@ -84,6 +84,7 @@ void main() {
ikBob.pk,
resultAlice.sk,
resultAlice.ad,
0,
);
final bobsRatchet = await OmemoDoubleRatchet.acceptNewSession(
spkBob,

View File

@@ -653,7 +653,7 @@ void main() {
expect(await bobRatchet1.equals(bobRatchet2), false);
});
test('Test receiving an old message that contains a KEX', () async {
test('Test receiving old messages including a KEX', () async {
const aliceJid = 'alice@server.example';
const bobJid = 'bob@other.server.example';
// Alice and Bob generate their sessions
@@ -668,6 +668,8 @@ void main() {
opkAmount: 2,
);
final bobsReceivedMessages = List<EncryptionResult>.empty(growable: true);
// Alice sends Bob a message
final msg1 = await aliceSession.encryptToJid(
bobJid,
@@ -676,7 +678,7 @@ void main() {
await bobSession.getDeviceBundle(),
],
);
bobsReceivedMessages.add(msg1);
await bobSession.decryptMessage(
msg1.ciphertext,
aliceJid,
@@ -696,90 +698,51 @@ void main() {
msg2.encryptedKeys,
);
// Due to some issue with the transport protocol, the first message Bob received is
// received again
try {
await bobSession.decryptMessage(
msg1.ciphertext,
// Send some messages between the two
for (var i = 0; i < 100; i++) {
final msg = await aliceSession.encryptToJid(
bobJid,
'Hello $i',
);
bobsReceivedMessages.add(msg);
final result = await bobSession.decryptMessage(
msg.ciphertext,
aliceJid,
await aliceSession.getDeviceId(),
msg1.encryptedKeys,
msg.encryptedKeys,
);
expect(true, false);
} on InvalidMessageHMACException {
// NOOP
expect(result, 'Hello $i');
}
final msg3 = await aliceSession.encryptToJid(
bobJid,
'Are you okay?',
);
final result = await bobSession.decryptMessage(
msg3.ciphertext,
aliceJid,
await aliceSession.getDeviceId(),
msg3.encryptedKeys,
);
expect(result, 'Are you okay?');
});
test('Test receiving an old message that does not contain a KEX', () async {
const aliceJid = 'alice@server.example';
const bobJid = 'bob@other.server.example';
// Alice and Bob generate their sessions
final aliceSession = await OmemoSessionManager.generateNewIdentity(
aliceJid,
AlwaysTrustingTrustManager(),
opkAmount: 1,
);
final bobSession = await OmemoSessionManager.generateNewIdentity(
bobJid,
AlwaysTrustingTrustManager(),
opkAmount: 2,
);
// Alice sends Bob a message
final msg1 = await aliceSession.encryptToJid(
bobJid,
'Hallo Welt',
newSessions: [
await bobSession.getDeviceBundle(),
],
);
await bobSession.decryptMessage(
msg1.ciphertext,
aliceJid,
await aliceSession.getDeviceId(),
msg1.encryptedKeys,
);
// Bob responds
final msg2 = await bobSession.encryptToJid(
aliceJid,
'Hello!',
);
await aliceSession.decryptMessage(
msg2.ciphertext,
bobJid,
await bobSession.getDeviceId(),
msg2.encryptedKeys,
);
// Due to some issue with the transport protocol, the first message Alice received is
// received again.
try {
await aliceSession.decryptMessage(
msg2.ciphertext,
bobJid,
await bobSession.getDeviceId(),
msg2.encryptedKeys,
);
expect(true, false);
} catch (_) {
// NOOP
// Due to some issue with the transport protocol, the messages to Bob are received
// again.
final ratchetPreError = bobSession
.getRatchet(aliceJid, await aliceSession.getDeviceId())
.clone();
var errorCounter = 0;
for (final msg in bobsReceivedMessages) {
try {
await bobSession.decryptMessage(
msg.ciphertext,
aliceJid,
await aliceSession.getDeviceId(),
msg.encryptedKeys,
);
expect(true, false);
} catch (_) {
errorCounter++;
}
}
final ratchetPostError = bobSession
.getRatchet(aliceJid, await aliceSession.getDeviceId())
.clone();
// The 100 messages including the initial KEX message
expect(errorCounter, 101);
expect(await ratchetPreError.equals(ratchetPostError), true);
final msg3 = await aliceSession.encryptToJid(
bobJid,
'Are you okay?',

View File

@@ -86,6 +86,7 @@ void main() {
'bob@localhost',
await bobSession.getDeviceId(),
await bobSession.getDeviceBundle(),
0,
);
// Serialise and deserialise