crypto work

This commit is contained in:
Christien Rioux 2024-05-27 22:58:37 -04:00
parent e04fd7ee77
commit 8a5af51ec7
8 changed files with 53 additions and 36 deletions

View File

@ -33,8 +33,8 @@ class ActiveAccountInfo {
identitySecret.value, identitySecret.value,
utf8.encode('VeilidChat Conversation')); utf8.encode('VeilidChat Conversation'));
final messagesCrypto = final messagesCrypto = await VeilidCryptoPrivate.fromSharedSecret(
await VeilidCryptoPrivate.fromSecret(identitySecret.kind, sharedSecret); identitySecret.kind, sharedSecret);
return messagesCrypto; return messagesCrypto;
} }

View File

@ -146,15 +146,13 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
// Open reconciled chat record key // Open reconciled chat record key
Future<void> _initReconciledMessagesCubit() async { Future<void> _initReconciledMessagesCubit() async {
final accountRecordKey = final tableName = _localConversationRecordKey.toString();
_activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
_reconciledMessagesCubit = DHTLogCubit( xxx whats the right encryption for reconciled messages cubit?
open: () async => DHTLog.openOwned(_reconciledChatRecord,
debugName: final crypto = VeilidCryptoPrivate.fromTypedKey(kind, secretKey);
'SingleContactMessagesCubit::_initReconciledMessagesCubit::' _reconciledMessagesCubit = TableDBArrayCubit(
'ReconciledMessages', open: () async => TableDBArray.make(table: tableName, crypto: crypto),
parent: accountRecordKey),
decodeElement: proto.Message.fromBuffer); decodeElement: proto.Message.fromBuffer);
_reconciledSubscription = _reconciledSubscription =
_reconciledMessagesCubit!.stream.listen(_updateReconciledMessagesState); _reconciledMessagesCubit!.stream.listen(_updateReconciledMessagesState);
@ -461,7 +459,7 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
DHTLogCubit<proto.Message>? _sentMessagesCubit; DHTLogCubit<proto.Message>? _sentMessagesCubit;
DHTLogCubit<proto.Message>? _rcvdMessagesCubit; DHTLogCubit<proto.Message>? _rcvdMessagesCubit;
DHTLogCubit<proto.Message>? _reconciledMessagesCubit; TableDBArrayCubit<proto.Message>? _reconciledMessagesCubit;
late final PersistentQueue<proto.Message> _unreconciledMessagesQueue; late final PersistentQueue<proto.Message> _unreconciledMessagesQueue;
late final PersistentQueue<proto.Message> _sendingMessagesQueue; late final PersistentQueue<proto.Message> _sendingMessagesQueue;

View File

@ -129,9 +129,9 @@ class ContactInvitationListCubit
await contactRequestInbox.eventualWriteBytes(Uint8List(0), await contactRequestInbox.eventualWriteBytes(Uint8List(0),
subkey: 1, subkey: 1,
writer: contactRequestWriter, writer: contactRequestWriter,
crypto: await VeilidCryptoPrivate.fromTypedKeyPair( crypto: await DHTRecordPool.privateCryptoFromTypedSecret(TypedKey(
TypedKeyPair.fromKeyPair( kind: contactRequestInbox.key.kind,
contactRequestInbox.key.kind, contactRequestWriter))); value: contactRequestWriter.secret)));
// Create ContactInvitation and SignedContactInvitation // Create ContactInvitation and SignedContactInvitation
final cinv = proto.ContactInvitation() final cinv = proto.ContactInvitation()

View File

@ -28,16 +28,16 @@ class ContactRequestInboxCubit
final pool = DHTRecordPool.instance; final pool = DHTRecordPool.instance;
final accountRecordKey = final accountRecordKey =
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey; activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
final writerKey = contactInvitationRecord.writerKey.toVeilid();
final writerSecret = contactInvitationRecord.writerSecret.toVeilid(); final writerSecret = contactInvitationRecord.writerSecret.toVeilid();
final recordKey = final recordKey =
contactInvitationRecord.contactRequestInbox.recordKey.toVeilid(); contactInvitationRecord.contactRequestInbox.recordKey.toVeilid();
final writer = TypedKeyPair( final writerTypedSecret =
kind: recordKey.kind, key: writerKey, secret: writerSecret); TypedKey(kind: recordKey.kind, value: writerSecret);
return pool.openRecordRead(recordKey, return pool.openRecordRead(recordKey,
debugName: 'ContactRequestInboxCubit::_open::' debugName: 'ContactRequestInboxCubit::_open::'
'ContactRequestInbox', 'ContactRequestInbox',
crypto: await VeilidCryptoPrivate.fromTypedKeyPair(writer), crypto:
await DHTRecordPool.privateCryptoFromTypedSecret(writerTypedSecret),
parent: accountRecordKey, parent: accountRecordKey,
defaultSubkey: 1); defaultSubkey: 1);
} }

View File

@ -28,13 +28,13 @@ class HomeAccountReadyChatState extends State<HomeAccountReadyChat> {
} }
Widget buildChatComponent(BuildContext context) { Widget buildChatComponent(BuildContext context) {
final activeChatRemoteConversationKey = final activeChatLocalConversationKey =
context.watch<ActiveChatCubit>().state; context.watch<ActiveChatCubit>().state;
if (activeChatRemoteConversationKey == null) { if (activeChatLocalConversationKey == null) {
return const EmptyChatWidget(); return const EmptyChatWidget();
} }
return ChatComponent.builder( return ChatComponent.builder(
localConversationRecordKey: activeChatRemoteConversationKey); localConversationRecordKey: activeChatLocalConversationKey);
} }
@override @override

View File

@ -27,6 +27,9 @@ const int watchRenewalDenominator = 5;
// Maximum number of concurrent DHT operations to perform on the network // Maximum number of concurrent DHT operations to perform on the network
const int maxDHTConcurrency = 8; const int maxDHTConcurrency = 8;
// DHT crypto domain
const String cryptoDomainDHT = 'dht';
typedef DHTRecordPoolLogger = void Function(String message); typedef DHTRecordPoolLogger = void Function(String message);
/// Record pool that managed DHTRecords and allows for tagged deletion /// Record pool that managed DHTRecords and allows for tagged deletion
@ -547,9 +550,9 @@ class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
writer: writer ?? writer: writer ??
openedRecordInfo.shared.recordDescriptor.ownerKeyPair(), openedRecordInfo.shared.recordDescriptor.ownerKeyPair(),
crypto: crypto ?? crypto: crypto ??
await VeilidCryptoPrivate.fromTypedKeyPair(openedRecordInfo await privateCryptoFromTypedSecret(openedRecordInfo
.shared.recordDescriptor .shared.recordDescriptor
.ownerTypedKeyPair()!)); .ownerTypedSecret()!));
openedRecordInfo.records.add(rec); openedRecordInfo.records.add(rec);
@ -612,8 +615,8 @@ class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
writer: writer, writer: writer,
sharedDHTRecordData: openedRecordInfo.shared, sharedDHTRecordData: openedRecordInfo.shared,
crypto: crypto ?? crypto: crypto ??
await VeilidCryptoPrivate.fromTypedKeyPair( await privateCryptoFromTypedSecret(
TypedKeyPair.fromKeyPair(recordKey.kind, writer))); TypedKey(kind: recordKey.kind, value: writer.secret)));
openedRecordInfo.records.add(rec); openedRecordInfo.records.add(rec);
@ -663,6 +666,11 @@ class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
} }
} }
/// Generate default VeilidCrypto for a writer
static Future<VeilidCrypto> privateCryptoFromTypedSecret(
TypedKey typedSecret) async =>
VeilidCryptoPrivate.fromTypedKey(typedSecret, cryptoDomainDHT);
/// Handle the DHT record updates coming from Veilid /// Handle the DHT record updates coming from Veilid
void processRemoteValueChange(VeilidUpdateValueChange updateValueChange) { void processRemoteValueChange(VeilidUpdateValueChange updateValueChange) {
if (updateValueChange.subkeys.isNotEmpty) { if (updateValueChange.subkeys.isNotEmpty) {

View File

@ -125,13 +125,14 @@ extension IdentityMasterExtension on IdentityMaster {
} }
Future<List<AccountRecordInfo>> readAccountsFromIdentity( Future<List<AccountRecordInfo>> readAccountsFromIdentity(
{required SharedSecret identitySecret, {required SecretKey identitySecret, required String accountKey}) async {
required String accountKey}) async {
// Read the identity key to get the account keys // Read the identity key to get the account keys
final pool = DHTRecordPool.instance; final pool = DHTRecordPool.instance;
final identityRecordCrypto = await VeilidCryptoPrivate.fromSecret( final identityRecordCrypto =
identityRecordKey.kind, identitySecret); await DHTRecordPool.privateCryptoFromTypedSecret(
TypedKey(kind: identityRecordKey.kind, value: identitySecret),
);
late final List<AccountRecordInfo> accountRecordInfo; late final List<AccountRecordInfo> accountRecordInfo;
await (await pool.openRecordRead(identityRecordKey, 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 /// Creates a new Account associated with master identity and store it in the
/// identity key. /// identity key.
Future<AccountRecordInfo> addAccountToIdentity<T extends GeneratedMessage>({ Future<AccountRecordInfo> addAccountToIdentity<T extends GeneratedMessage>({
required SharedSecret identitySecret, required SecretKey identitySecret,
required String accountKey, required String accountKey,
required Future<T> Function(TypedKey parent) createAccountCallback, required Future<T> Function(TypedKey parent) createAccountCallback,
int maxAccounts = 1, int maxAccounts = 1,

View File

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import '../../../veilid_support.dart'; import '../../../veilid_support.dart';
@ -16,15 +17,24 @@ class VeilidCryptoPrivate implements VeilidCrypto {
final VeilidCryptoSystem _cryptoSystem; final VeilidCryptoSystem _cryptoSystem;
final SharedSecret _secretKey; final SharedSecret _secretKey;
static Future<VeilidCryptoPrivate> fromTypedKeyPair( static Future<VeilidCryptoPrivate> fromTypedKey(
TypedKeyPair typedKeyPair) async { TypedKey typedKey, String domain) async {
final cryptoSystem = final cryptoSystem = await Veilid.instance.getCryptoSystem(typedKey.kind);
await Veilid.instance.getCryptoSystem(typedKeyPair.kind); final keyMaterial = Uint8List(0)
final secretKey = typedKeyPair.secret; ..addAll(typedKey.value.decode())
..addAll(utf8.encode(domain));
final secretKey = await cryptoSystem.generateHash(keyMaterial);
return VeilidCryptoPrivate._(cryptoSystem, secretKey); return VeilidCryptoPrivate._(cryptoSystem, secretKey);
} }
static Future<VeilidCryptoPrivate> fromSecret( static Future<VeilidCryptoPrivate> fromTypedKeyPair(
TypedKeyPair typedKeyPair, String domain) async {
final typedSecret =
TypedKey(kind: typedKeyPair.kind, value: typedKeyPair.secret);
return fromTypedKey(typedSecret, domain);
}
static Future<VeilidCryptoPrivate> fromSharedSecret(
CryptoKind kind, SharedSecret secretKey) async { CryptoKind kind, SharedSecret secretKey) async {
final cryptoSystem = await Veilid.instance.getCryptoSystem(kind); final cryptoSystem = await Veilid.instance.getCryptoSystem(kind);
return VeilidCryptoPrivate._(cryptoSystem, secretKey); return VeilidCryptoPrivate._(cryptoSystem, secretKey);