mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-09-24 14:28:30 -04:00
fix keys, upgrade lints
This commit is contained in:
parent
bcc246dd9c
commit
e44ff0a89d
10 changed files with 235 additions and 113 deletions
|
@ -18,7 +18,7 @@ dev_dependencies:
|
|||
async_tools: ^0.1.10
|
||||
integration_test:
|
||||
sdk: flutter
|
||||
lint_hard: ^6.0.0
|
||||
lint_hard: ^6.2.1
|
||||
test: ^1.25.15
|
||||
veilid_test:
|
||||
path: ../../../../veilid/veilid-flutter/packages/veilid_test
|
||||
|
|
|
@ -16,7 +16,7 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
required RecordKey recordKey,
|
||||
|
||||
// Public key of identity instance
|
||||
@JsonKey(name: 'publicKey') required BarePublicKey barePublicKey,
|
||||
@JsonKey(name: 'public_key') required BarePublicKey barePublicKey,
|
||||
|
||||
// Secret key of identity instance
|
||||
// Encrypted with appended salt, key is DeriveSharedSecret(
|
||||
|
@ -27,7 +27,7 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
|
||||
// Signature of SuperInstance recordKey and SuperInstance publicKey
|
||||
// by publicKey
|
||||
@JsonKey(name: 'superSignature') required BareSignature bareSuperSignature,
|
||||
@JsonKey(name: 'super_signature') required BareSignature bareSuperSignature,
|
||||
|
||||
// Signature of recordKey, publicKey, encryptedSecretKey, and superSignature
|
||||
// by SuperIdentity publicKey
|
||||
|
@ -42,25 +42,28 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// Public interface
|
||||
|
||||
Future<bool> validate(
|
||||
{required RecordKey superRecordKey,
|
||||
required PublicKey superPublicKey}) async {
|
||||
Future<bool> validate({
|
||||
required RecordKey superRecordKey,
|
||||
required PublicKey superPublicKey,
|
||||
}) async {
|
||||
final sigValid = await _validateIdentitySignature(
|
||||
recordKey: recordKey,
|
||||
barePublicKey: barePublicKey,
|
||||
encryptedSecretKey: encryptedSecretKey,
|
||||
bareSuperSignature: bareSuperSignature,
|
||||
superPublicKey: superPublicKey,
|
||||
signature: signature);
|
||||
recordKey: recordKey,
|
||||
barePublicKey: barePublicKey,
|
||||
encryptedSecretKey: encryptedSecretKey,
|
||||
bareSuperSignature: bareSuperSignature,
|
||||
superPublicKey: superPublicKey,
|
||||
signature: signature,
|
||||
);
|
||||
if (!sigValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final superSigValid = await _validateSuperSignature(
|
||||
superRecordKey: superRecordKey,
|
||||
superPublicKey: superPublicKey,
|
||||
publicKey: publicKey,
|
||||
superSignature: superSignature);
|
||||
superRecordKey: superRecordKey,
|
||||
superPublicKey: superPublicKey,
|
||||
publicKey: publicKey,
|
||||
superSignature: superSignature,
|
||||
);
|
||||
if (!superSigValid) {
|
||||
return false;
|
||||
}
|
||||
|
@ -86,21 +89,23 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
|
||||
/// Read the account record info for a specific applicationId from the
|
||||
/// identity instance record using the identity instance secret key to decrypt
|
||||
Future<List<AccountRecordInfo>> readAccount(
|
||||
{required RecordKey superRecordKey,
|
||||
required SecretKey secretKey,
|
||||
required String applicationId}) async {
|
||||
Future<List<AccountRecordInfo>> readAccount({
|
||||
required RecordKey superRecordKey,
|
||||
required SecretKey secretKey,
|
||||
required String applicationId,
|
||||
}) async {
|
||||
// Read the identity key to get the account keys
|
||||
final pool = DHTRecordPool.instance;
|
||||
|
||||
final identityRecordCrypto = await getPrivateCrypto(secretKey);
|
||||
|
||||
late final List<AccountRecordInfo> accountRecordInfo;
|
||||
await (await pool.openRecordRead(recordKey,
|
||||
debugName: 'IdentityInstance::readAccounts::IdentityRecord',
|
||||
parent: superRecordKey,
|
||||
crypto: identityRecordCrypto))
|
||||
.scope((identityRec) async {
|
||||
await (await pool.openRecordRead(
|
||||
recordKey,
|
||||
debugName: 'IdentityInstance::readAccounts::IdentityRecord',
|
||||
parent: superRecordKey,
|
||||
crypto: identityRecordCrypto,
|
||||
)).scope((identityRec) async {
|
||||
final identity = await identityRec.getJson(Identity.fromJson);
|
||||
if (identity == null) {
|
||||
// Identity could not be read or decrypted from DHT
|
||||
|
@ -130,17 +135,19 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
|
||||
// Open identity key for writing
|
||||
veilidLoggy.debug('Opening identity record');
|
||||
return (await pool.openRecordWrite(recordKey, writer(secretKey),
|
||||
debugName: 'IdentityInstance::addAccount::IdentityRecord',
|
||||
parent: superRecordKey))
|
||||
.scope((identityRec) async {
|
||||
return (await pool.openRecordWrite(
|
||||
recordKey,
|
||||
writer(secretKey),
|
||||
debugName: 'IdentityInstance::addAccount::IdentityRecord',
|
||||
parent: superRecordKey,
|
||||
)).scope((identityRec) async {
|
||||
// Create new account to insert into identity
|
||||
veilidLoggy.debug('Creating new account');
|
||||
return (await pool.createRecord(
|
||||
debugName:
|
||||
'IdentityInstance::addAccount::IdentityRecord::AccountRecord',
|
||||
parent: identityRec.key))
|
||||
.deleteScope((accountRec) async {
|
||||
debugName:
|
||||
'IdentityInstance::addAccount::IdentityRecord::AccountRecord',
|
||||
parent: identityRec.key,
|
||||
)).deleteScope((accountRec) async {
|
||||
final account = await createAccountCallback(accountRec.key);
|
||||
// Write account key
|
||||
veilidLoggy.debug('Writing account record');
|
||||
|
@ -148,13 +155,16 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
|
||||
// Update identity key to include account
|
||||
final newAccountRecordInfo = AccountRecordInfo(
|
||||
accountRecord: OwnedDHTRecordPointer(
|
||||
recordKey: accountRec.key,
|
||||
owner: accountRec.ownerKeyPair!.value));
|
||||
accountRecord: OwnedDHTRecordPointer(
|
||||
recordKey: accountRec.key,
|
||||
owner: accountRec.ownerKeyPair!.value,
|
||||
),
|
||||
);
|
||||
|
||||
veilidLoggy.debug('Updating identity with new account');
|
||||
await identityRec.eventualUpdateJson(Identity.fromJson,
|
||||
(oldIdentity) async {
|
||||
await identityRec.eventualUpdateJson(Identity.fromJson, (
|
||||
oldIdentity,
|
||||
) async {
|
||||
if (oldIdentity == null) {
|
||||
throw IdentityException.readError;
|
||||
}
|
||||
|
@ -182,8 +192,9 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
required SecretKey secretKey,
|
||||
required String applicationId,
|
||||
required Future<AccountRecordInfo?> Function(
|
||||
List<AccountRecordInfo> accountRecordInfos)
|
||||
removeAccountCallback,
|
||||
List<AccountRecordInfo> accountRecordInfos,
|
||||
)
|
||||
removeAccountCallback,
|
||||
}) async {
|
||||
final pool = DHTRecordPool.instance;
|
||||
|
||||
|
@ -191,15 +202,18 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
|
||||
// Open identity key for writing
|
||||
veilidLoggy.debug('Opening identity record');
|
||||
return (await pool.openRecordWrite(recordKey, writer(secretKey),
|
||||
debugName: 'IdentityInstance::addAccount::IdentityRecord',
|
||||
parent: superRecordKey))
|
||||
.scope((identityRec) async {
|
||||
return (await pool.openRecordWrite(
|
||||
recordKey,
|
||||
writer(secretKey),
|
||||
debugName: 'IdentityInstance::addAccount::IdentityRecord',
|
||||
parent: superRecordKey,
|
||||
)).scope((identityRec) async {
|
||||
try {
|
||||
// Update identity key to remove account
|
||||
veilidLoggy.debug('Updating identity to remove account');
|
||||
await identityRec.eventualUpdateJson(Identity.fromJson,
|
||||
(oldIdentity) async {
|
||||
await identityRec.eventualUpdateJson(Identity.fromJson, (
|
||||
oldIdentity,
|
||||
) async {
|
||||
if (oldIdentity == null) {
|
||||
throw IdentityException.readError;
|
||||
}
|
||||
|
@ -214,8 +228,9 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
if (toRemove == null) {
|
||||
throw IdentityException.cancelled;
|
||||
}
|
||||
final newAccountRecords =
|
||||
oldAccountRecords.remove(applicationId, toRemove).asIMap();
|
||||
final newAccountRecords = oldAccountRecords
|
||||
.remove(applicationId, toRemove)
|
||||
.asIMap();
|
||||
|
||||
return oldIdentity.copyWith(accountRecords: newAccountRecords);
|
||||
});
|
||||
|
@ -274,10 +289,11 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
}) async {
|
||||
final cs = await Veilid.instance.getCryptoSystem(recordKey.kind);
|
||||
final identitySigBytes = IdentityInstance._signatureBytes(
|
||||
recordKey: recordKey,
|
||||
barePublicKey: barePublicKey,
|
||||
encryptedSecretKey: encryptedSecretKey,
|
||||
bareSuperSignature: bareSuperSignature);
|
||||
recordKey: recordKey,
|
||||
barePublicKey: barePublicKey,
|
||||
encryptedSecretKey: encryptedSecretKey,
|
||||
bareSuperSignature: bareSuperSignature,
|
||||
);
|
||||
return cs.verify(superPublicKey, identitySigBytes, signature);
|
||||
}
|
||||
|
||||
|
@ -288,16 +304,21 @@ sealed class IdentityInstance with _$IdentityInstance {
|
|||
required Signature superSignature,
|
||||
required KeyPair superKeyPair,
|
||||
}) async {
|
||||
assert(publicKey.kind == recordKey.kind,
|
||||
'public key kind must match record kind');
|
||||
assert(superSignature.kind == recordKey.kind,
|
||||
'super signature kind must match record kind');
|
||||
assert(
|
||||
publicKey.kind == recordKey.kind,
|
||||
'public key kind must match record kind',
|
||||
);
|
||||
assert(
|
||||
superSignature.kind == recordKey.kind,
|
||||
'super signature kind must match record kind',
|
||||
);
|
||||
final cs = await Veilid.instance.getCryptoSystem(recordKey.kind);
|
||||
final identitySigBytes = _signatureBytes(
|
||||
recordKey: recordKey,
|
||||
barePublicKey: publicKey.value,
|
||||
encryptedSecretKey: encryptedSecretKey,
|
||||
bareSuperSignature: superSignature.value);
|
||||
recordKey: recordKey,
|
||||
barePublicKey: publicKey.value,
|
||||
encryptedSecretKey: encryptedSecretKey,
|
||||
bareSuperSignature: superSignature.value,
|
||||
);
|
||||
return cs.sign(superKeyPair.key, superKeyPair.secret, identitySigBytes);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,14 +17,14 @@ mixin _$IdentityInstance {
|
|||
|
||||
// Private DHT record storing identity account mapping
|
||||
RecordKey get recordKey;// Public key of identity instance
|
||||
@JsonKey(name: 'publicKey') BarePublicKey get barePublicKey;// Secret key of identity instance
|
||||
@JsonKey(name: 'public_key') BarePublicKey get barePublicKey;// Secret key of identity instance
|
||||
// Encrypted with appended salt, key is DeriveSharedSecret(
|
||||
// password = SuperIdentity.secret,
|
||||
// salt = publicKey)
|
||||
// Used to recover accounts without generating a new instance
|
||||
@Uint8ListJsonConverter() Uint8List get encryptedSecretKey;// Signature of SuperInstance recordKey and SuperInstance publicKey
|
||||
// by publicKey
|
||||
@JsonKey(name: 'superSignature') BareSignature get bareSuperSignature;// Signature of recordKey, publicKey, encryptedSecretKey, and superSignature
|
||||
@JsonKey(name: 'super_signature') BareSignature get bareSuperSignature;// Signature of recordKey, publicKey, encryptedSecretKey, and superSignature
|
||||
// by SuperIdentity publicKey
|
||||
@JsonKey(name: 'signature') BareSignature get bareSignature;
|
||||
/// Create a copy of IdentityInstance
|
||||
|
@ -59,7 +59,7 @@ abstract mixin class $IdentityInstanceCopyWith<$Res> {
|
|||
factory $IdentityInstanceCopyWith(IdentityInstance value, $Res Function(IdentityInstance) _then) = _$IdentityInstanceCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
RecordKey recordKey,@JsonKey(name: 'publicKey') BarePublicKey barePublicKey,@Uint8ListJsonConverter() Uint8List encryptedSecretKey,@JsonKey(name: 'superSignature') BareSignature bareSuperSignature,@JsonKey(name: 'signature') BareSignature bareSignature
|
||||
RecordKey recordKey,@JsonKey(name: 'public_key') BarePublicKey barePublicKey,@Uint8ListJsonConverter() Uint8List encryptedSecretKey,@JsonKey(name: 'super_signature') BareSignature bareSuperSignature,@JsonKey(name: 'signature') BareSignature bareSignature
|
||||
});
|
||||
|
||||
|
||||
|
@ -165,7 +165,7 @@ return $default(_that);case _:
|
|||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( RecordKey recordKey, @JsonKey(name: 'publicKey') BarePublicKey barePublicKey, @Uint8ListJsonConverter() Uint8List encryptedSecretKey, @JsonKey(name: 'superSignature') BareSignature bareSuperSignature, @JsonKey(name: 'signature') BareSignature bareSignature)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( RecordKey recordKey, @JsonKey(name: 'public_key') BarePublicKey barePublicKey, @Uint8ListJsonConverter() Uint8List encryptedSecretKey, @JsonKey(name: 'super_signature') BareSignature bareSuperSignature, @JsonKey(name: 'signature') BareSignature bareSignature)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _IdentityInstance() when $default != null:
|
||||
return $default(_that.recordKey,_that.barePublicKey,_that.encryptedSecretKey,_that.bareSuperSignature,_that.bareSignature);case _:
|
||||
|
@ -186,7 +186,7 @@ return $default(_that.recordKey,_that.barePublicKey,_that.encryptedSecretKey,_th
|
|||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( RecordKey recordKey, @JsonKey(name: 'publicKey') BarePublicKey barePublicKey, @Uint8ListJsonConverter() Uint8List encryptedSecretKey, @JsonKey(name: 'superSignature') BareSignature bareSuperSignature, @JsonKey(name: 'signature') BareSignature bareSignature) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( RecordKey recordKey, @JsonKey(name: 'public_key') BarePublicKey barePublicKey, @Uint8ListJsonConverter() Uint8List encryptedSecretKey, @JsonKey(name: 'super_signature') BareSignature bareSuperSignature, @JsonKey(name: 'signature') BareSignature bareSignature) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _IdentityInstance():
|
||||
return $default(_that.recordKey,_that.barePublicKey,_that.encryptedSecretKey,_that.bareSuperSignature,_that.bareSignature);}
|
||||
|
@ -203,7 +203,7 @@ return $default(_that.recordKey,_that.barePublicKey,_that.encryptedSecretKey,_th
|
|||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( RecordKey recordKey, @JsonKey(name: 'publicKey') BarePublicKey barePublicKey, @Uint8ListJsonConverter() Uint8List encryptedSecretKey, @JsonKey(name: 'superSignature') BareSignature bareSuperSignature, @JsonKey(name: 'signature') BareSignature bareSignature)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( RecordKey recordKey, @JsonKey(name: 'public_key') BarePublicKey barePublicKey, @Uint8ListJsonConverter() Uint8List encryptedSecretKey, @JsonKey(name: 'super_signature') BareSignature bareSuperSignature, @JsonKey(name: 'signature') BareSignature bareSignature)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _IdentityInstance() when $default != null:
|
||||
return $default(_that.recordKey,_that.barePublicKey,_that.encryptedSecretKey,_that.bareSuperSignature,_that.bareSignature);case _:
|
||||
|
@ -218,13 +218,13 @@ return $default(_that.recordKey,_that.barePublicKey,_that.encryptedSecretKey,_th
|
|||
@JsonSerializable()
|
||||
|
||||
class _IdentityInstance extends IdentityInstance {
|
||||
const _IdentityInstance({required this.recordKey, @JsonKey(name: 'publicKey') required this.barePublicKey, @Uint8ListJsonConverter() required this.encryptedSecretKey, @JsonKey(name: 'superSignature') required this.bareSuperSignature, @JsonKey(name: 'signature') required this.bareSignature}): super._();
|
||||
const _IdentityInstance({required this.recordKey, @JsonKey(name: 'public_key') required this.barePublicKey, @Uint8ListJsonConverter() required this.encryptedSecretKey, @JsonKey(name: 'super_signature') required this.bareSuperSignature, @JsonKey(name: 'signature') required this.bareSignature}): super._();
|
||||
factory _IdentityInstance.fromJson(Map<String, dynamic> json) => _$IdentityInstanceFromJson(json);
|
||||
|
||||
// Private DHT record storing identity account mapping
|
||||
@override final RecordKey recordKey;
|
||||
// Public key of identity instance
|
||||
@override@JsonKey(name: 'publicKey') final BarePublicKey barePublicKey;
|
||||
@override@JsonKey(name: 'public_key') final BarePublicKey barePublicKey;
|
||||
// Secret key of identity instance
|
||||
// Encrypted with appended salt, key is DeriveSharedSecret(
|
||||
// password = SuperIdentity.secret,
|
||||
|
@ -233,7 +233,7 @@ class _IdentityInstance extends IdentityInstance {
|
|||
@override@Uint8ListJsonConverter() final Uint8List encryptedSecretKey;
|
||||
// Signature of SuperInstance recordKey and SuperInstance publicKey
|
||||
// by publicKey
|
||||
@override@JsonKey(name: 'superSignature') final BareSignature bareSuperSignature;
|
||||
@override@JsonKey(name: 'super_signature') final BareSignature bareSuperSignature;
|
||||
// Signature of recordKey, publicKey, encryptedSecretKey, and superSignature
|
||||
// by SuperIdentity publicKey
|
||||
@override@JsonKey(name: 'signature') final BareSignature bareSignature;
|
||||
|
@ -271,7 +271,7 @@ abstract mixin class _$IdentityInstanceCopyWith<$Res> implements $IdentityInstan
|
|||
factory _$IdentityInstanceCopyWith(_IdentityInstance value, $Res Function(_IdentityInstance) _then) = __$IdentityInstanceCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
RecordKey recordKey,@JsonKey(name: 'publicKey') BarePublicKey barePublicKey,@Uint8ListJsonConverter() Uint8List encryptedSecretKey,@JsonKey(name: 'superSignature') BareSignature bareSuperSignature,@JsonKey(name: 'signature') BareSignature bareSignature
|
||||
RecordKey recordKey,@JsonKey(name: 'public_key') BarePublicKey barePublicKey,@Uint8ListJsonConverter() Uint8List encryptedSecretKey,@JsonKey(name: 'super_signature') BareSignature bareSuperSignature,@JsonKey(name: 'signature') BareSignature bareSignature
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -9,21 +9,21 @@ part of 'identity_instance.dart';
|
|||
_IdentityInstance _$IdentityInstanceFromJson(Map<String, dynamic> json) =>
|
||||
_IdentityInstance(
|
||||
recordKey: RecordKey.fromJson(json['record_key']),
|
||||
barePublicKey: BarePublicKey.fromJson(json['publicKey']),
|
||||
barePublicKey: BarePublicKey.fromJson(json['public_key']),
|
||||
encryptedSecretKey: const Uint8ListJsonConverter().fromJson(
|
||||
json['encrypted_secret_key'],
|
||||
),
|
||||
bareSuperSignature: BareSignature.fromJson(json['superSignature']),
|
||||
bareSuperSignature: BareSignature.fromJson(json['super_signature']),
|
||||
bareSignature: BareSignature.fromJson(json['signature']),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$IdentityInstanceToJson(_IdentityInstance instance) =>
|
||||
<String, dynamic>{
|
||||
'record_key': instance.recordKey.toJson(),
|
||||
'publicKey': instance.barePublicKey.toJson(),
|
||||
'public_key': instance.barePublicKey.toJson(),
|
||||
'encrypted_secret_key': const Uint8ListJsonConverter().toJson(
|
||||
instance.encryptedSecretKey,
|
||||
),
|
||||
'superSignature': instance.bareSuperSignature.toJson(),
|
||||
'super_signature': instance.bareSuperSignature.toJson(),
|
||||
'signature': instance.bareSignature.toJson(),
|
||||
};
|
||||
|
|
|
@ -34,7 +34,7 @@ sealed class SuperIdentity with _$SuperIdentity {
|
|||
/// Public key of the SuperIdentity used to sign identity keys for recovery
|
||||
/// This must match the owner of the superRecord DHT record and can not be
|
||||
/// changed without changing the record
|
||||
@JsonKey(name: 'publicKey') required BarePublicKey barePublicKey,
|
||||
@JsonKey(name: 'public_key') required BarePublicKey barePublicKey,
|
||||
|
||||
/// Current identity instance
|
||||
/// The most recently generated identity instance for this SuperIdentity
|
||||
|
@ -72,7 +72,9 @@ sealed class SuperIdentity with _$SuperIdentity {
|
|||
}
|
||||
// Validate current IdentityInstance
|
||||
if (!await currentInstance.validate(
|
||||
superRecordKey: superRecordKey, superPublicKey: publicKey)) {
|
||||
superRecordKey: superRecordKey,
|
||||
superPublicKey: publicKey,
|
||||
)) {
|
||||
// Invalid current IdentityInstance signature(s)
|
||||
throw IdentityException.invalid;
|
||||
}
|
||||
|
@ -80,38 +82,46 @@ sealed class SuperIdentity with _$SuperIdentity {
|
|||
// Validate deprecated IdentityInstances
|
||||
for (final deprecatedInstance in deprecatedInstances) {
|
||||
if (!await deprecatedInstance.validate(
|
||||
superRecordKey: superRecordKey, superPublicKey: publicKey)) {
|
||||
superRecordKey: superRecordKey,
|
||||
superPublicKey: publicKey,
|
||||
)) {
|
||||
// Invalid deprecated IdentityInstance signature(s)
|
||||
throw IdentityException.invalid;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate SuperIdentity
|
||||
final deprecatedInstancesSignatures =
|
||||
deprecatedInstances.map((x) => x.signature).toList();
|
||||
final deprecatedInstancesSignatures = deprecatedInstances
|
||||
.map((x) => x.signature)
|
||||
.toList();
|
||||
if (!await _validateSuperIdentitySignature(
|
||||
recordKey: recordKey,
|
||||
currentInstanceSignature: currentInstance.signature,
|
||||
deprecatedInstancesSignatures: deprecatedInstancesSignatures,
|
||||
deprecatedSuperRecordKeys: deprecatedSuperRecordKeys,
|
||||
publicKey: publicKey,
|
||||
signature: signature)) {
|
||||
recordKey: recordKey,
|
||||
currentInstanceSignature: currentInstance.signature,
|
||||
deprecatedInstancesSignatures: deprecatedInstancesSignatures,
|
||||
deprecatedSuperRecordKeys: deprecatedSuperRecordKeys,
|
||||
publicKey: publicKey,
|
||||
signature: signature,
|
||||
)) {
|
||||
// Invalid SuperIdentity signature
|
||||
throw IdentityException.invalid;
|
||||
}
|
||||
}
|
||||
|
||||
/// Opens an existing super identity, validates it, and returns it
|
||||
static Future<SuperIdentity?> open(
|
||||
{required RecordKey superRecordKey}) async {
|
||||
static Future<SuperIdentity?> open({
|
||||
required RecordKey superRecordKey,
|
||||
}) async {
|
||||
final pool = DHTRecordPool.instance;
|
||||
|
||||
// SuperIdentity DHT record is public/unencrypted
|
||||
return (await pool.openRecordRead(superRecordKey,
|
||||
debugName: 'SuperIdentity::openSuperIdentity::SuperIdentityRecord'))
|
||||
.deleteScope((superRec) async {
|
||||
final superIdentity = await superRec.getJson(SuperIdentity.fromJson,
|
||||
refreshMode: DHTRecordRefreshMode.network);
|
||||
return (await pool.openRecordRead(
|
||||
superRecordKey,
|
||||
debugName: 'SuperIdentity::openSuperIdentity::SuperIdentityRecord',
|
||||
)).deleteScope((superRec) async {
|
||||
final superIdentity = await superRec.getJson(
|
||||
SuperIdentity.fromJson,
|
||||
refreshMode: DHTRecordRefreshMode.network,
|
||||
);
|
||||
if (superIdentity == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -138,7 +148,9 @@ sealed class SuperIdentity with _$SuperIdentity {
|
|||
final kind = recordKey.kind;
|
||||
assert(secretKey.kind == kind, 'secretKey kind must match recordKey kind');
|
||||
return KeyPair.fromBareKeyPair(
|
||||
kind, BareKeyPair(key: barePublicKey, secret: secretKey.value));
|
||||
kind,
|
||||
BareKeyPair(key: barePublicKey, secret: secretKey.value),
|
||||
);
|
||||
}
|
||||
|
||||
PublicKey get publicKey =>
|
||||
|
@ -182,10 +194,11 @@ sealed class SuperIdentity with _$SuperIdentity {
|
|||
}) async {
|
||||
final cs = await Veilid.instance.getCryptoSystem(recordKey.kind);
|
||||
final sigBytes = SuperIdentity.signatureBytes(
|
||||
recordKey: recordKey,
|
||||
currentInstanceSignature: currentInstanceSignature,
|
||||
deprecatedInstancesSignatures: deprecatedInstancesSignatures,
|
||||
deprecatedSuperRecordKeys: deprecatedSuperRecordKeys);
|
||||
recordKey: recordKey,
|
||||
currentInstanceSignature: currentInstanceSignature,
|
||||
deprecatedInstancesSignatures: deprecatedInstancesSignatures,
|
||||
deprecatedSuperRecordKeys: deprecatedSuperRecordKeys,
|
||||
);
|
||||
return cs.verify(publicKey, sigBytes, signature);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ mixin _$SuperIdentity {
|
|||
RecordKey get recordKey;/// Public key of the SuperIdentity used to sign identity keys for recovery
|
||||
/// This must match the owner of the superRecord DHT record and can not be
|
||||
/// changed without changing the record
|
||||
@JsonKey(name: 'publicKey') BarePublicKey get barePublicKey;/// Current identity instance
|
||||
@JsonKey(name: 'public_key') BarePublicKey get barePublicKey;/// Current identity instance
|
||||
/// The most recently generated identity instance for this SuperIdentity
|
||||
IdentityInstance get currentInstance;/// Deprecated identity instances
|
||||
/// These may be compromised and should not be considered valid for
|
||||
|
@ -66,7 +66,7 @@ abstract mixin class $SuperIdentityCopyWith<$Res> {
|
|||
factory $SuperIdentityCopyWith(SuperIdentity value, $Res Function(SuperIdentity) _then) = _$SuperIdentityCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
RecordKey recordKey,@JsonKey(name: 'publicKey') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys,@JsonKey(name: 'signature') BareSignature bareSignature
|
||||
RecordKey recordKey,@JsonKey(name: 'public_key') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys,@JsonKey(name: 'signature') BareSignature bareSignature
|
||||
});
|
||||
|
||||
|
||||
|
@ -182,7 +182,7 @@ return $default(_that);case _:
|
|||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( RecordKey recordKey, @JsonKey(name: 'publicKey') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys, @JsonKey(name: 'signature') BareSignature bareSignature)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( RecordKey recordKey, @JsonKey(name: 'public_key') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys, @JsonKey(name: 'signature') BareSignature bareSignature)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SuperIdentity() when $default != null:
|
||||
return $default(_that.recordKey,_that.barePublicKey,_that.currentInstance,_that.deprecatedInstances,_that.deprecatedSuperRecordKeys,_that.bareSignature);case _:
|
||||
|
@ -203,7 +203,7 @@ return $default(_that.recordKey,_that.barePublicKey,_that.currentInstance,_that.
|
|||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( RecordKey recordKey, @JsonKey(name: 'publicKey') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys, @JsonKey(name: 'signature') BareSignature bareSignature) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( RecordKey recordKey, @JsonKey(name: 'public_key') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys, @JsonKey(name: 'signature') BareSignature bareSignature) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SuperIdentity():
|
||||
return $default(_that.recordKey,_that.barePublicKey,_that.currentInstance,_that.deprecatedInstances,_that.deprecatedSuperRecordKeys,_that.bareSignature);}
|
||||
|
@ -220,7 +220,7 @@ return $default(_that.recordKey,_that.barePublicKey,_that.currentInstance,_that.
|
|||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( RecordKey recordKey, @JsonKey(name: 'publicKey') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys, @JsonKey(name: 'signature') BareSignature bareSignature)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( RecordKey recordKey, @JsonKey(name: 'public_key') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys, @JsonKey(name: 'signature') BareSignature bareSignature)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SuperIdentity() when $default != null:
|
||||
return $default(_that.recordKey,_that.barePublicKey,_that.currentInstance,_that.deprecatedInstances,_that.deprecatedSuperRecordKeys,_that.bareSignature);case _:
|
||||
|
@ -235,7 +235,7 @@ return $default(_that.recordKey,_that.barePublicKey,_that.currentInstance,_that.
|
|||
|
||||
@JsonSerializable()
|
||||
class _SuperIdentity extends SuperIdentity {
|
||||
const _SuperIdentity({required this.recordKey, @JsonKey(name: 'publicKey') required this.barePublicKey, required this.currentInstance, required final List<IdentityInstance> deprecatedInstances, required final List<RecordKey> deprecatedSuperRecordKeys, @JsonKey(name: 'signature') required this.bareSignature}): _deprecatedInstances = deprecatedInstances,_deprecatedSuperRecordKeys = deprecatedSuperRecordKeys,super._();
|
||||
const _SuperIdentity({required this.recordKey, @JsonKey(name: 'public_key') required this.barePublicKey, required this.currentInstance, required final List<IdentityInstance> deprecatedInstances, required final List<RecordKey> deprecatedSuperRecordKeys, @JsonKey(name: 'signature') required this.bareSignature}): _deprecatedInstances = deprecatedInstances,_deprecatedSuperRecordKeys = deprecatedSuperRecordKeys,super._();
|
||||
factory _SuperIdentity.fromJson(Map<String, dynamic> json) => _$SuperIdentityFromJson(json);
|
||||
|
||||
/// Public DHT record storing this structure for account recovery
|
||||
|
@ -246,7 +246,7 @@ class _SuperIdentity extends SuperIdentity {
|
|||
/// Public key of the SuperIdentity used to sign identity keys for recovery
|
||||
/// This must match the owner of the superRecord DHT record and can not be
|
||||
/// changed without changing the record
|
||||
@override@JsonKey(name: 'publicKey') final BarePublicKey barePublicKey;
|
||||
@override@JsonKey(name: 'public_key') final BarePublicKey barePublicKey;
|
||||
/// Current identity instance
|
||||
/// The most recently generated identity instance for this SuperIdentity
|
||||
@override final IdentityInstance currentInstance;
|
||||
|
@ -314,7 +314,7 @@ abstract mixin class _$SuperIdentityCopyWith<$Res> implements $SuperIdentityCopy
|
|||
factory _$SuperIdentityCopyWith(_SuperIdentity value, $Res Function(_SuperIdentity) _then) = __$SuperIdentityCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
RecordKey recordKey,@JsonKey(name: 'publicKey') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys,@JsonKey(name: 'signature') BareSignature bareSignature
|
||||
RecordKey recordKey,@JsonKey(name: 'public_key') BarePublicKey barePublicKey, IdentityInstance currentInstance, List<IdentityInstance> deprecatedInstances, List<RecordKey> deprecatedSuperRecordKeys,@JsonKey(name: 'signature') BareSignature bareSignature
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ part of 'super_identity.dart';
|
|||
_SuperIdentity _$SuperIdentityFromJson(Map<String, dynamic> json) =>
|
||||
_SuperIdentity(
|
||||
recordKey: RecordKey.fromJson(json['record_key']),
|
||||
barePublicKey: BarePublicKey.fromJson(json['publicKey']),
|
||||
barePublicKey: BarePublicKey.fromJson(json['public_key']),
|
||||
currentInstance: IdentityInstance.fromJson(json['current_instance']),
|
||||
deprecatedInstances: (json['deprecated_instances'] as List<dynamic>)
|
||||
.map(IdentityInstance.fromJson)
|
||||
|
@ -24,7 +24,7 @@ _SuperIdentity _$SuperIdentityFromJson(Map<String, dynamic> json) =>
|
|||
Map<String, dynamic> _$SuperIdentityToJson(_SuperIdentity instance) =>
|
||||
<String, dynamic>{
|
||||
'record_key': instance.recordKey.toJson(),
|
||||
'publicKey': instance.barePublicKey.toJson(),
|
||||
'public_key': instance.barePublicKey.toJson(),
|
||||
'current_instance': instance.currentInstance.toJson(),
|
||||
'deprecated_instances': instance.deprecatedInstances
|
||||
.map((e) => e.toJson())
|
||||
|
|
|
@ -13,10 +13,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "974859dc0ff5f37bc4313244b3218c791810d03ab3470a579580279ba971a48d"
|
||||
sha256: f4ad0fea5f102201015c9aae9d93bc02f75dd9491529a8c21f88d17a8523d44c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.7.1"
|
||||
version: "7.6.0"
|
||||
analyzer_plugin:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer_plugin
|
||||
sha256: a5ab7590c27b779f3d4de67f31c4109dbe13dd7339f86461a6f2a8ab2594d8ce
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.4"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -169,6 +177,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
ci:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ci
|
||||
sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.0"
|
||||
cli_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -177,6 +193,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -217,6 +241,38 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
custom_lint:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: custom_lint
|
||||
sha256: "78085fbe842de7c5bef92de811ca81536968dbcbbcdac5c316711add2d15e796"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.0"
|
||||
custom_lint_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: custom_lint_builder
|
||||
sha256: cc5532d5733d4eccfccaaec6070a1926e9f21e613d93ad0927fad020b95c9e52
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.0"
|
||||
custom_lint_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: custom_lint_core
|
||||
sha256: cc4684d22ca05bf0a4a51127e19a8aea576b42079ed2bc9e956f11aaebe35dd1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.0"
|
||||
custom_lint_visitor:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: custom_lint_visitor
|
||||
sha256: "4a86a0d8415a91fbb8298d6ef03e9034dc8e323a599ddc4120a0e36c433983a2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0+7.7.0"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -323,6 +379,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
hotreloader:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hotreloader
|
||||
sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -383,10 +447,10 @@ packages:
|
|||
dependency: "direct dev"
|
||||
description:
|
||||
name: lint_hard
|
||||
sha256: "2073d4e83ac4e3f2b87cc615fff41abb5c2c5618e117edcd3d71f40f2186f4d5"
|
||||
sha256: "805771ca5131c1e798ec7e94eb557dc61d6dc1220246855196776f4ac7299446"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.1"
|
||||
version: "6.2.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -555,6 +619,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
rxdart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: rxdart
|
||||
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.28.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -632,6 +704,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sprintf
|
||||
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -728,6 +808,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -39,5 +39,5 @@ dev_dependencies:
|
|||
build_runner: ^2.4.15
|
||||
freezed: ^3.2.0
|
||||
json_serializable: ^6.9.4
|
||||
lint_hard: ^6.0.0
|
||||
lint_hard: ^6.2.1
|
||||
test: ^1.25.15
|
||||
|
|
|
@ -125,7 +125,7 @@ dev_dependencies:
|
|||
freezed: ^3.2.0
|
||||
icons_launcher: ^3.0.1
|
||||
json_serializable: ^6.9.4
|
||||
lint_hard: ^6.0.0
|
||||
lint_hard: ^6.2.1
|
||||
|
||||
flutter_native_splash:
|
||||
color: "#8588D0"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue