style: Formattiing issues

This commit is contained in:
PapaTutuWawa 2023-06-12 19:37:45 +02:00
parent 3783ec6f13
commit 3376929c24
13 changed files with 188 additions and 71 deletions

View File

@ -7,7 +7,10 @@ import 'package:omemo_dart/src/keys.dart';
/// is the identity key. This is needed since the identity key pair/public key is /// is the identity key. This is needed since the identity key pair/public key is
/// an Ed25519 key, but we need them as X25519 keys for DH. /// an Ed25519 key, but we need them as X25519 keys for DH.
Future<List<int>> omemoDH( Future<List<int>> omemoDH(
OmemoKeyPair kp, OmemoPublicKey pk, int identityKey,) async { OmemoKeyPair kp,
OmemoPublicKey pk,
int identityKey,
) async {
var ckp = kp; var ckp = kp;
var cpk = pk; var cpk = pk;
@ -62,13 +65,19 @@ Future<HkdfKeyResult> deriveEncryptionKeys(List<int> input, String info) async {
final bytes = await result.extractBytes(); final bytes = await result.extractBytes();
return HkdfKeyResult( return HkdfKeyResult(
bytes.sublist(0, 32), bytes.sublist(32, 64), bytes.sublist(64, 80),); bytes.sublist(0, 32),
bytes.sublist(32, 64),
bytes.sublist(64, 80),
);
} }
/// A small helper function to make AES-256-CBC easier. Encrypt [plaintext] using [key] as /// A small helper function to make AES-256-CBC easier. Encrypt [plaintext] using [key] as
/// the encryption key and [iv] as the IV. Returns the ciphertext. /// the encryption key and [iv] as the IV. Returns the ciphertext.
Future<List<int>> aes256CbcEncrypt( Future<List<int>> aes256CbcEncrypt(
List<int> plaintext, List<int> key, List<int> iv,) async { List<int> plaintext,
List<int> key,
List<int> iv,
) async {
final algorithm = AesCbc.with256bits( final algorithm = AesCbc.with256bits(
macAlgorithm: MacAlgorithm.empty, macAlgorithm: MacAlgorithm.empty,
); );
@ -84,7 +93,10 @@ Future<List<int>> aes256CbcEncrypt(
/// A small helper function to make AES-256-CBC easier. Decrypt [ciphertext] using [key] as /// A small helper function to make AES-256-CBC easier. Decrypt [ciphertext] using [key] as
/// the encryption key and [iv] as the IV. Returns the ciphertext. /// the encryption key and [iv] as the IV. Returns the ciphertext.
Future<List<int>> aes256CbcDecrypt( Future<List<int>> aes256CbcDecrypt(
List<int> ciphertext, List<int> key, List<int> iv,) async { List<int> ciphertext,
List<int> key,
List<int> iv,
) async {
final algorithm = AesCbc.with256bits( final algorithm = AesCbc.with256bits(
macAlgorithm: MacAlgorithm.empty, macAlgorithm: MacAlgorithm.empty,
); );

View File

@ -10,8 +10,12 @@ const encryptHkdfInfoString = 'OMEMO Message Key Material';
/// Signals ENCRYPT function as specified by OMEMO 0.8.3. /// Signals ENCRYPT function as specified by OMEMO 0.8.3.
/// Encrypt [plaintext] using the message key [mk], given associated_data [associatedData] /// Encrypt [plaintext] using the message key [mk], given associated_data [associatedData]
/// and the AD output from the X3DH [sessionAd]. /// and the AD output from the X3DH [sessionAd].
Future<List<int>> encrypt(List<int> mk, List<int> plaintext, Future<List<int>> encrypt(
List<int> associatedData, List<int> sessionAd,) async { List<int> mk,
List<int> plaintext,
List<int> associatedData,
List<int> sessionAd,
) async {
// Generate encryption, authentication key and IV // Generate encryption, authentication key and IV
final keys = await deriveEncryptionKeys(mk, encryptHkdfInfoString); final keys = await deriveEncryptionKeys(mk, encryptHkdfInfoString);
final ciphertext = final ciphertext =
@ -32,8 +36,12 @@ Future<List<int>> encrypt(List<int> mk, List<int> plaintext,
/// Signals DECRYPT function as specified by OMEMO 0.8.3. /// Signals DECRYPT function as specified by OMEMO 0.8.3.
/// Decrypt [ciphertext] with the message key [mk], given the associated_data [associatedData] /// Decrypt [ciphertext] with the message key [mk], given the associated_data [associatedData]
/// and the AD output from the X3DH. /// and the AD output from the X3DH.
Future<List<int>> decrypt(List<int> mk, List<int> ciphertext, Future<List<int>> decrypt(
List<int> associatedData, List<int> sessionAd,) async { List<int> mk,
List<int> ciphertext,
List<int> associatedData,
List<int> sessionAd,
) async {
// Generate encryption, authentication key and IV // Generate encryption, authentication key and IV
final keys = await deriveEncryptionKeys(mk, encryptHkdfInfoString); final keys = await deriveEncryptionKeys(mk, encryptHkdfInfoString);

View File

@ -179,8 +179,13 @@ class OmemoDoubleRatchet {
/// Create an OMEMO session using the Signed Pre Key [spk], the shared secret [sk] that /// Create an OMEMO session using the Signed Pre Key [spk], the shared secret [sk] that
/// was obtained using a X3DH and the associated data [ad] that was also obtained through /// was obtained using a X3DH and the associated data [ad] that was also obtained through
/// a X3DH. [ik] refers to Bob's (the receiver's) IK public key. /// a X3DH. [ik] refers to Bob's (the receiver's) IK public key.
static Future<OmemoDoubleRatchet> initiateNewSession(OmemoPublicKey spk, static Future<OmemoDoubleRatchet> initiateNewSession(
OmemoPublicKey ik, List<int> sk, List<int> ad, int timestamp,) async { OmemoPublicKey spk,
OmemoPublicKey ik,
List<int> sk,
List<int> ad,
int timestamp,
) async {
final dhs = await OmemoKeyPair.generateNewPair(KeyPairType.x25519); final dhs = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
final dhr = spk; final dhr = spk;
final rk = await kdfRk(sk, await omemoDH(dhs, dhr, 0)); final rk = await kdfRk(sk, await omemoDH(dhs, dhr, 0));
@ -208,8 +213,13 @@ class OmemoDoubleRatchet {
/// Pre Key keypair [spk], the shared secret [sk] that was obtained through a X3DH and /// Pre Key keypair [spk], the shared secret [sk] that was obtained through a X3DH and
/// the associated data [ad] that was also obtained through a X3DH. [ik] refers to /// the associated data [ad] that was also obtained through a X3DH. [ik] refers to
/// Alice's (the initiator's) IK public key. /// Alice's (the initiator's) IK public key.
static Future<OmemoDoubleRatchet> acceptNewSession(OmemoKeyPair spk, static Future<OmemoDoubleRatchet> acceptNewSession(
OmemoPublicKey ik, List<int> sk, List<int> ad, int kexTimestamp,) async { OmemoKeyPair spk,
OmemoPublicKey ik,
List<int> sk,
List<int> ad,
int kexTimestamp,
) async {
return OmemoDoubleRatchet( return OmemoDoubleRatchet(
spk, spk,
null, null,
@ -264,7 +274,9 @@ class OmemoDoubleRatchet {
} }
Future<List<int>?> _trySkippedMessageKeys( Future<List<int>?> _trySkippedMessageKeys(
OmemoMessage header, List<int> ciphertext,) async { OmemoMessage header,
List<int> ciphertext,
) async {
final key = SkippedKey( final key = SkippedKey(
OmemoPublicKey.fromBytes(header.dhPub!, KeyPairType.x25519), OmemoPublicKey.fromBytes(header.dhPub!, KeyPairType.x25519),
header.n!, header.n!,
@ -273,8 +285,12 @@ class OmemoDoubleRatchet {
final mk = mkSkipped[key]!; final mk = mkSkipped[key]!;
mkSkipped.remove(key); mkSkipped.remove(key);
return decrypt(mk, ciphertext, return decrypt(
concat([sessionAd, header.writeToBuffer()]), sessionAd,); mk,
ciphertext,
concat([sessionAd, header.writeToBuffer()]),
sessionAd,
);
} }
return null; return null;
@ -326,8 +342,12 @@ class OmemoDoubleRatchet {
return RatchetStep( return RatchetStep(
header, header,
await encrypt(mk, plaintext, concat([sessionAd, header.writeToBuffer()]), await encrypt(
sessionAd,), mk,
plaintext,
concat([sessionAd, header.writeToBuffer()]),
sessionAd,
),
); );
} }
@ -336,7 +356,9 @@ class OmemoDoubleRatchet {
/// ///
/// Throws an SkippingTooManyMessagesException if too many messages were to be skipped. /// Throws an SkippingTooManyMessagesException if too many messages were to be skipped.
Future<List<int>> ratchetDecrypt( Future<List<int>> ratchetDecrypt(
OmemoMessage header, List<int> ciphertext,) async { OmemoMessage header,
List<int> ciphertext,
) async {
// Check if we skipped too many messages // Check if we skipped too many messages
final plaintext = await _trySkippedMessageKeys(header, ciphertext); final plaintext = await _trySkippedMessageKeys(header, ciphertext);
if (plaintext != null) { if (plaintext != null) {
@ -359,7 +381,11 @@ class OmemoDoubleRatchet {
nr++; nr++;
return decrypt( return decrypt(
mk, ciphertext, concat([sessionAd, header.writeToBuffer()]), sessionAd,); mk,
ciphertext,
concat([sessionAd, header.writeToBuffer()]),
sessionAd,
);
} }
OmemoDoubleRatchet clone() { OmemoDoubleRatchet clone() {

View File

@ -44,7 +44,10 @@ int generateRandom32BitNumber() {
} }
OmemoPublicKey? decodeKeyIfNotNull( OmemoPublicKey? decodeKeyIfNotNull(
Map<String, dynamic> map, String key, KeyPairType type,) { Map<String, dynamic> map,
String key,
KeyPairType type,
) {
if (map[key] == null) return null; if (map[key] == null) return null;
return OmemoPublicKey.fromBytes( return OmemoPublicKey.fromBytes(

View File

@ -31,8 +31,10 @@ class OmemoPublicKey {
Future<String> asBase64() async => base64Encode(_pubkey.bytes); Future<String> asBase64() async => base64Encode(_pubkey.bytes);
Future<OmemoPublicKey> toCurve25519() async { Future<OmemoPublicKey> toCurve25519() async {
assert(type == KeyPairType.ed25519, assert(
'Cannot convert non-Ed25519 public key to X25519',); type == KeyPairType.ed25519,
'Cannot convert non-Ed25519 public key to X25519',
);
final pkc = Uint8List(publicKeyLength); final pkc = Uint8List(publicKeyLength);
TweetNaClExt.crypto_sign_ed25519_pk_to_x25519_pk( TweetNaClExt.crypto_sign_ed25519_pk_to_x25519_pk(
@ -41,7 +43,8 @@ class OmemoPublicKey {
); );
return OmemoPublicKey( return OmemoPublicKey(
SimplePublicKey(List<int>.from(pkc), type: KeyPairType.x25519),); SimplePublicKey(List<int>.from(pkc), type: KeyPairType.x25519),
);
} }
SimplePublicKey asPublicKey() => _pubkey; SimplePublicKey asPublicKey() => _pubkey;
@ -64,8 +67,10 @@ class OmemoPrivateKey {
Future<List<int>> getBytes() async => _privkey; Future<List<int>> getBytes() async => _privkey;
Future<OmemoPrivateKey> toCurve25519() async { Future<OmemoPrivateKey> toCurve25519() async {
assert(type == KeyPairType.ed25519, assert(
'Cannot convert non-Ed25519 private key to X25519',); type == KeyPairType.ed25519,
'Cannot convert non-Ed25519 private key to X25519',
);
final skc = Uint8List(privateKeyLength); final skc = Uint8List(privateKeyLength);
TweetNaClExt.crypto_sign_ed25519_sk_to_x25519_sk( TweetNaClExt.crypto_sign_ed25519_sk_to_x25519_sk(
@ -93,7 +98,10 @@ class OmemoKeyPair {
/// Create an OmemoKeyPair just from a [type] and the bytes of the private and public /// Create an OmemoKeyPair just from a [type] and the bytes of the private and public
/// key. /// key.
factory OmemoKeyPair.fromBytes( factory OmemoKeyPair.fromBytes(
List<int> publicKey, List<int> privateKey, KeyPairType type,) { List<int> publicKey,
List<int> privateKey,
KeyPairType type,
) {
return OmemoKeyPair( return OmemoKeyPair(
OmemoPublicKey.fromBytes( OmemoPublicKey.fromBytes(
publicKey, publicKey,
@ -110,8 +118,10 @@ class OmemoKeyPair {
/// Generate a completely new random OmemoKeyPair of type [type]. [type] must be either /// Generate a completely new random OmemoKeyPair of type [type]. [type] must be either
/// KeyPairType.ed25519 or KeyPairType.x25519. /// KeyPairType.ed25519 or KeyPairType.x25519.
static Future<OmemoKeyPair> generateNewPair(KeyPairType type) async { static Future<OmemoKeyPair> generateNewPair(KeyPairType type) async {
assert(type == KeyPairType.ed25519 || type == KeyPairType.x25519, assert(
'Keypair must be either Ed25519 or X25519',); type == KeyPairType.ed25519 || type == KeyPairType.x25519,
'Keypair must be either Ed25519 or X25519',
);
SimpleKeyPair kp; SimpleKeyPair kp;
if (type == KeyPairType.ed25519) { if (type == KeyPairType.ed25519) {
@ -140,8 +150,10 @@ class OmemoKeyPair {
/// Return the bytes that comprise the public key. /// Return the bytes that comprise the public key.
Future<OmemoKeyPair> toCurve25519() async { Future<OmemoKeyPair> toCurve25519() async {
assert(type == KeyPairType.ed25519, assert(
'Cannot convert non-Ed25519 keypair to X25519',); type == KeyPairType.ed25519,
'Cannot convert non-Ed25519 keypair to X25519',
);
return OmemoKeyPair( return OmemoKeyPair(
await pk.toCurve25519(), await pk.toCurve25519(),

View File

@ -93,8 +93,10 @@ class OmemoDevice {
} }
/// Generate a completely new device, i.e. cryptographic identity. /// Generate a completely new device, i.e. cryptographic identity.
static Future<OmemoDevice> generateNewDevice(String jid, static Future<OmemoDevice> generateNewDevice(
{int opkAmount = 100,}) async { String jid, {
int opkAmount = 100,
}) async {
final id = generateRandom32BitNumber(); final id = generateRandom32BitNumber();
final ik = await OmemoKeyPair.generateNewPair(KeyPairType.ed25519); final ik = await OmemoKeyPair.generateNewPair(KeyPairType.ed25519);
final spk = await OmemoKeyPair.generateNewPair(KeyPairType.x25519); final spk = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);

View File

@ -5,8 +5,12 @@ import 'package:omemo_dart/src/omemo/ratchet_map_key.dart';
@immutable @immutable
class EncryptionResult { class EncryptionResult {
const EncryptionResult(this.ciphertext, this.encryptedKeys, const EncryptionResult(
this.deviceEncryptionErrors, this.jidEncryptionErrors,); this.ciphertext,
this.encryptedKeys,
this.deviceEncryptionErrors,
this.jidEncryptionErrors,
);
/// The actual message that was encrypted. /// The actual message that was encrypted.
final List<int>? ciphertext; final List<int>? ciphertext;

View File

@ -6,7 +6,12 @@ abstract class OmemoEvent {}
/// Triggered when a ratchet has been modified /// Triggered when a ratchet has been modified
class RatchetModifiedEvent extends OmemoEvent { class RatchetModifiedEvent extends OmemoEvent {
RatchetModifiedEvent( RatchetModifiedEvent(
this.jid, this.deviceId, this.ratchet, this.added, this.replaced,); this.jid,
this.deviceId,
this.ratchet,
this.added,
this.replaced,
);
final String jid; final String jid;
final int deviceId; final int deviceId;
final OmemoDoubleRatchet ratchet; final OmemoDoubleRatchet ratchet;

View File

@ -33,8 +33,10 @@ class _InternalDecryptionResult {
this.ratchetCreated, this.ratchetCreated,
this.ratchetReplaced, this.ratchetReplaced,
this.payload, this.payload,
) : assert(!ratchetCreated || !ratchetReplaced, ) : assert(
'Ratchet must be either replaced or created',); !ratchetCreated || !ratchetReplaced,
'Ratchet must be either replaced or created',
);
final bool ratchetCreated; final bool ratchetCreated;
final bool ratchetReplaced; final bool ratchetReplaced;
final String? payload; final String? payload;
@ -132,7 +134,9 @@ class OmemoManager {
} }
Future<String?> _decryptAndVerifyHmac( Future<String?> _decryptAndVerifyHmac(
List<int>? ciphertext, List<int> keyAndHmac,) async { List<int>? ciphertext,
List<int> keyAndHmac,
) async {
// Empty OMEMO messages should just have the key decrypted and/or session set up. // Empty OMEMO messages should just have the key decrypted and/or session set up.
if (ciphertext == null) { if (ciphertext == null) {
return null; return null;
@ -149,7 +153,10 @@ class OmemoManager {
return utf8.decode( return utf8.decode(
await aes256CbcDecrypt( await aes256CbcDecrypt(
ciphertext, derivedKeys.encryptionKey, derivedKeys.iv,), ciphertext,
derivedKeys.encryptionKey,
derivedKeys.iv,
),
); );
} }
@ -185,7 +192,10 @@ class OmemoManager {
/// from the key exchange [kex]. In case [kex] contains an unknown Signed Prekey /// from the key exchange [kex]. In case [kex] contains an unknown Signed Prekey
/// identifier an UnknownSignedPrekeyException will be thrown. /// identifier an UnknownSignedPrekeyException will be thrown.
Future<OmemoDoubleRatchet> _addSessionFromKeyExchange( Future<OmemoDoubleRatchet> _addSessionFromKeyExchange(
String jid, int deviceId, OmemoKeyExchange kex,) async { String jid,
int deviceId,
OmemoKeyExchange kex,
) async {
// Pick the correct SPK // Pick the correct SPK
final device = await getDevice(); final device = await getDevice();
OmemoKeyPair spk; OmemoKeyPair spk;
@ -225,7 +235,10 @@ class OmemoManager {
/// [deviceId] from the bundle [bundle]. /// [deviceId] from the bundle [bundle].
@visibleForTesting @visibleForTesting
Future<OmemoKeyExchange> addSessionFromBundle( Future<OmemoKeyExchange> addSessionFromBundle(
String jid, int deviceId, OmemoBundle bundle,) async { String jid,
int deviceId,
OmemoBundle bundle,
) async {
final device = await getDevice(); final device = await getDevice();
final kexResult = await x3dhFromBundle( final kexResult = await x3dhFromBundle(
bundle, bundle,
@ -255,7 +268,8 @@ class OmemoManager {
/// NOTE: Must be called from within the ratchet critical section /// NOTE: Must be called from within the ratchet critical section
void _restoreRatchet(RatchetMapKey mapKey, OmemoDoubleRatchet oldRatchet) { void _restoreRatchet(RatchetMapKey mapKey, OmemoDoubleRatchet oldRatchet) {
_log.finest( _log.finest(
'Restoring ratchet ${mapKey.jid}:${mapKey.deviceId} to ${oldRatchet.nr}',); 'Restoring ratchet ${mapKey.jid}:${mapKey.deviceId} to ${oldRatchet.nr}',
);
_ratchetMap[mapKey] = oldRatchet; _ratchetMap[mapKey] = oldRatchet;
// Commit the ratchet // Commit the ratchet
@ -283,11 +297,12 @@ class OmemoManager {
/// will return null as there is no message to be decrypted. This, however, is used /// will return null as there is no message to be decrypted. This, however, is used
/// to set up sessions or advance the ratchets. /// to set up sessions or advance the ratchets.
Future<_InternalDecryptionResult> _decryptMessage( Future<_InternalDecryptionResult> _decryptMessage(
List<int>? ciphertext, List<int>? ciphertext,
String senderJid, String senderJid,
int senderDeviceId, int senderDeviceId,
List<EncryptedKey> keys, List<EncryptedKey> keys,
int timestamp,) async { int timestamp,
) async {
// Try to find a session we can decrypt with. // Try to find a session we can decrypt with.
var device = await getDevice(); var device = await getDevice();
final rawKey = keys.firstWhereOrNull((key) => key.rid == device.id); final rawKey = keys.firstWhereOrNull((key) => key.rid == device.id);
@ -312,7 +327,8 @@ class OmemoManager {
// Guard against old key exchanges // Guard against old key exchanges
if (oldRatchet != null) { if (oldRatchet != null) {
_log.finest( _log.finest(
'KEX for existent ratchet ${ratchetKey.toJsonKey()}. ${oldRatchet.kexTimestamp} > $timestamp: ${oldRatchet.kexTimestamp > timestamp}',); 'KEX for existent ratchet ${ratchetKey.toJsonKey()}. ${oldRatchet.kexTimestamp} > $timestamp: ${oldRatchet.kexTimestamp > timestamp}',
);
if (oldRatchet.kexTimestamp > timestamp) { if (oldRatchet.kexTimestamp > timestamp) {
throw InvalidKeyExchangeException(); throw InvalidKeyExchangeException();
} }
@ -461,7 +477,9 @@ class OmemoManager {
/// the result will be null as well. /// the result will be null as well.
/// NOTE: Must be called within the ratchet critical section /// NOTE: Must be called within the ratchet critical section
Future<EncryptionResult> _encryptToJids( Future<EncryptionResult> _encryptToJids(
List<String> jids, String? plaintext,) async { List<String> jids,
String? plaintext,
) async {
final encryptedKeys = List<EncryptedKey>.empty(growable: true); final encryptedKeys = List<EncryptedKey>.empty(growable: true);
var ciphertext = const <int>[]; var ciphertext = const <int>[];
@ -564,7 +582,8 @@ class OmemoManager {
} else { } else {
// The ratchet is not acked but we don't have the old key exchange // The ratchet is not acked but we don't have the old key exchange
_log.warning( _log.warning(
'Ratchet for $jid:$deviceId is not acked but the kex attribute is null',); 'Ratchet for $jid:$deviceId is not acked but the kex attribute is null',
);
encryptedKeys.add( encryptedKeys.add(
EncryptedKey( EncryptedKey(
jid, jid,
@ -632,7 +651,9 @@ class OmemoManager {
// Check if the ratchet is acked // Check if the ratchet is acked
final ratchet = getRatchet(ratchetKey); final ratchet = getRatchet(ratchetKey);
assert( assert(
ratchet != null, 'We decrypted the message, so the ratchet must exist',); ratchet != null,
'We decrypted the message, so the ratchet must exist',
);
if (ratchet!.acknowledged) { if (ratchet!.acknowledged) {
// Ratchet is acknowledged // Ratchet is acknowledged
@ -704,8 +725,11 @@ class OmemoManager {
} }
/// Mark the ratchet for device [deviceId] from [jid] as acked. /// Mark the ratchet for device [deviceId] from [jid] as acked.
Future<void> ratchetAcknowledged(String jid, int deviceId, Future<void> ratchetAcknowledged(
{bool enterCriticalSection = true,}) async { String jid,
int deviceId, {
bool enterCriticalSection = true,
}) async {
if (enterCriticalSection) await _enterRatchetCriticalSection(jid); if (enterCriticalSection) await _enterRatchetCriticalSection(jid);
final key = RatchetMapKey(jid, deviceId); final key = RatchetMapKey(jid, deviceId);
@ -717,7 +741,8 @@ class OmemoManager {
.add(RatchetModifiedEvent(jid, deviceId, ratchet, false, false)); .add(RatchetModifiedEvent(jid, deviceId, ratchet, false, false));
} else { } else {
_log.severe( _log.severe(
'Attempted to acknowledge ratchet ${key.toJsonKey()}, even though it does not exist',); 'Attempted to acknowledge ratchet ${key.toJsonKey()}, even though it does not exist',
);
} }
if (enterCriticalSection) await _leaveRatchetCriticalSection(jid); if (enterCriticalSection) await _leaveRatchetCriticalSection(jid);
@ -788,8 +813,10 @@ class OmemoManager {
_eventStreamController.add(DeviceListModifiedEvent(_deviceList)); _eventStreamController.add(DeviceListModifiedEvent(_deviceList));
} }
void initialize(Map<RatchetMapKey, OmemoDoubleRatchet> ratchetMap, void initialize(
Map<String, List<int>> deviceList,) { Map<RatchetMapKey, OmemoDoubleRatchet> ratchetMap,
Map<String, List<int>> deviceList,
) {
_deviceList = deviceList; _deviceList = deviceList;
_ratchetMap = ratchetMap; _ratchetMap = ratchetMap;
} }

View File

@ -147,7 +147,10 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
/// Sets the trust of [jid]'s device with identifier [deviceId] to [state]. /// Sets the trust of [jid]'s device with identifier [deviceId] to [state].
Future<void> setDeviceTrust( Future<void> setDeviceTrust(
String jid, int deviceId, BTBVTrustState state,) async { String jid,
int deviceId,
BTBVTrustState state,
) async {
await _lock.synchronized(() async { await _lock.synchronized(() async {
trustCache[RatchetMapKey(jid, deviceId)] = state; trustCache[RatchetMapKey(jid, deviceId)] = state;
@ -205,7 +208,8 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
/// From a serialized version of a BTBV trust manager, extract the trust cache. /// From a serialized version of a BTBV trust manager, extract the trust cache.
/// NOTE: This is needed as Dart cannot just cast a List<dynamic> to List<int> and so on. /// NOTE: This is needed as Dart cannot just cast a List<dynamic> to List<int> and so on.
static Map<RatchetMapKey, BTBVTrustState> trustCacheFromJson( static Map<RatchetMapKey, BTBVTrustState> trustCacheFromJson(
Map<String, dynamic> json,) { Map<String, dynamic> json,
) {
return (json['trust']! as Map<String, dynamic>) return (json['trust']! as Map<String, dynamic>)
.map<RatchetMapKey, BTBVTrustState>( .map<RatchetMapKey, BTBVTrustState>(
(key, value) => MapEntry( (key, value) => MapEntry(
@ -218,7 +222,8 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
/// From a serialized version of a BTBV trust manager, extract the enable cache. /// From a serialized version of a BTBV trust manager, extract the enable cache.
/// NOTE: This is needed as Dart cannot just cast a List<dynamic> to List<int> and so on. /// NOTE: This is needed as Dart cannot just cast a List<dynamic> to List<int> and so on.
static Map<RatchetMapKey, bool> enableCacheFromJson( static Map<RatchetMapKey, bool> enableCacheFromJson(
Map<String, dynamic> json,) { Map<String, dynamic> json,
) {
return (json['enable']! as Map<String, dynamic>).map<RatchetMapKey, bool>( return (json['enable']! as Map<String, dynamic>).map<RatchetMapKey, bool>(
(key, value) => MapEntry( (key, value) => MapEntry(
RatchetMapKey.fromJsonKey(key), RatchetMapKey.fromJsonKey(key),

View File

@ -37,7 +37,9 @@ class X3DHBobResult {
/// a Ed25519 keypair. /// a Ed25519 keypair.
Future<List<int>> sig(OmemoKeyPair keyPair, List<int> message) async { Future<List<int>> sig(OmemoKeyPair keyPair, List<int> message) async {
assert( assert(
keyPair.type == KeyPairType.ed25519, 'Signature keypair must be Ed25519',); keyPair.type == KeyPairType.ed25519,
'Signature keypair must be Ed25519',
);
final signature = await Ed25519().sign( final signature = await Ed25519().sign(
message, message,
keyPair: await keyPair.asKeyPair(), keyPair: await keyPair.asKeyPair(),
@ -69,7 +71,9 @@ Future<List<int>> kdf(List<int> km) async {
/// Alice builds a session with Bob using his bundle [bundle] and Alice's identity key /// Alice builds a session with Bob using his bundle [bundle] and Alice's identity key
/// pair [ik]. /// pair [ik].
Future<X3DHAliceResult> x3dhFromBundle( Future<X3DHAliceResult> x3dhFromBundle(
OmemoBundle bundle, OmemoKeyPair ik,) async { OmemoBundle bundle,
OmemoKeyPair ik,
) async {
// Check the signature first // Check the signature first
final signatureValue = await Ed25519().verify( final signatureValue = await Ed25519().verify(
await bundle.spk.getBytes(), await bundle.spk.getBytes(),
@ -107,8 +111,12 @@ Future<X3DHAliceResult> x3dhFromBundle(
/// Bob builds the X3DH shared secret from the inital message [msg], the SPK [spk], the /// Bob builds the X3DH shared secret from the inital message [msg], the SPK [spk], the
/// OPK [opk] that was selected by Alice and our IK [ik]. Returns the shared secret. /// OPK [opk] that was selected by Alice and our IK [ik]. Returns the shared secret.
Future<X3DHBobResult> x3dhFromInitialMessage(X3DHMessage msg, OmemoKeyPair spk, Future<X3DHBobResult> x3dhFromInitialMessage(
OmemoKeyPair opk, OmemoKeyPair ik,) async { X3DHMessage msg,
OmemoKeyPair spk,
OmemoKeyPair opk,
OmemoKeyPair ik,
) async {
final dh1 = await omemoDH(spk, msg.ik, 2); final dh1 = await omemoDH(spk, msg.ik, 2);
final dh2 = await omemoDH(ik, msg.ek, 1); final dh2 = await omemoDH(ik, msg.ek, 1);
final dh3 = await omemoDH(spk, msg.ek, 0); final dh3 = await omemoDH(spk, msg.ek, 0);

View File

@ -813,9 +813,10 @@ void main() {
expect(aliceResult.isSuccess(1), false); expect(aliceResult.isSuccess(1), false);
expect( expect(
aliceResult.jidEncryptionErrors[bobJid] aliceResult.jidEncryptionErrors[bobJid]
is NoKeyMaterialAvailableException, is NoKeyMaterialAvailableException,
true,); true,
);
}); });
test('Test sending a message two two JIDs with failed lookups', () async { test('Test sending a message two two JIDs with failed lookups', () async {
@ -866,9 +867,10 @@ void main() {
expect(aliceResult.isSuccess(2), true); expect(aliceResult.isSuccess(2), true);
expect( expect(
aliceResult.jidEncryptionErrors[cocoJid] aliceResult.jidEncryptionErrors[cocoJid]
is NoKeyMaterialAvailableException, is NoKeyMaterialAvailableException,
true,); true,
);
// Bob decrypts it // Bob decrypts it
final bobResult = await bobManager.onIncomingStanza( final bobResult = await bobManager.onIncomingStanza(

View File

@ -73,8 +73,11 @@ void main() {
await x3dhFromBundle(bundleBob, ikAlice); await x3dhFromBundle(bundleBob, ikAlice);
} catch (e) { } catch (e) {
exception = true; exception = true;
expect(e is InvalidSignatureException, true, expect(
reason: 'Expected InvalidSignatureException, but got $e',); e is InvalidSignatureException,
true,
reason: 'Expected InvalidSignatureException, but got $e',
);
} }
expect(exception, true, reason: 'Expected test failure'); expect(exception, true, reason: 'Expected test failure');