feat: Make any SPK survive exactly one rotation

This commit is contained in:
2022-08-08 15:48:09 +02:00
parent b8b6bbf800
commit 1bcbf27c83
3 changed files with 58 additions and 4 deletions

View File

@@ -24,3 +24,9 @@ class NotEncryptedForDeviceException implements Exception {
class NoDecryptionKeyException implements Exception {
String errMsg() => 'No key available for decrypting the message';
}
/// Triggered by the Session Manager when the identifier of the used Signed Prekey
/// is neither the current SPK's identifier nor the old one's.
class UnknownSignedPrekeyException implements Exception {
String errMsg() => 'Unknown Signed Prekey used.';
}

View File

@@ -156,27 +156,40 @@ class OmemoSessionManager {
return OmemoKeyExchange()
..pkId = kexResult.opkId
..spkId = 0
..spkId = bundle.spkId
..ik = await device.ik.pk.getBytes()
..ek = await kexResult.ek.pk.getBytes();
}
/// Build a new session with the user at [jid] with the device [deviceId] using data
/// from the key exchange [kex].
/// from the key exchange [kex]. In case [kex] contains an unknown Signed Prekey
/// identifier an UnknownSignedPrekeyException will be thrown.
Future<void> _addSessionFromKeyExchange(String jid, int deviceId, OmemoKeyExchange kex) async {
// Pick the correct SPK
final device = await getDevice();
OmemoKeyPair? spk;
if (kex.spkId == device.spkId) {
spk = device.spk;
} else if (kex.spkId == device.oldSpkId) {
spk = device.oldSpk;
} else {
throw UnknownSignedPrekeyException();
}
assert(spk != null, 'The used SPK must be found');
final kexResult = await x3dhFromInitialMessage(
X3DHMessage(
OmemoPublicKey.fromBytes(kex.ik!, KeyPairType.ed25519),
OmemoPublicKey.fromBytes(kex.ek!, KeyPairType.x25519),
kex.pkId!,
),
device.spk,
spk!,
device.opks.values.elementAt(kex.pkId!),
device.ik,
);
final ratchet = await OmemoDoubleRatchet.acceptNewSession(
device.spk,
spk,
OmemoPublicKey.fromBytes(kex.ik!, KeyPairType.ed25519),
kexResult.sk,
kexResult.ad,