diff --git a/lib/repositories/local_accounts.g.dart b/lib/repositories/local_accounts.g.dart index 921ae8a..8bac7a7 100644 --- a/lib/repositories/local_accounts.g.dart +++ b/lib/repositories/local_accounts.g.dart @@ -6,7 +6,7 @@ part of 'local_accounts.dart'; // RiverpodGenerator // ************************************************************************** -String _$localAccountsHash() => r'a4ad015e192c5db8e59ba2b5e922109c34572095'; +String _$localAccountsHash() => r'27e90f03be60aa9f3d534456b5b697de669a20fe'; /// See also [LocalAccounts]. @ProviderFor(LocalAccounts) diff --git a/lib/tools/dht_record.dart b/lib/tools/dht_record.dart index 409d47f..5a8335f 100644 --- a/lib/tools/dht_record.dart +++ b/lib/tools/dht_record.dart @@ -13,7 +13,6 @@ class DHTRecord { static Future create(VeilidRoutingContext dhtctx, {DHTSchema schema = const DHTSchema.dflt(oCnt: 1), int defaultSubkey = 0, - KeyPair? writer, DHTRecordEncryptionFactory crypto = DHTRecordEncryption.private}) async { DHTRecordDescriptor recordDescriptor = await dhtctx.createDHTRecord(schema); @@ -21,33 +20,55 @@ class DHTRecord { dhtctx: dhtctx, recordDescriptor: recordDescriptor, defaultSubkey: defaultSubkey, - writer: writer); - final encryption = crypto) + writer: recordDescriptor.ownerKeyPair()); + + rec._encryption = crypto(rec); + + return rec; } - static Future open( - VeilidRoutingContext dhtctx, TypedKey recordKey, KeyPair? writer, + static Future openRead( + VeilidRoutingContext dhtctx, TypedKey recordKey, {int defaultSubkey = 0, - KeyPair? writer, - DHTRecordEncryptionFactory encrypt = DHTRecordEncryption.private}) async { + DHTRecordEncryptionFactory crypto = DHTRecordEncryption.private}) async { DHTRecordDescriptor recordDescriptor = - await dhtctx.openDHTRecord(recordKey, writer); - return DHTRecord( + await dhtctx.openDHTRecord(recordKey, null); + final rec = DHTRecord( dhtctx: dhtctx, recordDescriptor: recordDescriptor, - defaultSubkey: defaultSubkey); + defaultSubkey: defaultSubkey, + writer: null); + + rec._encryption = crypto(rec); + return rec; + } + + static Future openWrite( + VeilidRoutingContext dhtctx, TypedKey recordKey, KeyPair writer, + {int defaultSubkey = 0, + DHTRecordEncryptionFactory crypto = DHTRecordEncryption.private}) async { + DHTRecordDescriptor recordDescriptor = + await dhtctx.openDHTRecord(recordKey, writer); + final rec = DHTRecord( + dhtctx: dhtctx, + recordDescriptor: recordDescriptor, + defaultSubkey: defaultSubkey, + writer: writer); + rec._encryption = crypto(rec); + return rec; } DHTRecord( {required VeilidRoutingContext dhtctx, required DHTRecordDescriptor recordDescriptor, - int defaultSubkey = 0, KeyPair? writer}) + int defaultSubkey = 0, + KeyPair? writer}) : _dhtctx = dhtctx, _recordDescriptor = recordDescriptor, _defaultSubkey = defaultSubkey, _writer = writer; - int _subkey(int subkey) => (subkey == -1) ? _defaultSubkey : subkey; + int subkeyOrDefault(int subkey) => (subkey == -1) ? _defaultSubkey : subkey; TypedKey key() { return _recordDescriptor.key; @@ -58,11 +79,7 @@ class DHTRecord { } KeyPair? ownerKeyPair() { - final ownerSecret = _recordDescriptor.ownerSecret; - if (ownerSecret == null) { - return null; - } - return KeyPair(key: _recordDescriptor.owner, secret: ownerSecret); + return _recordDescriptor.ownerKeyPair(); } KeyPair? writer() { @@ -97,25 +114,27 @@ class DHTRecord { } Future get({int subkey = -1, bool forceRefresh = false}) async { - ValueData? valueData = await _dhtctx.getDHTValue( - _recordDescriptor.key, _subkey(subkey), false); + subkey = subkeyOrDefault(subkey); + ValueData? valueData = + await _dhtctx.getDHTValue(_recordDescriptor.key, subkey, false); if (valueData == null) { return null; } - return valueData.data; + return _encryption.decrypt(valueData.data, subkey); } Future getJson(T Function(Map) fromJson, {int subkey = -1, bool forceRefresh = false}) async { - ValueData? valueData = await _dhtctx.getDHTValue( - _recordDescriptor.key, _subkey(subkey), false); - if (valueData == null) { + final data = await get(subkey: subkey, forceRefresh: forceRefresh); + if (data == null) { return null; } - return valueData.readJsonData(fromJson); + return jsonDecodeBytes(fromJson, data); } Future eventualWriteBytes(Uint8List newValue, {int subkey = -1}) async { + subkey = subkeyOrDefault(subkey); + newValue = await _encryption.encrypt(newValue, subkey); // Get existing identity key ValueData? valueData; do { @@ -125,8 +144,8 @@ class DHTRecord { } // Set the new data - valueData = await _dhtctx.setDHTValue( - _recordDescriptor.key, _subkey(subkey), newValue); + valueData = + await _dhtctx.setDHTValue(_recordDescriptor.key, subkey, newValue); // Repeat if newer data on the network was found } while (valueData != null); @@ -135,9 +154,10 @@ class DHTRecord { Future eventualUpdateBytes( Future Function(Uint8List oldValue) update, {int subkey = -1}) async { + subkey = subkeyOrDefault(subkey); // Get existing identity key - ValueData? valueData = await _dhtctx.getDHTValue( - _recordDescriptor.key, _subkey(subkey), false); + ValueData? valueData = + await _dhtctx.getDHTValue(_recordDescriptor.key, subkey, false); do { // Ensure it exists already if (valueData == null) { @@ -145,11 +165,13 @@ class DHTRecord { } // Update the data - final newData = await update(valueData.data); + final oldData = await _encryption.decrypt(valueData.data, subkey); + final updatedData = await update(oldData); + final newData = await _encryption.encrypt(updatedData, subkey); // Set it back - valueData = await _dhtctx.setDHTValue( - _recordDescriptor.key, _subkey(subkey), newData); + valueData = + await _dhtctx.setDHTValue(_recordDescriptor.key, subkey, newData); // Repeat if newer data on the network was found } while (valueData != null); diff --git a/lib/tools/dht_record_encryption.dart b/lib/tools/dht_record_encryption.dart index b550673..9af778a 100644 --- a/lib/tools/dht_record_encryption.dart +++ b/lib/tools/dht_record_encryption.dart @@ -4,52 +4,50 @@ import 'package:veilid/veilid.dart'; import 'dart:typed_data'; import 'tools.dart'; -typedef DHTRecordEncryptionFactory = DHTRecordEncryption Function(); +typedef DHTRecordEncryptionFactory = DHTRecordEncryption Function(DHTRecord); abstract class DHTRecordEncryption { - factory DHTRecordEncryption.private() { - return DHTRecordEncryptionPrivate(); + factory DHTRecordEncryption.private(DHTRecord record) { + return _DHTRecordEncryptionPrivate(record); } - factory DHTRecordEncryption.public() { - return DHTRecordEncryptionPublic(); + factory DHTRecordEncryption.public(DHTRecord record) { + return _DHTRecordEncryptionPublic(record); } - FutureOr encrypt(Uint8List data); - FutureOr decrypt(Uint8List data); + FutureOr encrypt(Uint8List data, int subkey); + FutureOr decrypt(Uint8List data, int subkey); } //////////////////////////////////// /// Private DHT Record: Encrypted with the owner's secret key -class DHTRecordEncryptionPrivate implements DHTRecordEncryption { - DHTRecordEncryptionPrivate() { - // +class _DHTRecordEncryptionPrivate implements DHTRecordEncryption { + _DHTRecordEncryptionPrivate(DHTRecord record) { + // xxx derive key from record } @override - FutureOr encrypt(Uint8List data) { - // - } + FutureOr encrypt(Uint8List data, int subkey) {} @override - FutureOr decrypt(Uint8List data) { + FutureOr decrypt(Uint8List data, int subkey) { // } } //////////////////////////////////// /// Public DHT Record: No encryption -class DHTRecordEncryptionPublic implements DHTRecordEncryption { - DHTRecordEncryptionPublic() { +class _DHTRecordEncryptionPublic implements DHTRecordEncryption { + _DHTRecordEncryptionPublic(DHTRecord record) { // } @override - FutureOr encrypt(Uint8List data) { + FutureOr encrypt(Uint8List data, int subkey) { return data; } @override - FutureOr decrypt(Uint8List data) { + FutureOr decrypt(Uint8List data, int subkey) { return data; } } diff --git a/lib/tools/json_tools.dart b/lib/tools/json_tools.dart index a575253..6d9b85a 100644 --- a/lib/tools/json_tools.dart +++ b/lib/tools/json_tools.dart @@ -2,10 +2,9 @@ import 'package:veilid/veilid.dart'; import 'dart:typed_data'; import 'dart:convert'; -extension FromValueDataJsonExt on ValueData { - T readJsonData(T Function(Map) fromJson) { - return fromJson(jsonDecode(utf8.decode(data))); - } +T jsonDecodeBytes( + T Function(Map) fromJson, Uint8List data) { + return fromJson(jsonDecode(utf8.decode(data))); } Uint8List jsonEncodeBytes(Object? object, diff --git a/pubspec.lock b/pubspec.lock index bbd2743..d27e740 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -904,7 +904,7 @@ packages: path: "../veilid/veilid-flutter" relative: true source: path - version: "0.1.1" + version: "0.1.4" watcher: dependency: transitive description: