From 8a5af51ec7714d27a5480313a6591c292888ed28 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Mon, 27 May 2024 22:58:37 -0400 Subject: [PATCH] crypto work --- .../models/active_account_info.dart | 4 ++-- .../cubits/single_contact_messages_cubit.dart | 16 ++++++-------- .../cubits/contact_invitation_list_cubit.dart | 6 ++--- .../cubits/contact_request_inbox_cubit.dart | 8 +++---- .../home_account_ready_chat.dart | 6 ++--- .../src/dht_record/dht_record_pool.dart | 16 ++++++++++---- packages/veilid_support/lib/src/identity.dart | 11 +++++----- .../veilid_support/lib/src/veilid_crypto.dart | 22 ++++++++++++++----- 8 files changed, 53 insertions(+), 36 deletions(-) diff --git a/lib/account_manager/models/active_account_info.dart b/lib/account_manager/models/active_account_info.dart index 2997434..e4a5beb 100644 --- a/lib/account_manager/models/active_account_info.dart +++ b/lib/account_manager/models/active_account_info.dart @@ -33,8 +33,8 @@ class ActiveAccountInfo { identitySecret.value, utf8.encode('VeilidChat Conversation')); - final messagesCrypto = - await VeilidCryptoPrivate.fromSecret(identitySecret.kind, sharedSecret); + final messagesCrypto = await VeilidCryptoPrivate.fromSharedSecret( + identitySecret.kind, sharedSecret); return messagesCrypto; } diff --git a/lib/chat/cubits/single_contact_messages_cubit.dart b/lib/chat/cubits/single_contact_messages_cubit.dart index cf644f9..dc0e2d4 100644 --- a/lib/chat/cubits/single_contact_messages_cubit.dart +++ b/lib/chat/cubits/single_contact_messages_cubit.dart @@ -146,15 +146,13 @@ class SingleContactMessagesCubit extends Cubit { // Open reconciled chat record key Future _initReconciledMessagesCubit() async { - final accountRecordKey = - _activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey; + final tableName = _localConversationRecordKey.toString(); - _reconciledMessagesCubit = DHTLogCubit( - open: () async => DHTLog.openOwned(_reconciledChatRecord, - debugName: - 'SingleContactMessagesCubit::_initReconciledMessagesCubit::' - 'ReconciledMessages', - parent: accountRecordKey), + xxx whats the right encryption for reconciled messages cubit? + + final crypto = VeilidCryptoPrivate.fromTypedKey(kind, secretKey); + _reconciledMessagesCubit = TableDBArrayCubit( + open: () async => TableDBArray.make(table: tableName, crypto: crypto), decodeElement: proto.Message.fromBuffer); _reconciledSubscription = _reconciledMessagesCubit!.stream.listen(_updateReconciledMessagesState); @@ -461,7 +459,7 @@ class SingleContactMessagesCubit extends Cubit { DHTLogCubit? _sentMessagesCubit; DHTLogCubit? _rcvdMessagesCubit; - DHTLogCubit? _reconciledMessagesCubit; + TableDBArrayCubit? _reconciledMessagesCubit; late final PersistentQueue _unreconciledMessagesQueue; late final PersistentQueue _sendingMessagesQueue; diff --git a/lib/contact_invitation/cubits/contact_invitation_list_cubit.dart b/lib/contact_invitation/cubits/contact_invitation_list_cubit.dart index b76eaee..da1f6e3 100644 --- a/lib/contact_invitation/cubits/contact_invitation_list_cubit.dart +++ b/lib/contact_invitation/cubits/contact_invitation_list_cubit.dart @@ -129,9 +129,9 @@ class ContactInvitationListCubit await contactRequestInbox.eventualWriteBytes(Uint8List(0), subkey: 1, writer: contactRequestWriter, - crypto: await VeilidCryptoPrivate.fromTypedKeyPair( - TypedKeyPair.fromKeyPair( - contactRequestInbox.key.kind, contactRequestWriter))); + crypto: await DHTRecordPool.privateCryptoFromTypedSecret(TypedKey( + kind: contactRequestInbox.key.kind, + value: contactRequestWriter.secret))); // Create ContactInvitation and SignedContactInvitation final cinv = proto.ContactInvitation() diff --git a/lib/contact_invitation/cubits/contact_request_inbox_cubit.dart b/lib/contact_invitation/cubits/contact_request_inbox_cubit.dart index a4d0b8a..214d08b 100644 --- a/lib/contact_invitation/cubits/contact_request_inbox_cubit.dart +++ b/lib/contact_invitation/cubits/contact_request_inbox_cubit.dart @@ -28,16 +28,16 @@ class ContactRequestInboxCubit final pool = DHTRecordPool.instance; final accountRecordKey = activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey; - final writerKey = contactInvitationRecord.writerKey.toVeilid(); final writerSecret = contactInvitationRecord.writerSecret.toVeilid(); final recordKey = contactInvitationRecord.contactRequestInbox.recordKey.toVeilid(); - final writer = TypedKeyPair( - kind: recordKey.kind, key: writerKey, secret: writerSecret); + final writerTypedSecret = + TypedKey(kind: recordKey.kind, value: writerSecret); return pool.openRecordRead(recordKey, debugName: 'ContactRequestInboxCubit::_open::' 'ContactRequestInbox', - crypto: await VeilidCryptoPrivate.fromTypedKeyPair(writer), + crypto: + await DHTRecordPool.privateCryptoFromTypedSecret(writerTypedSecret), parent: accountRecordKey, defaultSubkey: 1); } diff --git a/lib/layout/home/home_account_ready/home_account_ready_chat.dart b/lib/layout/home/home_account_ready/home_account_ready_chat.dart index fb0e7b4..087bb34 100644 --- a/lib/layout/home/home_account_ready/home_account_ready_chat.dart +++ b/lib/layout/home/home_account_ready/home_account_ready_chat.dart @@ -28,13 +28,13 @@ class HomeAccountReadyChatState extends State { } Widget buildChatComponent(BuildContext context) { - final activeChatRemoteConversationKey = + final activeChatLocalConversationKey = context.watch().state; - if (activeChatRemoteConversationKey == null) { + if (activeChatLocalConversationKey == null) { return const EmptyChatWidget(); } return ChatComponent.builder( - localConversationRecordKey: activeChatRemoteConversationKey); + localConversationRecordKey: activeChatLocalConversationKey); } @override diff --git a/packages/veilid_support/lib/dht_support/src/dht_record/dht_record_pool.dart b/packages/veilid_support/lib/dht_support/src/dht_record/dht_record_pool.dart index 440698a..8b65d41 100644 --- a/packages/veilid_support/lib/dht_support/src/dht_record/dht_record_pool.dart +++ b/packages/veilid_support/lib/dht_support/src/dht_record/dht_record_pool.dart @@ -27,6 +27,9 @@ const int watchRenewalDenominator = 5; // Maximum number of concurrent DHT operations to perform on the network const int maxDHTConcurrency = 8; +// DHT crypto domain +const String cryptoDomainDHT = 'dht'; + typedef DHTRecordPoolLogger = void Function(String message); /// Record pool that managed DHTRecords and allows for tagged deletion @@ -547,9 +550,9 @@ class DHTRecordPool with TableDBBackedJson { writer: writer ?? openedRecordInfo.shared.recordDescriptor.ownerKeyPair(), crypto: crypto ?? - await VeilidCryptoPrivate.fromTypedKeyPair(openedRecordInfo + await privateCryptoFromTypedSecret(openedRecordInfo .shared.recordDescriptor - .ownerTypedKeyPair()!)); + .ownerTypedSecret()!)); openedRecordInfo.records.add(rec); @@ -612,8 +615,8 @@ class DHTRecordPool with TableDBBackedJson { writer: writer, sharedDHTRecordData: openedRecordInfo.shared, crypto: crypto ?? - await VeilidCryptoPrivate.fromTypedKeyPair( - TypedKeyPair.fromKeyPair(recordKey.kind, writer))); + await privateCryptoFromTypedSecret( + TypedKey(kind: recordKey.kind, value: writer.secret))); openedRecordInfo.records.add(rec); @@ -663,6 +666,11 @@ class DHTRecordPool with TableDBBackedJson { } } + /// Generate default VeilidCrypto for a writer + static Future privateCryptoFromTypedSecret( + TypedKey typedSecret) async => + VeilidCryptoPrivate.fromTypedKey(typedSecret, cryptoDomainDHT); + /// Handle the DHT record updates coming from Veilid void processRemoteValueChange(VeilidUpdateValueChange updateValueChange) { if (updateValueChange.subkeys.isNotEmpty) { diff --git a/packages/veilid_support/lib/src/identity.dart b/packages/veilid_support/lib/src/identity.dart index 400d68b..4666487 100644 --- a/packages/veilid_support/lib/src/identity.dart +++ b/packages/veilid_support/lib/src/identity.dart @@ -125,13 +125,14 @@ extension IdentityMasterExtension on IdentityMaster { } Future> readAccountsFromIdentity( - {required SharedSecret identitySecret, - required String accountKey}) async { + {required SecretKey identitySecret, required String accountKey}) async { // Read the identity key to get the account keys final pool = DHTRecordPool.instance; - final identityRecordCrypto = await VeilidCryptoPrivate.fromSecret( - identityRecordKey.kind, identitySecret); + final identityRecordCrypto = + await DHTRecordPool.privateCryptoFromTypedSecret( + TypedKey(kind: identityRecordKey.kind, value: identitySecret), + ); late final List accountRecordInfo; await (await pool.openRecordRead(identityRecordKey, @@ -157,7 +158,7 @@ extension IdentityMasterExtension on IdentityMaster { /// Creates a new Account associated with master identity and store it in the /// identity key. Future addAccountToIdentity({ - required SharedSecret identitySecret, + required SecretKey identitySecret, required String accountKey, required Future Function(TypedKey parent) createAccountCallback, int maxAccounts = 1, diff --git a/packages/veilid_support/lib/src/veilid_crypto.dart b/packages/veilid_support/lib/src/veilid_crypto.dart index 6965089..75087fb 100644 --- a/packages/veilid_support/lib/src/veilid_crypto.dart +++ b/packages/veilid_support/lib/src/veilid_crypto.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:typed_data'; import '../../../veilid_support.dart'; @@ -16,15 +17,24 @@ class VeilidCryptoPrivate implements VeilidCrypto { final VeilidCryptoSystem _cryptoSystem; final SharedSecret _secretKey; - static Future fromTypedKeyPair( - TypedKeyPair typedKeyPair) async { - final cryptoSystem = - await Veilid.instance.getCryptoSystem(typedKeyPair.kind); - final secretKey = typedKeyPair.secret; + static Future fromTypedKey( + TypedKey typedKey, String domain) async { + final cryptoSystem = await Veilid.instance.getCryptoSystem(typedKey.kind); + final keyMaterial = Uint8List(0) + ..addAll(typedKey.value.decode()) + ..addAll(utf8.encode(domain)); + final secretKey = await cryptoSystem.generateHash(keyMaterial); return VeilidCryptoPrivate._(cryptoSystem, secretKey); } - static Future fromSecret( + static Future fromTypedKeyPair( + TypedKeyPair typedKeyPair, String domain) async { + final typedSecret = + TypedKey(kind: typedKeyPair.kind, value: typedKeyPair.secret); + return fromTypedKey(typedSecret, domain); + } + + static Future fromSharedSecret( CryptoKind kind, SharedSecret secretKey) async { final cryptoSystem = await Veilid.instance.getCryptoSystem(kind); return VeilidCryptoPrivate._(cryptoSystem, secretKey);