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
/// an Ed25519 key, but we need them as X25519 keys for DH.
Future<List<int>> omemoDH(
OmemoKeyPair kp, OmemoPublicKey pk, int identityKey,) async {
OmemoKeyPair kp,
OmemoPublicKey pk,
int identityKey,
) async {
var ckp = kp;
var cpk = pk;
@ -62,13 +65,19 @@ Future<HkdfKeyResult> deriveEncryptionKeys(List<int> input, String info) async {
final bytes = await result.extractBytes();
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
/// the encryption key and [iv] as the IV. Returns the ciphertext.
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(
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
/// the encryption key and [iv] as the IV. Returns the ciphertext.
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(
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.
/// Encrypt [plaintext] using the message key [mk], given associated_data [associatedData]
/// and the AD output from the X3DH [sessionAd].
Future<List<int>> encrypt(List<int> mk, List<int> plaintext,
List<int> associatedData, List<int> sessionAd,) async {
Future<List<int>> encrypt(
List<int> mk,
List<int> plaintext,
List<int> associatedData,
List<int> sessionAd,
) async {
// Generate encryption, authentication key and IV
final keys = await deriveEncryptionKeys(mk, encryptHkdfInfoString);
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.
/// Decrypt [ciphertext] with the message key [mk], given the associated_data [associatedData]
/// and the AD output from the X3DH.
Future<List<int>> decrypt(List<int> mk, List<int> ciphertext,
List<int> associatedData, List<int> sessionAd,) async {
Future<List<int>> decrypt(
List<int> mk,
List<int> ciphertext,
List<int> associatedData,
List<int> sessionAd,
) async {
// Generate encryption, authentication key and IV
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
/// 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.
static Future<OmemoDoubleRatchet> initiateNewSession(OmemoPublicKey spk,
OmemoPublicKey ik, List<int> sk, List<int> ad, int timestamp,) async {
static Future<OmemoDoubleRatchet> initiateNewSession(
OmemoPublicKey spk,
OmemoPublicKey ik,
List<int> sk,
List<int> ad,
int timestamp,
) async {
final dhs = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
final dhr = spk;
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
/// the associated data [ad] that was also obtained through a X3DH. [ik] refers to
/// Alice's (the initiator's) IK public key.
static Future<OmemoDoubleRatchet> acceptNewSession(OmemoKeyPair spk,
OmemoPublicKey ik, List<int> sk, List<int> ad, int kexTimestamp,) async {
static Future<OmemoDoubleRatchet> acceptNewSession(
OmemoKeyPair spk,
OmemoPublicKey ik,
List<int> sk,
List<int> ad,
int kexTimestamp,
) async {
return OmemoDoubleRatchet(
spk,
null,
@ -264,7 +274,9 @@ class OmemoDoubleRatchet {
}
Future<List<int>?> _trySkippedMessageKeys(
OmemoMessage header, List<int> ciphertext,) async {
OmemoMessage header,
List<int> ciphertext,
) async {
final key = SkippedKey(
OmemoPublicKey.fromBytes(header.dhPub!, KeyPairType.x25519),
header.n!,
@ -273,8 +285,12 @@ class OmemoDoubleRatchet {
final mk = mkSkipped[key]!;
mkSkipped.remove(key);
return decrypt(mk, ciphertext,
concat([sessionAd, header.writeToBuffer()]), sessionAd,);
return decrypt(
mk,
ciphertext,
concat([sessionAd, header.writeToBuffer()]),
sessionAd,
);
}
return null;
@ -326,8 +342,12 @@ class OmemoDoubleRatchet {
return RatchetStep(
header,
await encrypt(mk, plaintext, concat([sessionAd, header.writeToBuffer()]),
sessionAd,),
await encrypt(
mk,
plaintext,
concat([sessionAd, header.writeToBuffer()]),
sessionAd,
),
);
}
@ -336,7 +356,9 @@ class OmemoDoubleRatchet {
///
/// Throws an SkippingTooManyMessagesException if too many messages were to be skipped.
Future<List<int>> ratchetDecrypt(
OmemoMessage header, List<int> ciphertext,) async {
OmemoMessage header,
List<int> ciphertext,
) async {
// Check if we skipped too many messages
final plaintext = await _trySkippedMessageKeys(header, ciphertext);
if (plaintext != null) {
@ -359,7 +381,11 @@ class OmemoDoubleRatchet {
nr++;
return decrypt(
mk, ciphertext, concat([sessionAd, header.writeToBuffer()]), sessionAd,);
mk,
ciphertext,
concat([sessionAd, header.writeToBuffer()]),
sessionAd,
);
}
OmemoDoubleRatchet clone() {

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,12 @@ abstract class OmemoEvent {}
/// Triggered when a ratchet has been modified
class RatchetModifiedEvent extends OmemoEvent {
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 int deviceId;
final OmemoDoubleRatchet ratchet;

View File

@ -33,8 +33,10 @@ class _InternalDecryptionResult {
this.ratchetCreated,
this.ratchetReplaced,
this.payload,
) : assert(!ratchetCreated || !ratchetReplaced,
'Ratchet must be either replaced or created',);
) : assert(
!ratchetCreated || !ratchetReplaced,
'Ratchet must be either replaced or created',
);
final bool ratchetCreated;
final bool ratchetReplaced;
final String? payload;
@ -132,7 +134,9 @@ class OmemoManager {
}
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.
if (ciphertext == null) {
return null;
@ -149,7 +153,10 @@ class OmemoManager {
return utf8.decode(
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
/// identifier an UnknownSignedPrekeyException will be thrown.
Future<OmemoDoubleRatchet> _addSessionFromKeyExchange(
String jid, int deviceId, OmemoKeyExchange kex,) async {
String jid,
int deviceId,
OmemoKeyExchange kex,
) async {
// Pick the correct SPK
final device = await getDevice();
OmemoKeyPair spk;
@ -225,7 +235,10 @@ class OmemoManager {
/// [deviceId] from the bundle [bundle].
@visibleForTesting
Future<OmemoKeyExchange> addSessionFromBundle(
String jid, int deviceId, OmemoBundle bundle,) async {
String jid,
int deviceId,
OmemoBundle bundle,
) async {
final device = await getDevice();
final kexResult = await x3dhFromBundle(
bundle,
@ -255,7 +268,8 @@ class OmemoManager {
/// NOTE: Must be called from within the ratchet critical section
void _restoreRatchet(RatchetMapKey mapKey, OmemoDoubleRatchet oldRatchet) {
_log.finest(
'Restoring ratchet ${mapKey.jid}:${mapKey.deviceId} to ${oldRatchet.nr}',);
'Restoring ratchet ${mapKey.jid}:${mapKey.deviceId} to ${oldRatchet.nr}',
);
_ratchetMap[mapKey] = oldRatchet;
// Commit the ratchet
@ -287,7 +301,8 @@ class OmemoManager {
String senderJid,
int senderDeviceId,
List<EncryptedKey> keys,
int timestamp,) async {
int timestamp,
) async {
// Try to find a session we can decrypt with.
var device = await getDevice();
final rawKey = keys.firstWhereOrNull((key) => key.rid == device.id);
@ -312,7 +327,8 @@ class OmemoManager {
// Guard against old key exchanges
if (oldRatchet != null) {
_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) {
throw InvalidKeyExchangeException();
}
@ -461,7 +477,9 @@ class OmemoManager {
/// the result will be null as well.
/// NOTE: Must be called within the ratchet critical section
Future<EncryptionResult> _encryptToJids(
List<String> jids, String? plaintext,) async {
List<String> jids,
String? plaintext,
) async {
final encryptedKeys = List<EncryptedKey>.empty(growable: true);
var ciphertext = const <int>[];
@ -564,7 +582,8 @@ class OmemoManager {
} else {
// The ratchet is not acked but we don't have the old key exchange
_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(
EncryptedKey(
jid,
@ -632,7 +651,9 @@ class OmemoManager {
// Check if the ratchet is acked
final ratchet = getRatchet(ratchetKey);
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) {
// Ratchet is acknowledged
@ -704,8 +725,11 @@ class OmemoManager {
}
/// Mark the ratchet for device [deviceId] from [jid] as acked.
Future<void> ratchetAcknowledged(String jid, int deviceId,
{bool enterCriticalSection = true,}) async {
Future<void> ratchetAcknowledged(
String jid,
int deviceId, {
bool enterCriticalSection = true,
}) async {
if (enterCriticalSection) await _enterRatchetCriticalSection(jid);
final key = RatchetMapKey(jid, deviceId);
@ -717,7 +741,8 @@ class OmemoManager {
.add(RatchetModifiedEvent(jid, deviceId, ratchet, false, false));
} else {
_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);
@ -788,8 +813,10 @@ class OmemoManager {
_eventStreamController.add(DeviceListModifiedEvent(_deviceList));
}
void initialize(Map<RatchetMapKey, OmemoDoubleRatchet> ratchetMap,
Map<String, List<int>> deviceList,) {
void initialize(
Map<RatchetMapKey, OmemoDoubleRatchet> ratchetMap,
Map<String, List<int>> deviceList,
) {
_deviceList = deviceList;
_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].
Future<void> setDeviceTrust(
String jid, int deviceId, BTBVTrustState state,) async {
String jid,
int deviceId,
BTBVTrustState state,
) async {
await _lock.synchronized(() async {
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.
/// NOTE: This is needed as Dart cannot just cast a List<dynamic> to List<int> and so on.
static Map<RatchetMapKey, BTBVTrustState> trustCacheFromJson(
Map<String, dynamic> json,) {
Map<String, dynamic> json,
) {
return (json['trust']! as Map<String, dynamic>)
.map<RatchetMapKey, BTBVTrustState>(
(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.
/// NOTE: This is needed as Dart cannot just cast a List<dynamic> to List<int> and so on.
static Map<RatchetMapKey, bool> enableCacheFromJson(
Map<String, dynamic> json,) {
Map<String, dynamic> json,
) {
return (json['enable']! as Map<String, dynamic>).map<RatchetMapKey, bool>(
(key, value) => MapEntry(
RatchetMapKey.fromJsonKey(key),

View File

@ -37,7 +37,9 @@ class X3DHBobResult {
/// a Ed25519 keypair.
Future<List<int>> sig(OmemoKeyPair keyPair, List<int> message) async {
assert(
keyPair.type == KeyPairType.ed25519, 'Signature keypair must be Ed25519',);
keyPair.type == KeyPairType.ed25519,
'Signature keypair must be Ed25519',
);
final signature = await Ed25519().sign(
message,
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
/// pair [ik].
Future<X3DHAliceResult> x3dhFromBundle(
OmemoBundle bundle, OmemoKeyPair ik,) async {
OmemoBundle bundle,
OmemoKeyPair ik,
) async {
// Check the signature first
final signatureValue = await Ed25519().verify(
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
/// OPK [opk] that was selected by Alice and our IK [ik]. Returns the shared secret.
Future<X3DHBobResult> x3dhFromInitialMessage(X3DHMessage msg, OmemoKeyPair spk,
OmemoKeyPair opk, OmemoKeyPair ik,) async {
Future<X3DHBobResult> x3dhFromInitialMessage(
X3DHMessage msg,
OmemoKeyPair spk,
OmemoKeyPair opk,
OmemoKeyPair ik,
) async {
final dh1 = await omemoDH(spk, msg.ik, 2);
final dh2 = await omemoDH(ik, msg.ek, 1);
final dh3 = await omemoDH(spk, msg.ek, 0);

View File

@ -815,7 +815,8 @@ void main() {
expect(
aliceResult.jidEncryptionErrors[bobJid]
is NoKeyMaterialAvailableException,
true,);
true,
);
});
test('Test sending a message two two JIDs with failed lookups', () async {
@ -868,7 +869,8 @@ void main() {
expect(
aliceResult.jidEncryptionErrors[cocoJid]
is NoKeyMaterialAvailableException,
true,);
true,
);
// Bob decrypts it
final bobResult = await bobManager.onIncomingStanza(

View File

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