mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 07:48:40 +00:00
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
122 lines
3.8 KiB
Dart
122 lines
3.8 KiB
Dart
import 'dart:typed_data';
|
|
|
|
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
|
import 'package:mutex/mutex.dart';
|
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
|
import 'package:twonly/src/services/signal/consts.signal.dart';
|
|
import 'package:twonly/src/services/signal/prekeys.signal.dart';
|
|
import 'package:twonly/src/services/signal/utils.signal.dart';
|
|
import 'package:twonly/src/utils/log.dart';
|
|
|
|
/// This caused some troubles, so protection the encryption...
|
|
final lockingSignalEncryption = Mutex();
|
|
|
|
Future<CiphertextMessage?> signalEncryptMessage(
|
|
int target,
|
|
Uint8List plaintextContent,
|
|
) async {
|
|
return lockingSignalEncryption.protect<CiphertextMessage?>(() async {
|
|
try {
|
|
final signalStore = (await getSignalStore())!;
|
|
final address = SignalProtocolAddress(target.toString(), defaultDeviceId);
|
|
|
|
final session = SessionCipher.fromStore(signalStore, address);
|
|
|
|
final preKey = await getPreKeyByContactId(target);
|
|
final signedPreKey = await getSignedPreKeyByContactId(target);
|
|
|
|
if (signedPreKey != null) {
|
|
final sessionBuilder = SessionBuilder.fromSignalStore(
|
|
signalStore,
|
|
address,
|
|
);
|
|
|
|
ECPublicKey? tempPrePublicKey;
|
|
|
|
if (preKey != null) {
|
|
tempPrePublicKey = Curve.decodePoint(
|
|
DjbECPublicKey(
|
|
Uint8List.fromList(preKey.preKey),
|
|
).serialize(),
|
|
1,
|
|
);
|
|
}
|
|
|
|
final tempSignedPreKeyPublic = Curve.decodePoint(
|
|
DjbECPublicKey(Uint8List.fromList(signedPreKey.signedPreKey))
|
|
.serialize(),
|
|
1,
|
|
);
|
|
|
|
final tempSignedPreKeySignature = Uint8List.fromList(
|
|
signedPreKey.signedPreKeySignature,
|
|
);
|
|
|
|
final tempIdentityKey = await signalStore.getIdentity(address);
|
|
if (tempIdentityKey != null) {
|
|
final registrationId = await session.getRemoteRegistrationId();
|
|
final preKeyBundle = PreKeyBundle(
|
|
registrationId,
|
|
defaultDeviceId,
|
|
preKey?.preKeyId,
|
|
tempPrePublicKey,
|
|
signedPreKey.signedPreKeyId,
|
|
tempSignedPreKeyPublic,
|
|
tempSignedPreKeySignature,
|
|
tempIdentityKey,
|
|
);
|
|
|
|
try {
|
|
await sessionBuilder.processPreKeyBundle(preKeyBundle);
|
|
} catch (e) {
|
|
Log.error('could not process pre key bundle: $e');
|
|
}
|
|
} else {
|
|
Log.error('did not get the identity of the remote address');
|
|
}
|
|
}
|
|
return await session.encrypt(plaintextContent);
|
|
} catch (e) {
|
|
Log.error(e.toString());
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
|
|
Future<(EncryptedContent?, PlaintextContent_DecryptionErrorMessage_Type?)>
|
|
signalDecryptMessage(
|
|
int source,
|
|
Uint8List encryptedContentRaw,
|
|
int type,
|
|
) async {
|
|
try {
|
|
final session = SessionCipher.fromStore(
|
|
(await getSignalStore())!,
|
|
SignalProtocolAddress(source.toString(), defaultDeviceId),
|
|
);
|
|
|
|
Uint8List plaintext;
|
|
|
|
switch (type) {
|
|
case CiphertextMessage.prekeyType:
|
|
plaintext = await session.decrypt(
|
|
PreKeySignalMessage(encryptedContentRaw),
|
|
);
|
|
case CiphertextMessage.whisperType:
|
|
plaintext = await session.decryptFromSignal(
|
|
SignalMessage.fromSerialized(encryptedContentRaw),
|
|
);
|
|
default:
|
|
Log.error('Unknown Message Decryption Type: $type');
|
|
return (null, PlaintextContent_DecryptionErrorMessage_Type.UNKNOWN);
|
|
}
|
|
|
|
return (EncryptedContent.fromBuffer(plaintext), null);
|
|
} on InvalidKeyIdException catch (e) {
|
|
Log.warn(e);
|
|
return (null, PlaintextContent_DecryptionErrorMessage_Type.PREKEY_UNKNOWN);
|
|
} catch (e) {
|
|
Log.error(e);
|
|
return (null, PlaintextContent_DecryptionErrorMessage_Type.UNKNOWN);
|
|
}
|
|
}
|