mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2024-12-24 23:29:32 -05:00
crypto work
This commit is contained in:
parent
e04fd7ee77
commit
8a5af51ec7
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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()
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user