2022-08-03 13:29:13 +00:00
|
|
|
// ignore_for_file: avoid_print
|
2022-08-03 13:13:03 +00:00
|
|
|
import 'dart:convert';
|
|
|
|
import 'package:cryptography/cryptography.dart';
|
|
|
|
import 'package:omemo_dart/omemo_dart.dart';
|
|
|
|
import 'package:omemo_dart/protobuf/schema.pb.dart';
|
|
|
|
import 'package:omemo_dart/src/double_ratchet/crypto.dart';
|
|
|
|
import 'package:test/test.dart';
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
test('Test encrypting and decrypting', () async {
|
|
|
|
final sessionAd = List<int>.filled(32, 0x0);
|
|
|
|
final mk = List<int>.filled(32, 0x1);
|
|
|
|
final plaintext = utf8.encode('Hallo');
|
|
|
|
final header = OMEMOMessage()
|
|
|
|
..n = 0
|
|
|
|
..pn = 0
|
|
|
|
..dhPub = List<int>.empty();
|
|
|
|
final asd = concat([sessionAd, header.writeToBuffer()]);
|
2023-06-12 17:20:43 +00:00
|
|
|
|
2022-08-03 13:13:03 +00:00
|
|
|
final ciphertext = await encrypt(
|
|
|
|
mk,
|
|
|
|
plaintext,
|
|
|
|
asd,
|
|
|
|
sessionAd,
|
|
|
|
);
|
|
|
|
|
|
|
|
final decrypted = await decrypt(
|
|
|
|
mk,
|
|
|
|
ciphertext,
|
|
|
|
asd,
|
|
|
|
sessionAd,
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(decrypted, plaintext);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Test the Double Ratchet', () async {
|
|
|
|
// Generate keys
|
2022-08-08 12:44:05 +00:00
|
|
|
const bobJid = 'bob@other.example.server';
|
2022-08-03 13:13:03 +00:00
|
|
|
final ikAlice = await OmemoKeyPair.generateNewPair(KeyPairType.ed25519);
|
|
|
|
final ikBob = await OmemoKeyPair.generateNewPair(KeyPairType.ed25519);
|
|
|
|
final spkBob = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
|
|
|
|
final opkBob = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
|
|
|
|
final bundleBob = OmemoBundle(
|
2022-08-08 12:44:05 +00:00
|
|
|
bobJid,
|
2022-08-04 14:57:12 +00:00
|
|
|
1,
|
2022-08-03 13:13:03 +00:00
|
|
|
await spkBob.pk.asBase64(),
|
2022-08-04 14:57:12 +00:00
|
|
|
3,
|
2022-08-03 13:13:03 +00:00
|
|
|
base64Encode(
|
|
|
|
await sig(ikBob, await spkBob.pk.getBytes()),
|
|
|
|
),
|
|
|
|
//'Q5in+/L4kJixEX692h6mJkPMyp4I3SlQ84L0E7ipPzqfPHOMiraUlqG2vG/O8wvFjLsKYZpPBraga9IvwhqVDA==',
|
|
|
|
await ikBob.pk.asBase64(),
|
|
|
|
{
|
2022-08-04 14:57:12 +00:00
|
|
|
2: await opkBob.pk.asBase64(),
|
2022-08-03 13:13:03 +00:00
|
|
|
},
|
|
|
|
);
|
2023-06-12 17:20:43 +00:00
|
|
|
|
2022-08-03 13:13:03 +00:00
|
|
|
// Alice does X3DH
|
|
|
|
final resultAlice = await x3dhFromBundle(bundleBob, ikAlice);
|
|
|
|
|
|
|
|
// Alice sends the inital message to Bob
|
|
|
|
// ...
|
2023-06-12 17:20:43 +00:00
|
|
|
|
2022-08-03 13:13:03 +00:00
|
|
|
// Bob does X3DH
|
|
|
|
final resultBob = await x3dhFromInitialMessage(
|
|
|
|
X3DHMessage(
|
|
|
|
ikAlice.pk,
|
|
|
|
resultAlice.ek.pk,
|
2022-08-04 14:57:12 +00:00
|
|
|
2,
|
2022-08-03 13:13:03 +00:00
|
|
|
),
|
|
|
|
spkBob,
|
|
|
|
opkBob,
|
|
|
|
ikBob,
|
|
|
|
);
|
|
|
|
|
|
|
|
print('X3DH key exchange done');
|
|
|
|
|
|
|
|
// Alice and Bob now share sk as a common secret and ad
|
2022-08-03 14:32:39 +00:00
|
|
|
// Build a session
|
2022-08-03 13:13:03 +00:00
|
|
|
final alicesRatchet = await OmemoDoubleRatchet.initiateNewSession(
|
|
|
|
spkBob.pk,
|
2022-08-08 12:26:25 +00:00
|
|
|
ikBob.pk,
|
2022-08-03 13:13:03 +00:00
|
|
|
resultAlice.sk,
|
|
|
|
resultAlice.ad,
|
2022-10-02 12:56:20 +00:00
|
|
|
0,
|
2022-08-03 13:13:03 +00:00
|
|
|
);
|
|
|
|
final bobsRatchet = await OmemoDoubleRatchet.acceptNewSession(
|
|
|
|
spkBob,
|
2022-08-08 12:26:25 +00:00
|
|
|
ikAlice.pk,
|
2022-08-03 13:13:03 +00:00
|
|
|
resultBob.sk,
|
|
|
|
resultBob.ad,
|
2022-10-02 17:23:58 +00:00
|
|
|
0,
|
2022-08-03 13:13:03 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
expect(alicesRatchet.sessionAd, bobsRatchet.sessionAd);
|
|
|
|
|
2022-08-03 14:32:39 +00:00
|
|
|
for (var i = 0; i < 100; i++) {
|
|
|
|
final messageText = 'Hello, dear $i';
|
2023-06-12 17:20:43 +00:00
|
|
|
|
2022-08-03 14:33:22 +00:00
|
|
|
if (i.isEven) {
|
2022-08-03 14:32:39 +00:00
|
|
|
// Alice encrypts a message
|
2023-06-12 17:20:43 +00:00
|
|
|
final aliceRatchetResult =
|
|
|
|
await alicesRatchet.ratchetEncrypt(utf8.encode(messageText));
|
2022-08-03 14:32:39 +00:00
|
|
|
print('Alice sent the message');
|
2022-08-03 13:13:03 +00:00
|
|
|
|
2022-08-03 14:32:39 +00:00
|
|
|
// Alice sends it to Bob
|
|
|
|
// ...
|
2022-08-03 13:13:03 +00:00
|
|
|
|
2022-08-03 14:32:39 +00:00
|
|
|
// Bob tries to decrypt it
|
|
|
|
final bobRatchetResult = await bobsRatchet.ratchetDecrypt(
|
|
|
|
aliceRatchetResult.header,
|
|
|
|
aliceRatchetResult.ciphertext,
|
|
|
|
);
|
|
|
|
print('Bob decrypted the message');
|
2022-08-03 13:29:13 +00:00
|
|
|
|
2022-08-03 14:32:39 +00:00
|
|
|
expect(utf8.encode(messageText), bobRatchetResult);
|
|
|
|
} else {
|
|
|
|
// Bob sends a message to Alice
|
2023-06-12 17:20:43 +00:00
|
|
|
final bobRatchetResult =
|
|
|
|
await bobsRatchet.ratchetEncrypt(utf8.encode(messageText));
|
2022-08-03 14:32:39 +00:00
|
|
|
print('Bob sent the message');
|
2022-08-03 13:29:13 +00:00
|
|
|
|
2022-08-03 14:32:39 +00:00
|
|
|
// Bobs sends it to Alice
|
|
|
|
// ...
|
2022-08-03 13:29:13 +00:00
|
|
|
|
2022-08-03 14:32:39 +00:00
|
|
|
// Alice tries to decrypt it
|
|
|
|
final aliceRatchetResult = await alicesRatchet.ratchetDecrypt(
|
|
|
|
bobRatchetResult.header,
|
|
|
|
bobRatchetResult.ciphertext,
|
|
|
|
);
|
|
|
|
print('Alice decrypted the message');
|
2022-08-03 13:29:13 +00:00
|
|
|
|
2022-08-03 14:32:39 +00:00
|
|
|
expect(utf8.encode(messageText), aliceRatchetResult);
|
|
|
|
}
|
|
|
|
}
|
2022-08-03 13:13:03 +00:00
|
|
|
});
|
|
|
|
}
|