diff --git a/melos.yaml b/melos.yaml index 184069bc2..a260d4028 100644 --- a/melos.yaml +++ b/melos.yaml @@ -1,7 +1,6 @@ name: at_client_sdk packages: - - packages/* + - packages/at_client_mobile - packages/*/example - - tests/* diff --git a/packages/at_client/CHANGELOG.md b/packages/at_client/CHANGELOG.md index dcf0e9346..0066a0dd6 100644 --- a/packages/at_client/CHANGELOG.md +++ b/packages/at_client/CHANGELOG.md @@ -1,3 +1,10 @@ +# 3.0.72 +- build[deps]: Upgraded dependencies for the following packages: + - at_commons to v4.0.0 + - at_utils to v3.0.16 + - at_lookup to v3.0.44 + - at_chops to v1.0.7 + - at_persistence_secondary_server to v3.0.60 ## 3.0.71 - feat: Replace decryption methods from EncryptionUtil with AtChops methods ## 3.0.70 diff --git a/packages/at_client/lib/src/at_collection/impl/collection_methods_impl.dart b/packages/at_client/lib/src/at_collection/impl/collection_methods_impl.dart index 20d94f462..139b30c4d 100644 --- a/packages/at_client/lib/src/at_collection/impl/collection_methods_impl.dart +++ b/packages/at_client/lib/src/at_collection/impl/collection_methods_impl.dart @@ -41,7 +41,7 @@ class AtCollectionMethodImpl { _logger.finest('Self key to be used : $atKey'); var atOperationItemStatus = AtOperationItemStatus( atSign: atKey.sharedBy ?? '', - key: atKey.key ?? '', + key: atKey.key, complete: false, operation: Operation.save); try { @@ -76,7 +76,7 @@ class AtCollectionMethodImpl { _logger.finest('Update shared key $sharedKey'); var atOperationItemStatus = AtOperationItemStatus( atSign: sharedKey.sharedWith ?? '', - key: sharedKey.key ?? '', + key: sharedKey.key, complete: false, operation: Operation.share); try { @@ -133,7 +133,7 @@ class AtCollectionMethodImpl { var atOperationItemStatus = AtOperationItemStatus( atSign: atSign, - key: selfKey.key ?? '', + key: selfKey.key, complete: false, operation: Operation.share); @@ -164,7 +164,7 @@ class AtCollectionMethodImpl { yield AtOperationItemStatus( atSign: selfAtKey.sharedWith ?? '', - key: selfAtKey.key ?? '', + key: selfAtKey.key, complete: isSelfKeyDeleted, operation: Operation.delete); } @@ -192,7 +192,7 @@ class AtCollectionMethodImpl { for (var sharedKey in sharedAtKeys) { var atOperationItemStatus = AtOperationItemStatus( atSign: sharedKey.sharedWith ?? '', - key: sharedKey.key ?? '', + key: sharedKey.key, complete: false, operation: Operation.unshare); diff --git a/packages/at_client/lib/src/at_collection/impl/default_key_maker.dart b/packages/at_client/lib/src/at_collection/impl/default_key_maker.dart index 4ce67117b..52782e036 100644 --- a/packages/at_client/lib/src/at_collection/impl/default_key_maker.dart +++ b/packages/at_client/lib/src/at_collection/impl/default_key_maker.dart @@ -16,9 +16,9 @@ class DefaultKeyMaker implements KeyMaker { return AtKey() ..key = '$keyId.$collectionName.atcollectionmodel.$namespace' ..metadata = Metadata() - ..metadata!.ccd = objectLifeCycleOptions?.cascadeDelete ?? true - ..metadata!.ttl = objectLifeCycleOptions?.timeToLive?.inMilliseconds - ..metadata!.ttb = objectLifeCycleOptions?.timeToBirth?.inMilliseconds + ..metadata.ccd = objectLifeCycleOptions?.cascadeDelete ?? true + ..metadata.ttl = objectLifeCycleOptions?.timeToLive?.inMilliseconds + ..metadata.ttb = objectLifeCycleOptions?.timeToBirth?.inMilliseconds ..sharedBy = _getAtClient().getCurrentAtSign(); } @@ -36,10 +36,10 @@ class DefaultKeyMaker implements KeyMaker { ..key = '$keyId.$collectionName.atcollectionmodel.$namespace' ..sharedWith = sharedWith ..metadata = Metadata() - ..metadata!.ttr = ttrInSeconds ?? -1 - ..metadata!.ccd = objectLifeCycleOptions?.cascadeDelete ?? true - ..metadata!.ttl = objectLifeCycleOptions?.timeToLive?.inMilliseconds - ..metadata!.ttb = objectLifeCycleOptions?.timeToBirth?.inMilliseconds + ..metadata.ttr = ttrInSeconds ?? -1 + ..metadata.ccd = objectLifeCycleOptions?.cascadeDelete ?? true + ..metadata.ttl = objectLifeCycleOptions?.timeToLive?.inMilliseconds + ..metadata.ttb = objectLifeCycleOptions?.timeToBirth?.inMilliseconds ..sharedBy = _getAtClient().getCurrentAtSign(); } } diff --git a/packages/at_client/lib/src/client/at_client_impl.dart b/packages/at_client/lib/src/client/at_client_impl.dart index 4a8927e05..07b86db39 100644 --- a/packages/at_client/lib/src/client/at_client_impl.dart +++ b/packages/at_client/lib/src/client/at_client_impl.dart @@ -294,23 +294,8 @@ class AtClientImpl implements AtClient, AtSignChangeListener { Future _delete(AtKey atKey, {DeleteRequestOptions? deleteRequestOptions}) async { - // If metadata is null, initialize metadata - atKey.metadata ??= Metadata(); - String keyWithNamespace; - if (atKey.metadata!.namespaceAware) { - keyWithNamespace = AtClientUtil.getKeyWithNameSpace(atKey, _preference!); - } else { - keyWithNamespace = atKey.key!; - } atKey.sharedBy ??= _atSign; - var builder = DeleteVerbBuilder() - ..isLocal = atKey.isLocal - ..isCached = atKey.metadata!.isCached - ..isPublic = - (atKey.metadata!.isPublic == null) ? false : atKey.metadata!.isPublic! - ..sharedWith = atKey.sharedWith - ..atKey = keyWithNamespace - ..sharedBy = atKey.sharedBy; + var builder = DeleteVerbBuilder()..atKey = atKey; var secondary = getSecondary(); if (deleteRequestOptions != null && deleteRequestOptions.useRemoteAtServer) { @@ -441,10 +426,8 @@ class AtClientImpl implements AtClient, AtSignChangeListener { Future putText(AtKey atKey, String value, {PutRequestOptions? putRequestOptions}) async { try { - // Set the default metadata if not already set. - atKey.metadata ??= Metadata(); // Setting metadata.isBinary to false for putText - atKey.metadata!.isBinary = false; + atKey.metadata.isBinary = false; return await _putInternal(atKey, value, putRequestOptions); } on AtException catch (e) { throw AtExceptionManager.createException(e); @@ -456,10 +439,8 @@ class AtClientImpl implements AtClient, AtSignChangeListener { Future putBinary(AtKey atKey, List value, {PutRequestOptions? putRequestOptions}) async { try { - // Set the default metadata if not already set. - atKey.metadata ??= Metadata(); // Setting metadata.isBinary to true for putBinary - atKey.metadata!.isBinary = true; + atKey.metadata.isBinary = true; // Base2e15.encode method converts the List type to String. return await _putInternal( atKey, Base2e15.encode(value), putRequestOptions); @@ -470,7 +451,7 @@ class AtClientImpl implements AtClient, AtSignChangeListener { @visibleForTesting ensureLowerCase(AtKey atKey) { - if ((atKey.key != null && upperCaseRegex.hasMatch(atKey.key!)) || + if (upperCaseRegex.hasMatch(atKey.key) || (atKey.namespace != null && upperCaseRegex.hasMatch(atKey.namespace!))) { _logger.finer('AtKey: ${atKey.toString()} previously contained upper case' @@ -487,12 +468,12 @@ class AtClientImpl implements AtClient, AtSignChangeListener { if (atKey.sharedBy.isNull) { atKey.sharedBy = _atSign; } - if (atKey.metadata!.namespaceAware) { + if (atKey.metadata.namespaceAware) { atKey.namespace ??= preference?.namespace; } if (preference!.atProtocolEmitted >= Version(2, 0, 0)) { - atKey.metadata!.ivNonce ??= EncryptionUtil.generateIV(); + atKey.metadata.ivNonce ??= EncryptionUtil.generateIV(); } ensureLowerCase(atKey); @@ -521,7 +502,7 @@ class AtClientImpl implements AtClient, AtSignChangeListener { //Get encryptionPrivateKey for public key to signData String? encryptionPrivateKey; - if (atKey.metadata!.isPublic != null && atKey.metadata!.isPublic! == true) { + if (atKey.metadata.isPublic == true) { encryptionPrivateKey = await _localSecondary?.getEncryptionPrivateKey(); } // Transform put request @@ -543,7 +524,7 @@ class AtClientImpl implements AtClient, AtSignChangeListener { } // Execute the verb builder var putResponse = await secondary.executeVerb(verbBuilder, - sync: SyncUtil.shouldSync(atKey.key!)); + sync: SyncUtil.shouldSync(atKey.key)); // If putResponse is null or empty, return AtResponse with isError set to true if (putResponse == null || putResponse.isEmpty) { return AtResponse()..isError = true; @@ -579,27 +560,17 @@ class AtClientImpl implements AtClient, AtSignChangeListener { @override Future putMeta(AtKey atKey) async { var updateKey = atKey.key; - var metadata = atKey.metadata!; + var metadata = atKey.metadata; if (metadata.namespaceAware) { - updateKey = _getKeyWithNamespace(atKey.key!); + updateKey = _getKeyWithNamespace(atKey.key); } - var sharedWith = atKey.sharedWith; var builder = UpdateVerbBuilder(); builder - ..atKey = updateKey - ..sharedBy = _atSign - ..sharedWith = sharedWith - ..ttl = metadata.ttl - ..ttb = metadata.ttb - ..ttr = metadata.ttr - ..ccd = metadata.ccd - ..isBinary = metadata.isBinary - ..isEncrypted = metadata.isEncrypted - ..dataSignature = metadata.dataSignature + ..atKey = atKey ..operation = AtConstants.updateMeta; var updateMetaResult = await getSecondary() - .executeVerb(builder, sync: SyncUtil.shouldSync(updateKey!)); + .executeVerb(builder, sync: SyncUtil.shouldSync(updateKey)); return updateMetaResult != null; } @@ -768,9 +739,9 @@ class AtClientImpl implements AtClient, AtSignChangeListener { ..key = key ..sharedWith = sharedWithAtSign ..metadata = Metadata() - ..metadata!.ttr = -1 + ..metadata.ttr = -1 // file transfer key will be deleted after 30 days - ..metadata!.ttl = 2592000000 + ..metadata.ttl = 2592000000 ..sharedBy = _atSign; var notificationResult = await notificationService.notify( @@ -949,7 +920,7 @@ class AtClientImpl implements AtClient, AtSignChangeListener { PriorityEnum? priority, StrategyEnum? strategy, int? latestN, - String? notifier = SYSTEM, + String? notifier = AtConstants.system, bool isDedicated = false}) async { AtKeyValidators.get().validate( atKey.toString(), diff --git a/packages/at_client/lib/src/client/local_secondary.dart b/packages/at_client/lib/src/client/local_secondary.dart index 86881ef91..d1fb0918c 100644 --- a/packages/at_client/lib/src/client/local_secondary.dart +++ b/packages/at_client/lib/src/client/local_secondary.dart @@ -69,46 +69,15 @@ class LocalSecondary implements Secondary { var updateKey = builder.buildKey(); switch (builder.operation) { case AtConstants.updateMeta: - var metadata = Metadata(); - metadata - ..ttl = builder.ttl - ..ttb = builder.ttb - ..ttr = builder.ttr - ..ccd = builder.ccd - ..isBinary = builder.isBinary - ..isEncrypted = builder.isEncrypted - ..sharedKeyEnc = builder.sharedKeyEncrypted - ..pubKeyCS = builder.pubKeyChecksum - ..encoding = builder.encoding - ..encKeyName = builder.encKeyName - ..encAlgo = builder.encAlgo - ..ivNonce = builder.ivNonce - ..skeEncKeyName = builder.skeEncKeyName - ..skeEncAlgo = builder.skeEncAlgo; - var atMetadata = AtMetaData.fromCommonsMetadata(metadata); + var atMetadata = + AtMetaData.fromCommonsMetadata(builder.atKey.metadata); updateResult = await keyStore!.putMeta(updateKey, atMetadata); break; default: var atData = AtData(); atData.data = builder.value; - var metadata = Metadata(); - metadata - ..ttl = builder.ttl - ..ttb = builder.ttb - ..ttr = builder.ttr - ..ccd = builder.ccd - ..isBinary = builder.isBinary - ..isEncrypted = builder.isEncrypted - ..dataSignature = builder.dataSignature - ..sharedKeyEnc = builder.sharedKeyEncrypted - ..pubKeyCS = builder.pubKeyChecksum - ..encoding = builder.encoding - ..encKeyName = builder.encKeyName - ..encAlgo = builder.encAlgo - ..ivNonce = builder.ivNonce - ..skeEncKeyName = builder.skeEncKeyName - ..skeEncAlgo = builder.skeEncAlgo; - var atMetadata = AtMetaData.fromCommonsMetadata(metadata); + var atMetadata = + AtMetaData.fromCommonsMetadata(builder.atKey.metadata); updateResult = await keyStore!.putAll(updateKey, atData, atMetadata); break; } diff --git a/packages/at_client/lib/src/client/verb_builder_manager.dart b/packages/at_client/lib/src/client/verb_builder_manager.dart index d28b0c3b9..1d6a29490 100644 --- a/packages/at_client/lib/src/client/verb_builder_manager.dart +++ b/packages/at_client/lib/src/client/verb_builder_manager.dart @@ -10,12 +10,11 @@ class LookUpBuilderManager { {GetRequestOptions? getRequestOptions}) { // If isPublic is true in metadata, the key is a public key, return PLookupVerbHandler. if (atKey.sharedBy != currentAtSign && - (atKey.metadata != null && - atKey.metadata!.isPublic! && - !atKey.metadata!.isCached)) { + (atKey.metadata.isPublic && !atKey.metadata.isCached)) { final plookUpVerbBuilder = PLookupVerbBuilder() - ..atKey = AtClientUtil.getKeyWithNameSpace(atKey, atClientPreference) - ..sharedBy = AtClientUtil.fixAtSign(atKey.sharedBy) + ..atKey = (AtKey() + ..key = AtClientUtil.getKeyWithNameSpace(atKey, atClientPreference) + ..sharedBy = AtClientUtil.fixAtSign(atKey.sharedBy)) ..operation = 'all'; if (getRequestOptions != null && getRequestOptions.bypassCache == true) { plookUpVerbBuilder.bypassCache = true; @@ -24,12 +23,11 @@ class LookUpBuilderManager { } // If sharedBy is not equal to currentAtSign and isCached is false, return LookupVerbHandler if (atKey.sharedBy != currentAtSign && - (atKey.metadata != null && - !atKey.metadata!.isCached && - !atKey.metadata!.isPublic!)) { + (!atKey.metadata.isCached && !atKey.metadata.isPublic)) { final lookupVerbBuilder = LookupVerbBuilder() - ..atKey = AtClientUtil.getKeyWithNameSpace(atKey, atClientPreference) - ..sharedBy = AtClientUtil.fixAtSign(atKey.sharedBy) + ..atKey = (AtKey() + ..key = AtClientUtil.getKeyWithNameSpace(atKey, atClientPreference) + ..sharedBy = AtClientUtil.fixAtSign(atKey.sharedBy)) ..auth = true ..operation = 'all'; if (getRequestOptions != null && getRequestOptions.bypassCache == true) { @@ -38,16 +36,14 @@ class LookUpBuilderManager { return lookupVerbBuilder; } return LLookupVerbBuilder() - ..atKey = AtClientUtil.getKeyWithNameSpace(atKey, atClientPreference) - ..sharedBy = AtClientUtil.fixAtSign(atKey.sharedBy) - ..sharedWith = AtClientUtil.fixAtSign(atKey.sharedWith) - ..isPublic = (atKey.metadata != null && atKey.metadata?.isPublic != null) - ? atKey.metadata!.isPublic! - : false - ..isCached = (atKey.metadata != null && atKey.metadata?.isCached != null) - ? atKey.metadata!.isCached - : false - ..isLocal = atKey.isLocal + ..atKey = (AtKey() + ..key = AtClientUtil.getKeyWithNameSpace(atKey, atClientPreference) + ..sharedBy = AtClientUtil.fixAtSign(atKey.sharedBy) + ..sharedWith = AtClientUtil.fixAtSign(atKey.sharedWith) + ..metadata = (Metadata() + ..isPublic = atKey.metadata.isPublic + ..isCached = atKey.metadata.isCached) + ..isLocal = atKey.isLocal) ..operation = 'all'; } } diff --git a/packages/at_client/lib/src/decryption_service/decryption_manager.dart b/packages/at_client/lib/src/decryption_service/decryption_manager.dart index 4b0b9fd82..7099fae4e 100644 --- a/packages/at_client/lib/src/decryption_service/decryption_manager.dart +++ b/packages/at_client/lib/src/decryption_service/decryption_manager.dart @@ -21,7 +21,7 @@ class AtKeyDecryptionManager { // Eg: currentAtSign is @bob and _phone.wavi@bob (or) phone@bob (or) @bob:phone@bob if (((atKey.sharedWith == null || atKey.sharedWith == currentAtSign) && atKey.sharedBy == currentAtSign) || - atKey.key!.startsWith('_')) { + atKey.key.startsWith('_')) { return SelfKeyDecryption(_atClient); } // Returns LocalKeyDecryption to for the keys present in local storage diff --git a/packages/at_client/lib/src/decryption_service/local_key_decryption.dart b/packages/at_client/lib/src/decryption_service/local_key_decryption.dart index bec3cdbd7..3289aa3aa 100644 --- a/packages/at_client/lib/src/decryption_service/local_key_decryption.dart +++ b/packages/at_client/lib/src/decryption_service/local_key_decryption.dart @@ -35,8 +35,8 @@ class LocalKeyDecryption extends AbstractAtKeyEncryption exceptionScenario: ExceptionScenario.fetchEncryptionKeys); } InitialisationVector iV; - if (atKey.metadata?.ivNonce != null) { - iV = AtChopsUtil.generateIVFromBase64String(atKey.metadata!.ivNonce!); + if (atKey.metadata.ivNonce != null) { + iV = AtChopsUtil.generateIVFromBase64String(atKey.metadata.ivNonce!); } else { iV = AtChopsUtil.generateIVLegacy(); } diff --git a/packages/at_client/lib/src/decryption_service/self_key_decryption.dart b/packages/at_client/lib/src/decryption_service/self_key_decryption.dart index b06c51dd2..eef08cc33 100644 --- a/packages/at_client/lib/src/decryption_service/self_key_decryption.dart +++ b/packages/at_client/lib/src/decryption_service/self_key_decryption.dart @@ -36,8 +36,8 @@ class SelfKeyDecryption implements AtKeyDecryption { } InitialisationVector iV; - if (atKey.metadata?.ivNonce != null) { - iV = AtChopsUtil.generateIVFromBase64String(atKey.metadata!.ivNonce!); + if (atKey.metadata.ivNonce != null) { + iV = AtChopsUtil.generateIVFromBase64String(atKey.metadata.ivNonce!); } else { iV = AtChopsUtil.generateIVLegacy(); } diff --git a/packages/at_client/lib/src/decryption_service/shared_key_decryption.dart b/packages/at_client/lib/src/decryption_service/shared_key_decryption.dart index 4e2d541d0..0e372ea94 100644 --- a/packages/at_client/lib/src/decryption_service/shared_key_decryption.dart +++ b/packages/at_client/lib/src/decryption_service/shared_key_decryption.dart @@ -29,8 +29,8 @@ class SharedKeyDecryption implements AtKeyDecryption { exceptionScenario: ExceptionScenario.decryptionFailed); } String? encryptedSharedKey; - if (atKey.metadata != null) { - encryptedSharedKey = atKey.metadata!.sharedKeyEnc; + if (atKey.metadata.sharedKeyEnc != null) { + encryptedSharedKey = atKey.metadata.sharedKeyEnc; } encryptedSharedKey ??= await _getEncryptedSharedKey(atKey); if (encryptedSharedKey.isEmpty || encryptedSharedKey == 'null') { @@ -51,10 +51,9 @@ class SharedKeyDecryption implements AtKeyDecryption { exceptionScenario: ExceptionScenario.localVerbExecutionFailed); } if (currentAtSignPublicKey != null && - atKey.metadata != null && - atKey.metadata!.pubKeyCS != null && - atKey.metadata!.pubKeyCS != - EncryptionUtil.md5CheckSum(currentAtSignPublicKey)) { + (atKey.metadata.pubKeyCS != null && + atKey.metadata.pubKeyCS != + EncryptionUtil.md5CheckSum(currentAtSignPublicKey))) { throw AtPublicKeyChangeException( 'Public key has changed. Cannot decrypt shared key ${atKey.toString()}', intent: Intent.fetchEncryptionPublicKey, @@ -64,8 +63,8 @@ class SharedKeyDecryption implements AtKeyDecryption { AtEncryptionResult decryptionResultFromAtChops; try { InitialisationVector iV; - if (atKey.metadata?.ivNonce != null) { - iV = AtChopsUtil.generateIVFromBase64String(atKey.metadata!.ivNonce!); + if (atKey.metadata.ivNonce != null) { + iV = AtChopsUtil.generateIVFromBase64String(atKey.metadata.ivNonce!); } else { iV = AtChopsUtil.generateIVLegacy(); } @@ -76,12 +75,6 @@ class SharedKeyDecryption implements AtKeyDecryption { decryptionResultFromAtChops = _atClient.atChops!.decryptString( encryptedValue, EncryptionKeyType.aes256, encryptionAlgorithm: encryptionAlgo, iv: iV); - } on AtKeyException catch (e) { - e.stack(AtChainedException( - Intent.decryptData, - ExceptionScenario.decryptionFailed, - 'Failed to decrypt ${atKey.toString()}')); - rethrow; } on AtDecryptionException catch (e) { _logger.severe( 'decryption exception during of key: ${atKey.key}. Reason: ${e.toString()}'); @@ -93,10 +86,11 @@ class SharedKeyDecryption implements AtKeyDecryption { Future _getEncryptedSharedKey(AtKey atKey) async { String? encryptedSharedKey = ''; var localLookupSharedKeyBuilder = LLookupVerbBuilder() - ..atKey = AtConstants.atEncryptionSharedKey - ..sharedWith = _atClient.getCurrentAtSign() - ..sharedBy = atKey.sharedBy - ..isCached = true; + ..atKey = (AtKey() + ..key = AtConstants.atEncryptionSharedKey + ..sharedWith = _atClient.getCurrentAtSign() + ..sharedBy = atKey.sharedBy + ..metadata = (Metadata()..isCached = true)); try { encryptedSharedKey = await _atClient .getLocalSecondary()! @@ -109,8 +103,9 @@ class SharedKeyDecryption implements AtKeyDecryption { encryptedSharedKey.isEmpty || encryptedSharedKey == 'data:null') { var sharedKeyLookUpBuilder = LookupVerbBuilder() - ..atKey = AtConstants.atEncryptionSharedKey - ..sharedBy = atKey.sharedBy + ..atKey = (AtKey() + ..key = AtConstants.atEncryptionSharedKey + ..sharedBy = atKey.sharedBy) ..auth = true; encryptedSharedKey = await _atClient .getRemoteSecondary()! diff --git a/packages/at_client/lib/src/encryption_service/abstract_atkey_encryption.dart b/packages/at_client/lib/src/encryption_service/abstract_atkey_encryption.dart index 85d581f23..78612f25a 100644 --- a/packages/at_client/lib/src/encryption_service/abstract_atkey_encryption.dart +++ b/packages/at_client/lib/src/encryption_service/abstract_atkey_encryption.dart @@ -40,7 +40,6 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { Future encrypt(AtKey atKey, dynamic value, {bool storeSharedKeyEncryptedWithData = true}) async { _sharedKey = await getMyCopyOfSharedSymmetricKey(atKey); - if (_sharedKey.isEmpty) { _sharedKey = await createMyCopyOfSharedSymmetricKey(atKey); } @@ -49,8 +48,8 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { await verifyTheirCopyOfSharedSymmetricKey(atKey, _sharedKey); if (storeSharedKeyEncryptedWithData) { - atKey.metadata!.sharedKeyEnc = theirEncryptedSymmetricKeyCopy; - atKey.metadata!.pubKeyCS = + atKey.metadata.sharedKeyEnc = theirEncryptedSymmetricKeyCopy; + atKey.metadata.pubKeyCS = EncryptionUtil.md5CheckSum(await _getSharedWithPublicKey(atKey)); } } @@ -121,26 +120,15 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { Future createMyCopyOfSharedSymmetricKey(AtKey atKey) async { _logger.info( "Creating new shared symmetric key as ${atKey.sharedBy} for ${atKey.sharedWith}"); - // Fetch our encryption public key - String? currentAtSignEncryptionPublicKey; - try { - currentAtSignEncryptionPublicKey = await _atClient - .getLocalSecondary()! - .getEncryptionPublicKey(atKey.sharedBy!); - } on KeyNotFoundException catch (e) { - e.stack(AtChainedException( - Intent.fetchEncryptionPublicKey, - ExceptionScenario.fetchEncryptionKeys, - 'Failed to fetch encryption public key of current atSign')); - rethrow; - } // Generate new symmetric key - var newSymmetricKeyBase64 = EncryptionUtil.generateAESKey(); - + var newSymmetricKeyBase64 = + AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256).key; // Encrypt the new symmetric key with our public key - var encryptedSharedKeyMyCopy = EncryptionUtil.encryptKey( - newSymmetricKeyBase64, currentAtSignEncryptionPublicKey!); - + var atChopsEncryptionResult = _atClient.atChops! + .encryptString(newSymmetricKeyBase64, EncryptionKeyType.rsa2048); + var encryptedSharedKeyMyCopy = atChopsEncryptionResult.result; + _logger.info( + 'encryptedSharedKeyMyCopy from atChops: $encryptedSharedKeyMyCopy'); // Defensive code to ensure that we do not have an old 'their' copy on atServer await deleteTheirCopyOfEncryptedSharedKey( atKey, _atClient.getRemoteSecondary()!); @@ -248,10 +236,12 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { try { // 1. Get the cached public key var cachedEncryptionPublicKeyBuilder = LLookupVerbBuilder() - ..atKey = 'publickey' - ..sharedBy = atKey.sharedWith - ..isPublic = true - ..isCached = true; + ..atKey = (AtKey() + ..key = 'publickey' + ..sharedBy = atKey.sharedWith + ..metadata = (Metadata() + ..isPublic = true + ..isCached = true)); sharedWithPublicKey = await _atClient .getLocalSecondary()! @@ -262,8 +252,9 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { try { if (sharedWithPublicKey.isNull || sharedWithPublicKey == 'data:null') { var encryptionPublicKeyBuilder = PLookupVerbBuilder() - ..atKey = 'publickey' - ..sharedBy = atKey.sharedWith; + ..atKey = (AtKey() + ..key = 'publickey' + ..sharedBy = atKey.sharedWith); sharedWithPublicKey = await _atClient .getRemoteSecondary()! .executeVerb(encryptionPublicKeyBuilder); @@ -286,9 +277,10 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { Future _storeMyEncryptedCopyOfSharedSymmetricKey( AtKey atKey, String encryptedSharedKey, Secondary secondary) async { var updateSharedKeyForCurrentAtSignBuilder = UpdateVerbBuilder() - ..atKey = - '${AtConstants.atEncryptionSharedKey}.${atKey.sharedWith?.replaceAll('@', '')}' - ..sharedBy = atKey.sharedBy + ..atKey = (AtKey() + ..key = + '${AtConstants.atEncryptionSharedKey}.${atKey.sharedWith?.replaceAll('@', '')}' + ..sharedBy = atKey.sharedBy) ..value = encryptedSharedKey; await secondary.executeVerb(updateSharedKeyForCurrentAtSignBuilder, sync: false); @@ -300,9 +292,10 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { Future _getMyEncryptedCopyOfSharedSymmetricKey( Secondary secondary, AtKey atKey) async { var llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = - '${AtConstants.atEncryptionSharedKey}.${atKey.sharedWith?.replaceAll('@', '')}' - ..sharedBy = atKey.sharedBy; + ..atKey = (AtKey() + ..key = + '${AtConstants.atEncryptionSharedKey}.${atKey.sharedWith?.replaceAll('@', '')}' + ..sharedBy = atKey.sharedBy); String? myCopy; try { @@ -324,9 +317,10 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { Future _getTheirEncryptedCopyOfSharedSymmetricKey( Secondary secondary, AtKey atKey) async { var llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = AtConstants.atEncryptionSharedKey - ..sharedBy = atKey.sharedBy - ..sharedWith = atKey.sharedWith; + ..atKey = (AtKey() + ..key = AtConstants.atEncryptionSharedKey + ..sharedBy = atKey.sharedBy + ..sharedWith = atKey.sharedWith); String? theirCopy; try { theirCopy = await secondary.executeVerb(llookupVerbBuilder); @@ -346,10 +340,11 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { {Secondary? secondary}) async { secondary ??= _atClient.getLocalSecondary()!; var updateSharedKeyBuilder = UpdateVerbBuilder() - ..atKey = AtConstants.atEncryptionSharedKey - ..sharedWith = atKey.sharedWith - ..sharedBy = atKey.sharedBy - ..ttr = 3888000 + ..atKey = (AtKey() + ..key = AtConstants.atEncryptionSharedKey + ..sharedWith = atKey.sharedWith + ..sharedBy = atKey.sharedBy + ..metadata = (Metadata()..ttr = 3888000)) ..value = encryptedSharedKeyValue; return await secondary.executeVerb(updateSharedKeyBuilder, sync: false); } @@ -360,9 +355,10 @@ abstract class AbstractAtKeyEncryption implements AtKeyEncryption { Future deleteTheirCopyOfEncryptedSharedKey( AtKey atKey, Secondary secondary) async { var deleteBuilder = DeleteVerbBuilder() - ..atKey = AtConstants.atEncryptionSharedKey - ..sharedWith = atKey.sharedWith - ..sharedBy = atKey.sharedBy; + ..atKey = (AtKey() + ..key = AtConstants.atEncryptionSharedKey + ..sharedWith = atKey.sharedWith + ..sharedBy = atKey.sharedBy); _logger.info( 'Deleting ${deleteBuilder.buildKey()} from ${secondary.runtimeType}'); diff --git a/packages/at_client/lib/src/encryption_service/self_key_encryption.dart b/packages/at_client/lib/src/encryption_service/self_key_encryption.dart index b2f9ee3ed..7adf0404d 100644 --- a/packages/at_client/lib/src/encryption_service/self_key_encryption.dart +++ b/packages/at_client/lib/src/encryption_service/self_key_encryption.dart @@ -3,19 +3,19 @@ import 'package:at_client/src/client/local_secondary.dart'; import 'package:at_client/src/encryption_service/encryption.dart'; import 'package:at_client/src/response/default_response_parser.dart'; import 'package:at_client/src/util/at_client_util.dart'; -import 'package:at_client/src/util/encryption_util.dart'; import 'package:at_commons/at_commons.dart'; +import 'package:at_chops/at_chops.dart'; import 'package:at_utils/at_logger.dart'; ///Class responsible for encrypting the selfKey's class SelfKeyEncryption implements AtKeyEncryption { late final AtSignLogger _logger; - final AtClient atClient; + final AtClient _atClient; - SelfKeyEncryption(this.atClient) { + SelfKeyEncryption(this._atClient) { _logger = - AtSignLogger('SelfKeyEncryption (${atClient.getCurrentAtSign()})'); + AtSignLogger('SelfKeyEncryption (${_atClient.getCurrentAtSign()})'); } @override @@ -29,12 +29,27 @@ class SelfKeyEncryption implements AtKeyEncryption { } // Get AES key for current atSign var selfEncryptionKey = - await _getSelfEncryptionKey(atClient.getLocalSecondary()!); + await _getSelfEncryptionKey(_atClient.getLocalSecondary()!); selfEncryptionKey = DefaultResponseParser().parse(selfEncryptionKey).response; - // Encrypt value using sharedKey - return EncryptionUtil.encryptValue(value, selfEncryptionKey, - ivBase64: atKey.metadata?.ivNonce); + AtEncryptionResult encryptionResultFromAtChops; + try { + InitialisationVector iV; + if (atKey.metadata.ivNonce != null) { + iV = AtChopsUtil.generateIVFromBase64String(atKey.metadata.ivNonce!); + } else { + iV = AtChopsUtil.generateIVLegacy(); + } + var encryptionAlgo = AESEncryptionAlgo(AESKey(selfEncryptionKey)); + encryptionResultFromAtChops = _atClient.atChops!.encryptString( + value, EncryptionKeyType.aes256, + encryptionAlgorithm: encryptionAlgo, iv: iV); + } on AtEncryptionException catch (e) { + _logger.severe( + 'encryption exception during self encryption of key: ${atKey.key}. Reason: ${e.toString()}'); + rethrow; + } + return encryptionResultFromAtChops.result; } Future _getSelfEncryptionKey(LocalSecondary localSecondary) async { diff --git a/packages/at_client/lib/src/encryption_service/shared_key_encryption.dart b/packages/at_client/lib/src/encryption_service/shared_key_encryption.dart index 631da68c7..7a8587cb5 100644 --- a/packages/at_client/lib/src/encryption_service/shared_key_encryption.dart +++ b/packages/at_client/lib/src/encryption_service/shared_key_encryption.dart @@ -1,9 +1,16 @@ import 'package:at_client/at_client.dart'; +import 'package:at_utils/at_logger.dart'; +import 'package:at_chops/at_chops.dart'; import 'package:at_client/src/encryption_service/abstract_atkey_encryption.dart'; ///Class responsible for encrypting the value of the SharedKey's class SharedKeyEncryption extends AbstractAtKeyEncryption { - SharedKeyEncryption(AtClient atClient) : super(atClient); + final AtClient _atClient; + late final AtSignLogger _logger; + SharedKeyEncryption(this._atClient) : super(_atClient) { + _logger = + AtSignLogger('SelfKeyEncryption (${_atClient.getCurrentAtSign()})'); + } @override Future encrypt(AtKey atKey, dynamic value, @@ -17,9 +24,23 @@ class SharedKeyEncryption extends AbstractAtKeyEncryption { // encryption key and setting it in super.sharedKey await super.encrypt(atKey, value, storeSharedKeyEncryptedWithData: storeSharedKeyEncryptedWithData); - - // Encrypt the value - return EncryptionUtil.encryptValue(value, sharedKey, - ivBase64: atKey.metadata?.ivNonce); + AtEncryptionResult encryptionResultFromAtChops; + try { + InitialisationVector iV; + if (atKey.metadata.ivNonce != null) { + iV = AtChopsUtil.generateIVFromBase64String(atKey.metadata.ivNonce!); + } else { + iV = AtChopsUtil.generateIVLegacy(); + } + var encryptionAlgo = AESEncryptionAlgo(AESKey(sharedKey)); + encryptionResultFromAtChops = _atClient.atChops!.encryptString( + value, EncryptionKeyType.aes256, + encryptionAlgorithm: encryptionAlgo, iv: iV); + } on AtEncryptionException catch (e) { + _logger.severe( + 'encryption exception during shared key encryption of key: ${atKey.key}. Reason: ${e.toString()}'); + rethrow; + } + return encryptionResultFromAtChops.result; } -} +} \ No newline at end of file diff --git a/packages/at_client/lib/src/encryption_service/stream_encryption.dart b/packages/at_client/lib/src/encryption_service/stream_encryption.dart index dbe3daa6b..78a9ab78c 100644 --- a/packages/at_client/lib/src/encryption_service/stream_encryption.dart +++ b/packages/at_client/lib/src/encryption_service/stream_encryption.dart @@ -18,6 +18,6 @@ class StreamEncryption extends AbstractAtKeyEncryption { storeSharedKeyEncryptedWithData: storeSharedKeyEncryptedWithData); // Encrypt value using sharedKey return EncryptionUtil.encryptBytes(value, sharedKey, - ivBase64: atKey.metadata?.ivNonce); + ivBase64: atKey.metadata.ivNonce); } } diff --git a/packages/at_client/lib/src/key_stream/key_stream_iterable_base.dart b/packages/at_client/lib/src/key_stream/key_stream_iterable_base.dart index 8a46391bb..4e9c2b5c5 100644 --- a/packages/at_client/lib/src/key_stream/key_stream_iterable_base.dart +++ b/packages/at_client/lib/src/key_stream/key_stream_iterable_base.dart @@ -53,7 +53,7 @@ class KeyStreamIterableBase> extends KeyStreamMixin FutureOr Function(Object exception, [StackTrace? stackTrace])? onError, AtClientManager? atClientManager, - }) : _generateRef = generateRef ?? ((key, value) => key.key ?? ''), + }) : _generateRef = generateRef ?? ((key, value) => key.key), _castTo = castTo ?? ((Iterable values) => values as I), super( convert: convert, diff --git a/packages/at_client/lib/src/key_stream/key_stream_map_base.dart b/packages/at_client/lib/src/key_stream/key_stream_map_base.dart index f58e05e10..cd9e44838 100644 --- a/packages/at_client/lib/src/key_stream/key_stream_map_base.dart +++ b/packages/at_client/lib/src/key_stream/key_stream_map_base.dart @@ -43,7 +43,7 @@ class KeyStreamMapBase> extends KeyStreamMixin FutureOr Function(Object exception, [StackTrace? stackTrace])? onError, AtClientManager? atClientManager, - }) : _generateRef = generateRef ?? ((key, value) => key.key ?? ''), + }) : _generateRef = generateRef ?? ((key, value) => key.key), _castTo = castTo ?? ((Iterable> values) => values as I), super( convert: convert, diff --git a/packages/at_client/lib/src/manager/sync_manager.dart b/packages/at_client/lib/src/manager/sync_manager.dart index d8a459d64..08cc2a72c 100644 --- a/packages/at_client/lib/src/manager/sync_manager.dart +++ b/packages/at_client/lib/src/manager/sync_manager.dart @@ -204,7 +204,8 @@ class SyncManager { .getLastSyncedEntry(_preference!.syncRegex, atSign: _atSign!); var lastSyncedCommitId = lastSyncedEntry?.commitId; var commitIdReceivePort = ReceivePort(); - var privateKey = await _localSecondary!.keyStore!.get(AT_PKAM_PRIVATE_KEY); + var privateKey = + await _localSecondary!.keyStore!.get(AtConstants.atPkamPrivateKey); var isolate = await Isolate.spawn( SyncIsolateManager.executeRemoteCommandIsolate, commitIdReceivePort.sendPort); @@ -338,7 +339,7 @@ class SyncManager { var builder = UpdateVerbBuilder() ..atKey = serverCommitEntry['atKey'] ..value = serverCommitEntry['value']; - builder.operation = UPDATE_ALL; + builder.operation = AtConstants.updateAll; _setMetaData(builder, serverCommitEntry); await _pullToLocal(builder, serverCommitEntry, CommitOp.UPDATE_ALL); break; @@ -349,29 +350,33 @@ class SyncManager { } } - void _setMetaData(builder, serverCommitEntry) { + void _setMetaData(UpdateVerbBuilder builder, serverCommitEntry) { var metaData = serverCommitEntry['metadata']; if (metaData != null && metaData.isNotEmpty) { - if (metaData[AT_TTL] != null) builder.ttl = int.parse(metaData[AT_TTL]); - if (metaData[AT_TTB] != null) builder.ttb = int.parse(metaData[AT_TTB]); - if (metaData[AT_TTR] != null) builder.ttr = int.parse(metaData[AT_TTR]); - if (metaData[CCD] != null) { - (metaData[CCD].toLowerCase() == 'true') - ? builder.ccd = true - : builder.ccd = false; + if (metaData[AtConstants.ttl] != null) + builder.atKey.metadata.ttl = int.parse(metaData[AtConstants.ttl]); + if (metaData[AtConstants.ttb] != null) + builder.atKey.metadata.ttb = int.parse(metaData[AtConstants.ttb]); + if (metaData[AtConstants.ttr] != null) + builder.atKey.metadata.ttr = int.parse(metaData[AtConstants.ttr]); + if (metaData[AtConstants.ccd] != null) { + (metaData[AtConstants.ccd].toLowerCase() == 'true') + ? builder.atKey.metadata.ccd = true + : builder.atKey.metadata.ccd = false; } - if (metaData[PUBLIC_DATA_SIGNATURE] != null) { - builder.dataSignature = metaData[PUBLIC_DATA_SIGNATURE]; + if (metaData[AtConstants.publicDataSignature] != null) { + builder.atKey.metadata.dataSignature = + metaData[AtConstants.publicDataSignature]; } - if (metaData[IS_BINARY] != null) { - (metaData[IS_BINARY].toLowerCase() == 'true') - ? builder.isBinary = true - : builder.isBinary = false; + if (metaData[AtConstants.isBinary] != null) { + (metaData[AtConstants.isBinary].toLowerCase() == 'true') + ? builder.atKey.metadata.isBinary = true + : builder.atKey.metadata.isBinary = false; } - if (metaData[IS_ENCRYPTED] != null) { - (metaData[IS_ENCRYPTED].toLowerCase() == 'true') - ? builder.isEncrypted = true - : builder.isEncrypted = false; + if (metaData[AtConstants.isEncrypted] != null) { + (metaData[AtConstants.isEncrypted].toLowerCase() == 'true') + ? builder.atKey.metadata.isEncrypted = true + : builder.atKey.metadata.isEncrypted = false; } } } diff --git a/packages/at_client/lib/src/preference/at_client_config.dart b/packages/at_client/lib/src/preference/at_client_config.dart index 663cf9d1b..f0a9d5d88 100644 --- a/packages/at_client/lib/src/preference/at_client_config.dart +++ b/packages/at_client/lib/src/preference/at_client_config.dart @@ -10,7 +10,7 @@ class AtClientConfig { /// Represents the at_client version. /// Must always be the same as the actual version in pubspec.yaml - final String atClientVersion = '3.0.71'; + final String atClientVersion = '3.0.72'; /// Represents the client commit log compaction time interval /// diff --git a/packages/at_client/lib/src/service/encryption_service.dart b/packages/at_client/lib/src/service/encryption_service.dart index f1ccaf829..6f5cab98d 100644 --- a/packages/at_client/lib/src/service/encryption_service.dart +++ b/packages/at_client/lib/src/service/encryption_service.dart @@ -95,8 +95,9 @@ class EncryptionService { //a local lookup the cached public key of sharedWith atsign. String? sharedWithPublicKey; var cachedPublicKeyBuilder = LLookupVerbBuilder() - ..atKey = 'publickey.$sharedWithUser' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = 'publickey.$sharedWithUser' + ..sharedBy = atSign); try { sharedWithPublicKey = await localSecondary!.executeVerb(cachedPublicKeyBuilder); @@ -112,8 +113,9 @@ class EncryptionService { //b Lookup public key of sharedWith atsign var plookupBuilder = PLookupVerbBuilder() - ..atKey = 'publickey' - ..sharedBy = sharedWithUser; + ..atKey = (AtKey() + ..key = 'publickey' + ..sharedBy = sharedWithUser); sharedWithPublicKey = await remoteSecondary!.executeVerb(plookupBuilder); sharedWithPublicKey = DefaultResponseParser().parse(sharedWithPublicKey).response; @@ -125,8 +127,9 @@ class EncryptionService { } //Cache the sharedWithPublicKey var sharedWithPublicKeyBuilder = UpdateVerbBuilder() - ..atKey = 'publickey.$sharedWithUser' - ..sharedBy = atSign + ..atKey = (AtKey() + ..key = 'publickey.$sharedWithUser' + ..sharedBy = atSign) ..value = sharedWithPublicKey; await localSecondary!.executeVerb(sharedWithPublicKeyBuilder, sync: true); return sharedWithPublicKey; @@ -135,8 +138,9 @@ class EncryptionService { Future _getSharedKeyFromLocalForEncryption(String sharedWith) async { final sharedWithUser = sharedWith.replaceFirst('@', ''); final llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = '${AtConstants.atEncryptionSharedKey}.$sharedWithUser' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = '${AtConstants.atEncryptionSharedKey}.$sharedWithUser' + ..sharedBy = atSign); String? sharedKey; try { sharedKey = await localSecondary!.executeVerb(llookupVerbBuilder); @@ -151,8 +155,9 @@ class EncryptionService { String sharedWith) async { final sharedWithUser = sharedWith.replaceFirst('@', ''); final llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = '${AtConstants.atEncryptionSharedKey}.$sharedWithUser' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = '${AtConstants.atEncryptionSharedKey}.$sharedWithUser' + ..sharedBy = atSign); String? sharedKey; try { sharedKey = await remoteSecondary!.executeVerb(llookupVerbBuilder); @@ -166,9 +171,10 @@ class EncryptionService { var sharedWithUser = sharedWith.replaceFirst('@', ''); //Verify if encryptedSharedKey for sharedWith atSign is available. var lookupEncryptionSharedKey = LLookupVerbBuilder() - ..sharedWith = sharedWith - ..sharedBy = atSign - ..atKey = AtConstants.atEncryptionSharedKey; + ..atKey = (AtKey() + ..key = AtConstants.atEncryptionSharedKey + ..sharedWith = sharedWith + ..sharedBy = atSign); String? result; try { result = await localSecondary!.executeVerb(lookupEncryptionSharedKey); @@ -195,11 +201,12 @@ class EncryptionService { EncryptionUtil.encryptKey(sharedKey, sharedWithPublicKey); // Store the encryptedSharedWith Key. Set ttr to enable sharedWith atsign to cache the encryptedSharedKey. var updateSharedKeyBuilder = UpdateVerbBuilder() - ..sharedWith = sharedWith - ..sharedBy = atSign - ..atKey = AtConstants.atEncryptionSharedKey - ..value = encryptedSharedKey - ..ttr = 3888000; + ..atKey = (AtKey() + ..key = AtConstants.atEncryptionSharedKey + ..sharedWith = sharedWith + ..sharedBy = atSign + ..metadata = (Metadata()..ttr = 3888000)) + ..value = encryptedSharedKey; await localSecondary!.executeVerb(updateSharedKeyBuilder, sync: true); } } @@ -215,8 +222,9 @@ class EncryptionService { EncryptionUtil.encryptKey(sharedKey, currentAtSignPublicKey!); var updateSharedKeyForCurrentAtSignBuilder = UpdateVerbBuilder() - ..sharedBy = atSign - ..atKey = '${AtConstants.atEncryptionSharedKey}.$sharedWithUser' + ..atKey = (AtKey() + ..key = '${AtConstants.atEncryptionSharedKey}.$sharedWithUser' + ..sharedBy = atSign) ..value = encryptedSharedKeyForCurrentAtSign; await localSecondary! .executeVerb(updateSharedKeyForCurrentAtSignBuilder, sync: true); @@ -225,10 +233,11 @@ class EncryptionService { Future _getSharedKeyForDecryption(String sharedBy) async { String? encryptedSharedKey; var localLookupSharedKeyBuilder = LLookupVerbBuilder() - ..isCached = true - ..sharedBy = sharedBy - ..sharedWith = atSign - ..atKey = AtConstants.atEncryptionSharedKey; + ..atKey = (AtKey() + ..key = AtConstants.atEncryptionSharedKey + ..sharedBy = sharedBy + ..sharedWith = atSign + ..metadata = (Metadata()..isCached = true)); try { encryptedSharedKey = await localSecondary!.executeVerb(localLookupSharedKeyBuilder); @@ -238,8 +247,9 @@ class EncryptionService { } if (encryptedSharedKey == null || encryptedSharedKey == 'data:null') { var sharedKeyLookUpBuilder = LookupVerbBuilder() - ..atKey = AtConstants.atEncryptionSharedKey - ..sharedBy = sharedBy + ..atKey = (AtKey() + ..key = AtConstants.atEncryptionSharedKey + ..sharedBy = sharedBy) ..auth = true; encryptedSharedKey = await remoteSecondary!.executeVerb(sharedKeyLookUpBuilder); diff --git a/packages/at_client/lib/src/service/notification_service_impl.dart b/packages/at_client/lib/src/service/notification_service_impl.dart index 1e9c5ed84..784acf268 100644 --- a/packages/at_client/lib/src/service/notification_service_impl.dart +++ b/packages/at_client/lib/src/service/notification_service_impl.dart @@ -327,9 +327,7 @@ class NotificationServiceImpl ..atKey = notificationParams.atKey; if (_atClient.getPreferences()!.atProtocolEmitted >= Version(2, 0, 0)) { - notificationParams.atKey.metadata ??= Metadata(); - notificationParams.atKey.metadata!.ivNonce ??= - EncryptionUtil.generateIV(); + notificationParams.atKey.metadata.ivNonce ??= EncryptionUtil.generateIV(); } try { @@ -410,7 +408,8 @@ class NotificationServiceImpl case MessageTypeEnum.text: // When messageType is text, the "text" to notify is added to the key. Hence validating // the key length - if (builder.atKey!.length > _atClient.getPreferences()!.maxDataSize) { + if (builder.atKey.key.length > + _atClient.getPreferences()!.maxDataSize) { throw BufferOverFlowException( 'The length of value exceeds the maximum allowed length. Maximum buffer size is ${_atClient.getPreferences()!.maxDataSize} bytes. Found ${builder.value.toString().length} bytes'); } diff --git a/packages/at_client/lib/src/service/sync_service_impl.dart b/packages/at_client/lib/src/service/sync_service_impl.dart index 8eefc565f..012f4e6cf 100644 --- a/packages/at_client/lib/src/service/sync_service_impl.dart +++ b/packages/at_client/lib/src/service/sync_service_impl.dart @@ -896,7 +896,7 @@ class SyncServiceImpl implements SyncService, AtSignChangeListener { case '#': case '*': var builder = UpdateVerbBuilder() - ..atKeyObj = AtKey.fromString(serverCommitEntry['atKey']) + ..atKey = AtKey.fromString(serverCommitEntry['atKey']) ..value = serverCommitEntry['value']; builder.operation = AtConstants.updateAll; _setMetaData(builder, serverCommitEntry); @@ -904,7 +904,7 @@ class SyncServiceImpl implements SyncService, AtSignChangeListener { break; case '-': var builder = DeleteVerbBuilder() - ..atKeyObj = AtKey.fromString(serverCommitEntry['atKey']); + ..atKey = AtKey.fromString(serverCommitEntry['atKey']); await _pullToLocal(builder, serverCommitEntry, CommitOp.DELETE); break; } @@ -936,57 +936,60 @@ class SyncServiceImpl implements SyncService, AtSignChangeListener { var metaData = serverCommitEntry['metadata']; if (metaData != null && metaData.isNotEmpty) { if (metaData[AtConstants.ttl] != null) { - builder.ttl = int.parse(metaData[AtConstants.ttl]); + builder.atKey.metadata.ttl = int.parse(metaData[AtConstants.ttl]); } if (metaData[AtConstants.ttb] != null) { - builder.ttb = int.parse(metaData[AtConstants.ttb]); + builder.atKey.metadata.ttb = int.parse(metaData[AtConstants.ttb]); } if (metaData[AtConstants.ttr] != null) { - builder.ttr = int.parse(metaData[AtConstants.ttr]); + builder.atKey.metadata.ttr = int.parse(metaData[AtConstants.ttr]); } if (metaData[AtConstants.ccd] != null) { (metaData[AtConstants.ccd].toLowerCase() == 'true') - ? builder.ccd = true - : builder.ccd = false; + ? builder.atKey.metadata.ccd = true + : builder.atKey.metadata.ccd = false; } if (metaData[AtConstants.publicDataSignature] != null) { - builder.dataSignature = metaData[AtConstants.publicDataSignature]; + builder.atKey.metadata.dataSignature = + metaData[AtConstants.publicDataSignature]; } if (metaData[AtConstants.isBinary] != null) { (metaData[AtConstants.isBinary].toLowerCase() == 'true') - ? builder.isBinary = true - : builder.isBinary = false; + ? builder.atKey.metadata.isBinary = true + : builder.atKey.metadata.isBinary = false; } if (metaData[AtConstants.isEncrypted] != null) { (metaData[AtConstants.isEncrypted].toLowerCase() == 'true') - ? builder.isEncrypted = true - : builder.isEncrypted = false; + ? builder.atKey.metadata.isEncrypted = true + : builder.atKey.metadata.isEncrypted = false; } if (metaData[AtConstants.sharedKeyEncrypted] != null) { - builder.sharedKeyEncrypted = metaData[AtConstants.sharedKeyEncrypted]; + builder.atKey.metadata.sharedKeyEnc = + metaData[AtConstants.sharedKeyEncrypted]; } if (metaData[AtConstants.sharedWithPublicKeyCheckSum] != null) { - builder.pubKeyChecksum = + builder.atKey.metadata.pubKeyCS = metaData[AtConstants.sharedWithPublicKeyCheckSum]; } if (metaData[AtConstants.encoding] != null) { - builder.encoding = metaData[AtConstants.encoding]; + builder.atKey.metadata.encoding = metaData[AtConstants.encoding]; } if (metaData[AtConstants.encryptingKeyName] != null) { - builder.encKeyName = metaData[AtConstants.encryptingKeyName]; + builder.atKey.metadata.encKeyName = + metaData[AtConstants.encryptingKeyName]; } if (metaData[AtConstants.encryptingAlgo] != null) { - builder.encAlgo = metaData[AtConstants.encryptingAlgo]; + builder.atKey.metadata.encAlgo = metaData[AtConstants.encryptingAlgo]; } if (metaData[AtConstants.ivOrNonce] != null) { - builder.ivNonce = metaData[AtConstants.ivOrNonce]; + builder.atKey.metadata.ivNonce = metaData[AtConstants.ivOrNonce]; } if (metaData[AtConstants.sharedKeyEncryptedEncryptingKeyName] != null) { - builder.skeEncKeyName = + builder.atKey.metadata.skeEncKeyName = metaData[AtConstants.sharedKeyEncryptedEncryptingKeyName]; } if (metaData[AtConstants.sharedKeyEncryptedEncryptingAlgo] != null) { - builder.skeEncAlgo = + builder.atKey.metadata.skeEncAlgo = metaData[AtConstants.sharedKeyEncryptedEncryptingAlgo]; } } diff --git a/packages/at_client/lib/src/transformer/request_transformer/get_request_transformer.dart b/packages/at_client/lib/src/transformer/request_transformer/get_request_transformer.dart index b4f3a069d..835cb553a 100644 --- a/packages/at_client/lib/src/transformer/request_transformer/get_request_transformer.dart +++ b/packages/at_client/lib/src/transformer/request_transformer/get_request_transformer.dart @@ -12,8 +12,6 @@ class GetRequestTransformer implements RequestTransformer { @override VerbBuilder transform(AtKey atKey, {RequestOptions? requestOptions}) { - // Set the default metadata if not already set. - atKey.metadata ??= Metadata(); // Set sharedBy to currentAtSign if not set. atKey.sharedBy ??= _atClient.getCurrentAtSign(); atKey.sharedBy = AtClientUtil.fixAtSign(atKey.sharedBy); diff --git a/packages/at_client/lib/src/transformer/request_transformer/notify_request_transformer.dart b/packages/at_client/lib/src/transformer/request_transformer/notify_request_transformer.dart index 471bb29a5..2bbd454b7 100644 --- a/packages/at_client/lib/src/transformer/request_transformer/notify_request_transformer.dart +++ b/packages/at_client/lib/src/transformer/request_transformer/notify_request_transformer.dart @@ -21,8 +21,6 @@ class NotificationRequestTransformer @override Future transform( NotificationParams notificationParams) async { - // If metadata is not set, initialize Metadata instance. - notificationParams.atKey.metadata ??= Metadata(); // prepares notification builder NotifyVerbBuilder builder = await _prepareNotificationBuilder( notificationParams, atClientPreference); @@ -43,8 +41,8 @@ class NotificationRequestTransformer AtClientPreference atClientPreference) async { var builder = NotifyVerbBuilder() ..id = notificationParams.id - ..sharedBy = notificationParams.atKey.sharedBy - ..sharedWith = notificationParams.atKey.sharedWith + ..atKey.sharedBy = notificationParams.atKey.sharedBy + ..atKey.sharedWith = notificationParams.atKey.sharedWith ..operation = notificationParams.operation ..messageType = notificationParams.messageType ..priority = notificationParams.priority @@ -55,15 +53,15 @@ class NotificationRequestTransformer // Append namespace only to message type key. For message type text do not // append namespaces. if (notificationParams.messageType == MessageTypeEnum.key) { - builder.atKey = AtClientUtil.getKeyWithNameSpace( + builder.atKey.key = AtClientUtil.getKeyWithNameSpace( notificationParams.atKey, atClientPreference); } if (notificationParams.messageType == MessageTypeEnum.text) { - if (notificationParams.atKey.metadata!.isEncrypted!) { - builder.atKey = await _encryptNotificationValue( - notificationParams.atKey, notificationParams.atKey.key!); + if (notificationParams.atKey.metadata.isEncrypted) { + builder.atKey.key = await _encryptNotificationValue( + notificationParams.atKey, notificationParams.atKey.key); } else { - builder.atKey = notificationParams.atKey.key; + builder.atKey.key = notificationParams.atKey.key; } } return builder; @@ -71,23 +69,26 @@ class NotificationRequestTransformer void _addMetadataToBuilder( NotifyVerbBuilder builder, NotificationParams notificationParams) { - builder.ttl = notificationParams.atKey.metadata?.ttl; - builder.ttb = notificationParams.atKey.metadata?.ttb; - builder.ttr = notificationParams.atKey.metadata?.ttr; - builder.ccd = notificationParams.atKey.metadata?.ccd; - builder.isPublic = notificationParams.atKey.metadata!.isPublic!; - if (notificationParams.atKey.metadata!.isEncrypted != null) { - builder.isTextMessageEncrypted = - notificationParams.atKey.metadata!.isEncrypted!; - } - builder.sharedKeyEncrypted = - notificationParams.atKey.metadata?.sharedKeyEnc; - builder.pubKeyChecksum = notificationParams.atKey.metadata?.pubKeyCS; - builder.encKeyName = notificationParams.atKey.metadata?.encKeyName; - builder.encAlgo = notificationParams.atKey.metadata?.encAlgo; - builder.ivNonce = notificationParams.atKey.metadata?.ivNonce; - builder.skeEncKeyName = notificationParams.atKey.metadata?.skeEncKeyName; - builder.skeEncAlgo = notificationParams.atKey.metadata?.skeEncAlgo; + builder.atKey.metadata.ttl = notificationParams.atKey.metadata.ttl; + builder.atKey.metadata.ttb = notificationParams.atKey.metadata.ttb; + builder.atKey.metadata.ttr = notificationParams.atKey.metadata.ttr; + builder.atKey.metadata.ccd = notificationParams.atKey.metadata.ccd; + builder.atKey.metadata.isPublic = + notificationParams.atKey.metadata.isPublic; + builder.atKey.metadata.isEncrypted = + notificationParams.atKey.metadata.isEncrypted; + builder.atKey.metadata.sharedKeyEnc = + notificationParams.atKey.metadata.sharedKeyEnc; + builder.atKey.metadata.pubKeyCS = + notificationParams.atKey.metadata.pubKeyCS; + builder.atKey.metadata.encKeyName = + notificationParams.atKey.metadata.encKeyName; + builder.atKey.metadata.encAlgo = notificationParams.atKey.metadata.encAlgo; + builder.atKey.metadata.ivNonce = notificationParams.atKey.metadata.ivNonce; + builder.atKey.metadata.skeEncKeyName = + notificationParams.atKey.metadata.skeEncKeyName; + builder.atKey.metadata.skeEncAlgo = + notificationParams.atKey.metadata.skeEncAlgo; } Future _encryptNotificationValue(AtKey atKey, String value) async { diff --git a/packages/at_client/lib/src/transformer/request_transformer/put_request_transformer.dart b/packages/at_client/lib/src/transformer/request_transformer/put_request_transformer.dart index b3ad7cbe9..017103356 100644 --- a/packages/at_client/lib/src/transformer/request_transformer/put_request_transformer.dart +++ b/packages/at_client/lib/src/transformer/request_transformer/put_request_transformer.dart @@ -39,7 +39,7 @@ class PutRequestTransformer updateVerbBuilder.value = tuple.two; //Encrypt the data for non public keys - if (!atKey.metadata!.isPublic!) { + if (!atKey.metadata.isPublic) { var encryptionService = AtKeyEncryptionManager(_atClient) .get(atKey, _atClient.getCurrentAtSign()!); try { @@ -52,13 +52,15 @@ class PutRequestTransformer ExceptionScenario.encryptionFailed, 'Failed to encrypt the data')); rethrow; } - updateVerbBuilder.sharedKeyEncrypted = atKey.metadata!.sharedKeyEnc; - updateVerbBuilder.pubKeyChecksum = atKey.metadata!.pubKeyCS; - updateVerbBuilder.encKeyName = atKey.metadata!.encKeyName; - updateVerbBuilder.encAlgo = atKey.metadata!.encAlgo; - updateVerbBuilder.ivNonce = atKey.metadata!.ivNonce; - updateVerbBuilder.skeEncKeyName = atKey.metadata!.skeEncKeyName; - updateVerbBuilder.skeEncAlgo = atKey.metadata!.skeEncAlgo; + updateVerbBuilder.atKey.metadata.sharedKeyEnc = + atKey.metadata.sharedKeyEnc; + updateVerbBuilder.atKey.metadata.pubKeyCS = atKey.metadata.pubKeyCS; + updateVerbBuilder.atKey.metadata.encKeyName = atKey.metadata.encKeyName; + updateVerbBuilder.atKey.metadata.encAlgo = atKey.metadata.encAlgo; + updateVerbBuilder.atKey.metadata.ivNonce = atKey.metadata.ivNonce; + updateVerbBuilder.atKey.metadata.skeEncKeyName = + atKey.metadata.skeEncKeyName; + updateVerbBuilder.atKey.metadata.skeEncAlgo = atKey.metadata.skeEncAlgo; } else { if (encryptionPrivateKey.isNull) { throw AtPrivateKeyNotFoundException('Failed to sign the public data'); @@ -66,12 +68,13 @@ class PutRequestTransformer final atSigningInput = AtSigningInput(updateVerbBuilder.value) ..signingMode = AtSigningMode.data; final signingResult = _atClient.atChops!.sign(atSigningInput); - updateVerbBuilder.dataSignature = signingResult.result; + updateVerbBuilder.atKey.metadata.dataSignature = signingResult.result; // Encode the public data if it contains new line characters if (updateVerbBuilder.value.contains('\n')) { updateVerbBuilder.value = AtEncoderImpl().encodeData(updateVerbBuilder.value, encodingType); - updateVerbBuilder.encoding = encodingType.toShortString(); + updateVerbBuilder.atKey.metadata.encoding = + encodingType.toShortString(); } } @@ -82,31 +85,30 @@ class PutRequestTransformer UpdateVerbBuilder _populateUpdateVerbBuilder( AtKey atKey, AtClientPreference atClientPreference) { UpdateVerbBuilder updateVerbBuilder = UpdateVerbBuilder() - ..atKey = AtClientUtil.getKeyWithNameSpace(atKey, atClientPreference) - ..sharedWith = AtClientUtil.fixAtSign(atKey.sharedWith) - ..sharedBy = AtClientUtil.fixAtSign(atKey.sharedBy) - ..isPublic = - (atKey.metadata?.isPublic != null) ? atKey.metadata!.isPublic! : false - ..isEncrypted = (atKey.metadata?.isEncrypted != null) - ? atKey.metadata?.isEncrypted! - : false - ..isBinary = - (atKey.metadata?.isBinary != null) ? atKey.metadata?.isBinary! : false - ..isLocal = atKey.isLocal; + ..atKey = (AtKey() + ..key = AtClientUtil.getKeyWithNameSpace(atKey, atClientPreference) + ..sharedWith = AtClientUtil.fixAtSign(atKey.sharedWith) + ..sharedBy = AtClientUtil.fixAtSign(atKey.sharedBy) + ..isLocal = atKey.isLocal + ..metadata = (Metadata() + ..isPublic = atKey.metadata.isPublic + ..isEncrypted = atKey.metadata.isEncrypted + ..isBinary = atKey.metadata.isBinary)); - if (atKey.metadata!.ttl != null) { - updateVerbBuilder.ttl = atKey.metadata!.ttl; + if (atKey.metadata.ttl != null) { + updateVerbBuilder.atKey.metadata.ttl = atKey.metadata.ttl; } - if (atKey.metadata!.ttb != null) { - updateVerbBuilder.ttb = atKey.metadata!.ttb; + if (atKey.metadata.ttb != null) { + updateVerbBuilder.atKey.metadata.ttb = atKey.metadata.ttb; } - if (atKey.metadata!.ttr != null) { - updateVerbBuilder.ttr = atKey.metadata!.ttr; + if (atKey.metadata.ttr != null) { + updateVerbBuilder.atKey.metadata.ttr = atKey.metadata.ttr; } - if (atKey.metadata!.ccd != null) { - updateVerbBuilder.ccd = atKey.metadata!.ccd; + if (atKey.metadata.ccd != null) { + updateVerbBuilder.atKey.metadata.ccd = atKey.metadata.ccd; } - updateVerbBuilder.dataSignature = atKey.metadata!.dataSignature; + updateVerbBuilder.atKey.metadata.dataSignature = + atKey.metadata.dataSignature; return updateVerbBuilder; } } diff --git a/packages/at_client/lib/src/transformer/response_transformer/get_response_transformer.dart b/packages/at_client/lib/src/transformer/response_transformer/get_response_transformer.dart index 5e97175d8..517b6b09a 100644 --- a/packages/at_client/lib/src/transformer/response_transformer/get_response_transformer.dart +++ b/packages/at_client/lib/src/transformer/response_transformer/get_response_transformer.dart @@ -33,7 +33,7 @@ class GetResponseTransformer decodedResponse['metaData'], _isKeyPublic(decodedResponse['key']), isCached: decodedResponse['key'].startsWith('cached:')); atValue.metadata = metadata; - tuple.one.metadata = metadata; + tuple.one.metadata = metadata!; } // For public and cached public keys, data is not encrypted. @@ -62,9 +62,7 @@ class GetResponseTransformer // After decrypting the data, if data is binary, decode the data // For cached keys, isBinary is not on server-side. Hence getting // isBinary from AtKey. - if (tuple.one.metadata != null && - tuple.one.metadata!.isBinary != null && - tuple.one.metadata!.isBinary!) { + if (tuple.one.metadata.isBinary) { atValue.value = Base2e15.decode(atValue.value); } return atValue; diff --git a/packages/at_client/lib/src/transformer/response_transformer/notification_response_transformer.dart b/packages/at_client/lib/src/transformer/response_transformer/notification_response_transformer.dart index 26474c46b..8d307789f 100644 --- a/packages/at_client/lib/src/transformer/response_transformer/notification_response_transformer.dart +++ b/packages/at_client/lib/src/transformer/response_transformer/notification_response_transformer.dart @@ -50,8 +50,10 @@ class NotificationResponseTransformer AtKey atKey = AtKey() ..key = key ..sharedWith = atNotification.to - ..sharedBy = atNotification.from - ..metadata = atNotification.metadata; + ..sharedBy = atNotification.from; + if (atNotification.metadata != null) { + atKey.metadata = atNotification.metadata!; + } if (atNotification.messageType.isNotNull && atNotification.messageType!.toLowerCase().contains('text') && @@ -65,7 +67,7 @@ class NotificationResponseTransformer // The shared_key (which is a reserved key) has different decryption process // and is not a user created key. // Hence do not decrypt if key's are reserved keys - AtKey.getKeyType(atKey.key!) != KeyType.reservedKey) { + AtKey.getKeyType(atKey.toString()) != KeyType.reservedKey) { // decrypt the value atNotification.value = await _getDecryptedValue(atKey, atNotification.value!); diff --git a/packages/at_client/lib/src/util/at_client_util.dart b/packages/at_client/lib/src/util/at_client_util.dart index 70d81a927..60f585a2a 100644 --- a/packages/at_client/lib/src/util/at_client_util.dart +++ b/packages/at_client/lib/src/util/at_client_util.dart @@ -83,8 +83,12 @@ class AtClientUtil { metadata.ttl = metadataMap[AtConstants.ttl]; metadata.ttb = metadataMap[AtConstants.ttb]; metadata.ccd = metadataMap[AtConstants.ccd]; - metadata.isBinary = metadataMap[AtConstants.isBinary]; - metadata.isEncrypted = metadataMap[AtConstants.isEncrypted]; + metadata.isBinary = (metadataMap[AtConstants.isBinary] == null) + ? false + : metadataMap[AtConstants.isBinary]; + metadata.isEncrypted = (metadataMap[AtConstants.isEncrypted] == null) + ? false + : metadataMap[AtConstants.isEncrypted]; metadata.dataSignature = metadataMap[AtConstants.publicDataSignature]; metadata.sharedKeyEnc = metadataMap[AtConstants.sharedKeyEncrypted]; metadata.pubKeyCS = metadataMap[AtConstants.sharedWithPublicKeyCheckSum]; @@ -107,16 +111,14 @@ class AtClientUtil { /// else namespace is not appended static String getKeyWithNameSpace( AtKey atKey, AtClientPreference atClientPreference) { - // If metadata is null, initialize with new Metadata. - atKey.metadata ??= Metadata(); // Do not append namespace for encryption keys. - if (!(atKey.metadata!.namespaceAware)) { - return atKey.key!; + if (!(atKey.metadata.namespaceAware)) { + return atKey.key; } //Do not append namespace if already appended - if (atKey.key?.substring(atKey.key!.lastIndexOf('.') + 1) == + if (atKey.key.substring(atKey.key.lastIndexOf('.') + 1) == atClientPreference.namespace) { - return atKey.key!; + return atKey.key; } // If key does not have any namespace, append the namespace to the key. if (atKey.namespace.isNotNull) { @@ -125,7 +127,7 @@ class AtClientUtil { if (atClientPreference.namespace.isNotNull) { return '${atKey.key}.${atClientPreference.namespace}'; } - return atKey.key!; + return atKey.key; } // TODO Remove this once AtUtils.fixAtSign accepts and returns String? diff --git a/packages/at_client/lib/src/util/at_client_validation.dart b/packages/at_client/lib/src/util/at_client_validation.dart index 9f814b3e1..81e95fc69 100644 --- a/packages/at_client/lib/src/util/at_client_validation.dart +++ b/packages/at_client/lib/src/util/at_client_validation.dart @@ -97,8 +97,8 @@ class AtClientValidation { } // If key starts with 'cached:' (or) if the metadata of key has isCached set to true; it represent // a cached key. Prevent client updating the cached key. Hence throw exception. - if (atKey.key!.startsWith('${AtConstants.cached}:') || - (atKey.metadata != null && atKey.metadata!.isCached)) { + if (atKey.key.startsWith('${AtConstants.cached}:') || + (atKey.metadata.isCached)) { throw AtKeyException('Cannot create/update a cached key'); } // If namespace is not set on key and in preferences, throw exception diff --git a/packages/at_client/lib/src/util/at_collection_utils.dart b/packages/at_client/lib/src/util/at_collection_utils.dart index 3cdee5787..d4361e745 100644 --- a/packages/at_client/lib/src/util/at_collection_utils.dart +++ b/packages/at_client/lib/src/util/at_collection_utils.dart @@ -20,10 +20,10 @@ class AtCollectionUtil { return AtKey() ..key = key ..metadata = Metadata() - ..metadata!.ttr = -1 + ..metadata.ttr = -1 ..sharedWith = sharedWith - ..metadata!.ttl = ttl - ..metadata!.ttb = ttb + ..metadata.ttl = ttl + ..metadata.ttb = ttb ..sharedBy = _getAtClient().getCurrentAtSign(); } } diff --git a/packages/at_client/pubspec.yaml b/packages/at_client/pubspec.yaml index 71d90afb4..97039aee7 100644 --- a/packages/at_client/pubspec.yaml +++ b/packages/at_client/pubspec.yaml @@ -4,7 +4,7 @@ description: The at_client library is the non-platform specific Client SDK which ## ## ## NB: When incrementing the version, please also increment the version in AtClientConfig file -version: 3.0.71 +version: 3.0.72 ## NB: When incrementing the version, please also increment the version in AtClientConfig file ## @@ -31,12 +31,12 @@ dependencies: async: ^2.9.0 at_utf7: ^1.0.0 at_base2e15: ^1.0.0 - at_commons: ^3.0.57 - at_utils: ^3.0.15 - at_chops: ^1.0.5 - at_lookup: ^3.0.41 + at_commons: ^4.0.0 + at_utils: ^3.0.16 + at_chops: ^1.0.7 + at_lookup: ^3.0.44 at_persistence_spec: ^2.0.14 - at_persistence_secondary_server: ^3.0.59 + at_persistence_secondary_server: ^3.0.60 meta: ^1.8.0 version: ^3.0.2 diff --git a/packages/at_client/test/at_chops_encryption_util_compatibility_test.dart b/packages/at_client/test/at_chops_encryption_util_compatibility_test.dart new file mode 100644 index 000000000..ed75f4f22 --- /dev/null +++ b/packages/at_client/test/at_chops_encryption_util_compatibility_test.dart @@ -0,0 +1,118 @@ +import 'package:at_chops/at_chops.dart'; +import 'package:at_client/at_client.dart'; +import 'package:test/test.dart'; + +void main() { + test( + 'A test to verify encrypting AES key with encryption util and decryption with at_chops', + () { + // Generate RSA key pair. Generate AES key. Encrypt AES key using RSA public key using EncryptionUtil method + // Decrypt encryptedAESKey using AtChops (uses RSA private key) + var encryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair(); + var encryptionPublicKey = encryptionKeyPair.atPublicKey.publicKey; + var aesKey = EncryptionUtil.generateAESKey(); + var encryptedAesKey = + EncryptionUtil.encryptKey(aesKey, encryptionPublicKey); + AtChopsKeys atChopsKeys = AtChopsKeys.create(encryptionKeyPair, null); + var atChops = AtChopsImpl(atChopsKeys); + var decryptedAesKey = atChops + .decryptString(encryptedAesKey, EncryptionKeyType.rsa2048) + .result; + expect(decryptedAesKey, aesKey); + }); + test( + 'A test to verify encrypting AES key with at_chops and decryption with EncryptionUtil', + () { + // Generate RSA key pair. Generate AES key. Encrypt AES key using AtChops(uses RSA public key) + // Decrypt encryptedAESKey with EncryptionUtil using RSA private key + var encryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair(); + var encryptionPrivateKey = encryptionKeyPair.atPrivateKey.privateKey; + var aesKey = AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256).key; + + AtChopsKeys atChopsKeys = AtChopsKeys.create(encryptionKeyPair, null); + var atChops = AtChopsImpl(atChopsKeys); + var encryptedAesKey = + atChops.encryptString(aesKey, EncryptionKeyType.rsa2048).result; + + var decryptedAesKey = + //ignore: deprecated_member_use_from_same_package + EncryptionUtil.decryptKey(encryptedAesKey, encryptionPrivateKey); + expect(decryptedAesKey, aesKey); + }); + + test( + 'A test to verify data encryption with encryption util and decryption with at_chops', + () { + // Generate AES key. Encrypt data with EncryptionUtil using AES key + // Create a AESEncryption algo object using AES key and pass it to AtChops. Decrypt the encrypted value with AtChops + var aesKey = EncryptionUtil.generateAESKey(); + var dataToEncrypt = 'alice@atsign.com'; + var encryptedData = EncryptionUtil.encryptValue(dataToEncrypt, aesKey); + var encryptionAlgo = AESEncryptionAlgo(AESKey(aesKey)); + AtChopsKeys atChopsKeys = AtChopsKeys.create(null, null); + var atChops = AtChopsImpl(atChopsKeys); + var decryptedData = atChops + .decryptString(encryptedData, EncryptionKeyType.aes256, + encryptionAlgorithm: encryptionAlgo, + iv: AtChopsUtil.generateIVLegacy()) + .result; + expect(decryptedData, dataToEncrypt); + }); + + test( + 'A test to verify data encryption with at_chops and decryption with encryption_util', + () { + // Generate AES key. Encrypt data with AtChops using AES key + // Decrypt the encrypted value with EncryptionUtil + var aesKey = AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256); + var dataToEncrypt = 'alice@atsign.com'; + var encryptionAlgo = AESEncryptionAlgo(AESKey(aesKey.key)); + AtChopsKeys atChopsKeys = AtChopsKeys.create(null, null); + var atChops = AtChopsImpl(atChopsKeys); + var encryptedData = atChops + .encryptString(dataToEncrypt, EncryptionKeyType.aes256, + encryptionAlgorithm: encryptionAlgo, + iv: AtChopsUtil.generateIVLegacy()) + .result; + var decryptedData = EncryptionUtil.decryptValue(encryptedData, aesKey.key); + expect(decryptedData, dataToEncrypt); + }); + + test( + 'A test to verify data(with emoji) encryption with encryption util and decryption with at_chops', + () { + // Generate AES key. Encrypt data with EncryptionUtil using AES key + // Create a AESEncryption algo object using AES key and pass it to AtChops. Decrypt the encrypted value with AtChops + var aesKey = EncryptionUtil.generateAESKey(); + var dataToEncrypt = 'alice@🦄🛠'; + var encryptedData = EncryptionUtil.encryptValue(dataToEncrypt, aesKey); + var encryptionAlgo = AESEncryptionAlgo(AESKey(aesKey)); + AtChopsKeys atChopsKeys = AtChopsKeys.create(null, null); + var atChops = AtChopsImpl(atChopsKeys); + var decryptedData = atChops + .decryptString(encryptedData, EncryptionKeyType.aes256, + encryptionAlgorithm: encryptionAlgo, + iv: AtChopsUtil.generateIVLegacy()) + .result; + expect(decryptedData, dataToEncrypt); + }); + + test( + 'A test to verify data(with emoji) encryption with at_chops and decryption with encryption_util', + () { + // Generate AES key. Encrypt data with AtChops using AES key + // Decrypt the encrypted value with EncryptionUtil + var aesKey = AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256); + var dataToEncrypt = 'alice@🦄🛠'; + var encryptionAlgo = AESEncryptionAlgo(AESKey(aesKey.key)); + AtChopsKeys atChopsKeys = AtChopsKeys.create(null, null); + var atChops = AtChopsImpl(atChopsKeys); + var encryptedData = atChops + .encryptString(dataToEncrypt, EncryptionKeyType.aes256, + encryptionAlgorithm: encryptionAlgo, + iv: AtChopsUtil.generateIVLegacy()) + .result; + var decryptedData = EncryptionUtil.decryptValue(encryptedData, aesKey.key); + expect(decryptedData, dataToEncrypt); + }); +} diff --git a/packages/at_client/test/at_client_util_test.dart b/packages/at_client/test/at_client_util_test.dart index fb03942e9..13bf1bb61 100644 --- a/packages/at_client/test/at_client_util_test.dart +++ b/packages/at_client/test/at_client_util_test.dart @@ -1,30 +1,33 @@ import 'package:at_client/src/util/at_client_util.dart'; import 'package:at_commons/at_builders.dart'; +import 'package:at_commons/at_commons.dart'; import 'package:test/test.dart'; void main() { group('A group of update builder tests', () { test('test non public key', () { var builder = UpdateVerbBuilder() - ..atKey = 'privatekey:at_pkam_privatekey'; + ..atKey.key = 'privatekey:at_pkam_privatekey'; var updateKey = builder.buildKey(); expect(updateKey, 'privatekey:at_pkam_privatekey'); }); test('test public key', () { var builder = UpdateVerbBuilder() - ..isPublic = true - ..atKey = 'phone' - ..sharedBy = 'alice'; + ..atKey = (AtKey() + ..key = 'phone' + ..sharedBy = 'alice' + ..metadata = (Metadata()..isPublic = true)); var updateKey = builder.buildKey(); expect(updateKey, 'public:phone@alice'); }); test('test key sharedwith another atsign', () { var builder = UpdateVerbBuilder() - ..sharedWith = 'bob' - ..atKey = 'phone' - ..sharedBy = 'alice'; + ..atKey = (AtKey() + ..key = 'phone' + ..sharedWith = 'bob' + ..sharedBy = 'alice'); var updateKey = builder.buildKey(); expect(updateKey, '@bob:phone@alice'); }); diff --git a/packages/at_client/test/decryption_service_test.dart b/packages/at_client/test/decryption_service_test.dart index 2a1bd08af..c2ed1ed7d 100644 --- a/packages/at_client/test/decryption_service_test.dart +++ b/packages/at_client/test/decryption_service_test.dart @@ -34,8 +34,9 @@ void main() { LocalSecondary mockLocalSecondary = MockLocalSecondary(); var atClientPreferenceWithAtChops = AtClientPreference(); var lookupVerbBuilder = LookupVerbBuilder() - ..atKey = 'phone.wavi' - ..sharedBy = '@alice'; + ..atKey = (AtKey() + ..key = 'phone.wavi' + ..sharedBy = '@alice'); setUp(() { reset(mockAtLookup); diff --git a/packages/at_client/test/encryption_service_test.dart b/packages/at_client/test/encryption_service_test.dart index 85b2f228d..4ab33fc02 100644 --- a/packages/at_client/test/encryption_service_test.dart +++ b/packages/at_client/test/encryption_service_test.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:at_chops/at_chops.dart'; import 'package:at_client/at_client.dart'; import 'package:at_client/src/encryption_service/encryption_manager.dart'; import 'package:at_client/src/encryption_service/self_key_encryption.dart'; @@ -9,7 +10,6 @@ import 'package:at_commons/at_builders.dart'; import 'package:at_persistence_secondary_server/at_persistence_secondary_server.dart'; import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; -import 'package:at_chops/at_chops.dart'; class MockAtClientManager extends Mock implements AtClientManager {} @@ -49,6 +49,8 @@ void main() { when(() => mockAtClient.atChops).thenAnswer((_) => mockAtChops); when(() => mockAtClient.getLocalSecondary()) .thenAnswer((_) => mockLocalSecondary); + when(() => mockAtClient.getRemoteSecondary()) + .thenAnswer((_) => mockRemoteSecondary); mockSigningResult = AtSigningResult()..result = 'mock_signing_result'; registerFallbackValue(FakeAtSigningInput()); when(() => mockAtChops.sign(any())).thenAnswer((_) => mockSigningResult); @@ -76,42 +78,6 @@ void main() { }); }); - group('A group of tests related positive scenario of encryption', () { - test( - 'A test to verify value gets legacy encrypted when self encryption key is available', - () async { - var selfEncryptionKey = 'REqkIcl9HPekt0T7+rZhkrBvpysaPOeC2QL1PVuWlus='; - var value = 'self_key_value'; - when(() => mockLocalSecondary.getEncryptionSelfKey()) - .thenAnswer((_) => Future.value(selfEncryptionKey)); - var selfKeyEncryption = SelfKeyEncryption(mockAtClient); - var encryptedData = await selfKeyEncryption.encrypt( - AtKey.self('phone', namespace: 'wavi').build(), value); - var response = - EncryptionUtil.decryptValue(encryptedData, selfEncryptionKey); - expect(response, value); - }); - - test( - 'A test to verify value gets encrypted when self encryption key is available', - () async { - var selfEncryptionKey = 'REqkIcl9HPekt0T7+rZhkrBvpysaPOeC2QL1PVuWlus='; - var value = 'self_key_value'; - when(() => mockLocalSecondary.getEncryptionSelfKey()) - .thenAnswer((_) => Future.value(selfEncryptionKey)); - var selfKeyEncryption = SelfKeyEncryption(mockAtClient); - - var atKey = AtKey.self('phone', namespace: 'wavi').build(); - atKey.metadata!.ivNonce = EncryptionUtil.generateIV(); - - var encryptedData = await selfKeyEncryption.encrypt(atKey, value); - var response = EncryptionUtil.decryptValue( - encryptedData, selfEncryptionKey, - ivBase64: atKey.metadata!.ivNonce); - expect(response, value); - }); - }); - group('A group of test to sign the public data', () { test('A test to verify the sign the public data', () async { String encryptionPrivateKey = @@ -127,7 +93,7 @@ void main() { ..one = atKey ..two = value, encryptionPrivateKey: encryptionPrivateKey); - assert(updateVerbBuilder.dataSignature != null); + assert(updateVerbBuilder.atKey.metadata.dataSignature != null); }); }); @@ -370,13 +336,14 @@ void main() { when(() => mockLocalSecondary .executeVerb(any(that: EncryptionPublicKeyMatcher()))) .thenAnswer((_) => Future.value(encryptionPublicKey)); - when(() => mockAtChops.decryptString( - encryptedSharedKey, EncryptionKeyType.rsa2048)) - .thenAnswer((_) => (AtEncryptionResult()..result = sharedKey)); - + var encryptionKeyPair = + AtEncryptionKeyPair.create(encryptionPublicKey, encryptionPrivateKey); + AtChopsKeys atChopsKeys = AtChopsKeys.create(encryptionKeyPair, null); + var atChopsImpl = AtChopsImpl(atChopsKeys); + when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl); var encryptedValue = await sharedKeyEncryption.encrypt(atKey, value); - expect(atKey.metadata?.sharedKeyEnc.isNotNull, true); - expect(atKey.metadata?.pubKeyCS.isNotNull, true); + expect(atKey.metadata.sharedKeyEnc.isNotNull, true); + expect(atKey.metadata.pubKeyCS.isNotNull, true); var decryptedSharedKey = // ignore: deprecated_member_use_from_same_package @@ -398,7 +365,7 @@ void main() { var atKey = (AtKey.shared('phone', namespace: 'wavi', sharedBy: '@alice') ..sharedWith('@bob')) .build(); - atKey.metadata!.ivNonce = EncryptionUtil.generateIV(); + atKey.metadata.ivNonce = EncryptionUtil.generateIV(); var value = 'hello'; when(() => mockLocalSecondary @@ -407,10 +374,11 @@ void main() { when(() => mockLocalSecondary .executeVerb(any(that: EncryptionPublicKeyMatcher()))) .thenAnswer((_) => Future.value(encryptionPublicKey)); - when(() => mockAtChops.decryptString( - encryptedSharedKey, EncryptionKeyType.rsa2048)) - .thenAnswer((_) => (AtEncryptionResult()..result = sharedKey)); - + var encryptionKeyPair = + AtEncryptionKeyPair.create(encryptionPublicKey, encryptionPrivateKey); + AtChopsKeys atChopsKeys = AtChopsKeys.create(encryptionKeyPair, null); + var atChopsImpl = AtChopsImpl(atChopsKeys); + when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl); var encryptedValue = await sharedKeyEncryption.encrypt(atKey, value); var decryptedSharedKey = // ignore: deprecated_member_use_from_same_package @@ -418,10 +386,10 @@ void main() { expect(decryptedSharedKey, sharedKey); var decryptedValue = EncryptionUtil.decryptValue( encryptedValue, decryptedSharedKey, - ivBase64: atKey.metadata!.ivNonce); + ivBase64: atKey.metadata.ivNonce); expect(decryptedValue, value); - expect(atKey.metadata?.sharedKeyEnc.isNotNull, true); - expect(atKey.metadata?.pubKeyCS.isNotNull, true); + expect(atKey.metadata.sharedKeyEnc.isNotNull, true); + expect(atKey.metadata.pubKeyCS.isNotNull, true); }); test('test to verify legacy encryption when a new shared key is generated', @@ -453,6 +421,11 @@ void main() { sync: false)).thenAnswer((_) => Future.value('data:1')); when(() => mockLocalSecondary.getEncryptionPublicKey('@alice')) .thenAnswer((_) => Future.value(encryptionPublicKey)); + var encryptionKeyPair = + AtEncryptionKeyPair.create(encryptionPublicKey, encryptionPrivateKey); + AtChopsKeys atChopsKeys = AtChopsKeys.create(encryptionKeyPair, null); + var atChopsImpl = AtChopsImpl(atChopsKeys); + when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl); var atKey = (AtKey.shared('phone', namespace: 'wavi', sharedBy: '@alice') ..sharedWith('@bob')) @@ -466,8 +439,8 @@ void main() { encryptedValue, sharedKeyEncryption.sharedKey, ivBase64: null), originalValue); - expect(atKey.metadata?.sharedKeyEnc.isNotNull, true); - expect(atKey.metadata?.pubKeyCS.isNotNull, true); + expect(atKey.metadata.sharedKeyEnc.isNotNull, true); + expect(atKey.metadata.pubKeyCS.isNotNull, true); }); test('test to verify encryption when a new shared key is generated', @@ -490,14 +463,22 @@ void main() { .thenAnswer((_) => Future.value(encryptionPublicKey)); when(() => mockLocalSecondary.executeVerb( any(that: UpdateEncryptedSharedKeyMatcher()), - sync: true)).thenAnswer((_) => Future.value('data:1')); + sync: false)).thenAnswer((_) => Future.value('data:1')); + when(() => mockRemoteSecondary.executeVerb( + any(that: UpdateEncryptedSharedKeyMatcher()), + sync: false)).thenAnswer((_) => Future.value('data:1')); when(() => mockLocalSecondary.getEncryptionPublicKey('@alice')) .thenAnswer((_) => Future.value(encryptionPublicKey)); + var encryptionKeyPair = + AtEncryptionKeyPair.create(encryptionPublicKey, encryptionPrivateKey); + AtChopsKeys atChopsKeys = AtChopsKeys.create(encryptionKeyPair, null); + var atChopsImpl = AtChopsImpl(atChopsKeys); + when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl); var atKey = (AtKey.shared('phone', namespace: 'wavi', sharedBy: '@alice') ..sharedWith('@bob')) .build(); - atKey.metadata!.ivNonce = EncryptionUtil.generateIV(); + atKey.metadata.ivNonce = EncryptionUtil.generateIV(); var originalValue = 'hello'; var encryptedValue = @@ -505,10 +486,10 @@ void main() { expect( EncryptionUtil.decryptValue( encryptedValue, sharedKeyEncryption.sharedKey, - ivBase64: atKey.metadata!.ivNonce), + ivBase64: atKey.metadata.ivNonce), originalValue); - expect(atKey.metadata?.sharedKeyEnc.isNotNull, true); - expect(atKey.metadata?.pubKeyCS.isNotNull, true); + expect(atKey.metadata.sharedKeyEnc.isNotNull, true); + expect(atKey.metadata.pubKeyCS.isNotNull, true); }); test( @@ -540,7 +521,8 @@ void main() { 'unable to connect to remote secondary')); when(() => mockLocalSecondary.getEncryptionPublicKey('@alice')) .thenAnswer((_) => Future.value(encryptionPublicKey)); - + when(() => mockAtChops.encryptString(any(), EncryptionKeyType.rsa2048)) + .thenAnswer((_) => AtEncryptionResult()..result = 'random'); var atKey = (AtKey.shared('phone', namespace: 'wavi', sharedBy: '@alice') ..sharedWith('@bob')) .build(); @@ -569,7 +551,7 @@ class LLookupEncryptedSharedKeyMatcher extends Matcher { @override bool matches(item, Map matchState) { - if (item is LLookupVerbBuilder && item.atKey!.contains('shared_key')) { + if (item is LLookupVerbBuilder && item.atKey.key.contains('shared_key')) { return true; } return false; @@ -583,7 +565,7 @@ class EncryptionPublicKeyMatcher extends Matcher { @override bool matches(item, Map matchState) { - if (item is LLookupVerbBuilder && item.atKey!.contains('publickey')) { + if (item is LLookupVerbBuilder && item.atKey.key.contains('publickey')) { return true; } return false; @@ -597,7 +579,9 @@ class UpdateEncryptedSharedKeyMatcher extends Matcher { @override bool matches(item, Map matchState) { - if (item is UpdateVerbBuilder && item.atKey!.contains('shared_key')) { + print('inside matches'); + if (item is UpdateVerbBuilder && item.atKey.key.contains('shared_key')) { + print('match'); return true; } return false; diff --git a/packages/at_client/test/full_stack_test.dart b/packages/at_client/test/full_stack_test.dart index 704b7d0fe..7a8997078 100644 --- a/packages/at_client/test/full_stack_test.dart +++ b/packages/at_client/test/full_stack_test.dart @@ -62,8 +62,9 @@ void main() { var myEncryptedBobSharedKey = EncryptionUtil.encryptKey( bobSharedKey, alicesRSAKeyPair.publicKey.toString()); var llookupMySharedKeyForBob = LLookupVerbBuilder() - ..atKey = '${AtConstants.atEncryptionSharedKey}.bob' - ..sharedBy = '@alice'; + ..atKey = (AtKey() + ..key = '${AtConstants.atEncryptionSharedKey}.bob' + ..sharedBy = '@alice'); var victorSymKey = EncryptionUtil.generateAESKey(); var myEncryptedVicSymKey = EncryptionUtil.encryptKey( @@ -137,7 +138,8 @@ void main() { throw SecondaryConnectException( 'Mock remote atServer is unavailable'); } - var val = remotePLookupMap['${builder.atKey}${builder.sharedBy}']; + var val = + remotePLookupMap['${builder.atKey.key}${builder.atKey.sharedBy}']; if (val != null) { return val; } else { @@ -159,7 +161,7 @@ void main() { throw SecondaryConnectException( 'Mock remote atServer is unavailable'); } - var val = remoteLLookupMap[builder.atKeyObj.toString()]; + var val = remoteLLookupMap[builder.atKey.toString()]; if (val != null) { return val; } else { @@ -182,7 +184,7 @@ void main() { throw SecondaryConnectException( 'Mock remote atServer is unavailable'); } - remoteUpdatedMap[builder.atKeyObj.toString()] = builder.value; + remoteUpdatedMap[builder.atKey.toString()] = builder.value; return 'data:${remoteCommitId++}'; }); @@ -199,7 +201,7 @@ void main() { throw SecondaryConnectException( 'Mock remote atServer is unavailable'); } - remoteDeletedSet.add(builder.atKeyObj.toString()); + remoteDeletedSet.add(builder.atKey.toString()); return 'data:${remoteCommitId++}'; }); }); @@ -210,7 +212,7 @@ void main() { var atKey = AtKey.self('test_put').build(); await atClient.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNull); + expect(atKey.metadata.ivNonce, isNull); var atData = await (atClient .getLocalSecondary()! @@ -229,7 +231,7 @@ void main() { var atKey = AtKey.self('test_put').build(); await atClient.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNull); + expect(atKey.metadata.ivNonce, isNull); var atData = await (atClient .getLocalSecondary()! @@ -249,7 +251,7 @@ void main() { var atKey = AtKey.self('test_put').build(); await atClient.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNotNull); + expect(atKey.metadata.ivNonce, isNotNull); var atData = await (atClient .getLocalSecondary()! @@ -265,7 +267,7 @@ void main() { false); expect( EncryptionUtil.decryptValue(cipherText, selfEncryptionKey, - ivBase64: atKey.metadata?.ivNonce), + ivBase64: atKey.metadata.ivNonce), clearText); var getResult = await atClient.get(atKey); @@ -277,7 +279,7 @@ void main() { var atKey = AtKey.self('test_put').build(); await atClient.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNotNull); + expect(atKey.metadata.ivNonce, isNotNull); fullStackPrefs.atProtocolEmitted = Version(1, 5, 0); @@ -295,7 +297,7 @@ void main() { false); expect( EncryptionUtil.decryptValue(cipherText, selfEncryptionKey, - ivBase64: atKey.metadata?.ivNonce), + ivBase64: atKey.metadata.ivNonce), clearText); var getResult = await atClient.get(atKey); @@ -309,7 +311,7 @@ void main() { var atKey = (AtKey.shared('test_put')..sharedWith('@bob')).build(); await atClient.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNull); + expect(atKey.metadata.ivNonce, isNull); var atData = await (atClient .getLocalSecondary()! @@ -328,7 +330,7 @@ void main() { var atKey = (AtKey.shared('test_put')..sharedWith('@bob')).build(); await atClient.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNull); + expect(atKey.metadata.ivNonce, isNull); fullStackPrefs.atProtocolEmitted = Version(1, 5, 0); var atData = await (atClient @@ -348,7 +350,7 @@ void main() { var atKey = (AtKey.shared('test_put')..sharedWith('@bob')).build(); await atClient.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNotNull); + expect(atKey.metadata.ivNonce, isNotNull); var atData = await (atClient .getLocalSecondary()! @@ -366,7 +368,7 @@ void main() { wrappedDecryptSucceeds( cipherText: cipherText, aesKey: selfEncryptionKey, - ivBase64: atKey.metadata?.ivNonce, + ivBase64: atKey.metadata.ivNonce, clearText: clearText), false); expect( @@ -378,7 +380,7 @@ void main() { false); expect( EncryptionUtil.decryptValue(cipherText, bobSharedKey, - ivBase64: atKey.metadata?.ivNonce), + ivBase64: atKey.metadata.ivNonce), clearText); var getResult = await atClient.get(atKey); @@ -390,7 +392,7 @@ void main() { var atKey = (AtKey.shared('test_put')..sharedWith('@bob')).build(); await atClient.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNotNull); + expect(atKey.metadata.ivNonce, isNotNull); fullStackPrefs.atProtocolEmitted = Version(1, 5, 0); var atData = await (atClient @@ -409,7 +411,7 @@ void main() { wrappedDecryptSucceeds( cipherText: cipherText, aesKey: selfEncryptionKey, - ivBase64: atKey.metadata?.ivNonce, + ivBase64: atKey.metadata.ivNonce, clearText: clearText), false); expect( @@ -421,7 +423,7 @@ void main() { false); expect( EncryptionUtil.decryptValue(cipherText, bobSharedKey, - ivBase64: atKey.metadata?.ivNonce), + ivBase64: atKey.metadata.ivNonce), clearText); var getResult = await atClient.get(atKey); @@ -441,12 +443,12 @@ void main() { any(that: isA()), sync: true)).thenAnswer((invocation) async { var builder = invocation.positionalArguments[0] as UpdateVerbBuilder; - if (builder.atKeyObj.toString() == atKey.toString()) { + if (builder.atKey.toString() == atKey.toString()) { print( - 'mockRemoteSecondary.executeVerb with UpdateVerbBuilder for ${builder.atKeyObj.toString()} as expected'); + 'mockRemoteSecondary.executeVerb with UpdateVerbBuilder for ${builder.atKey.toString()} as expected'); executedRemotely = true; return 'data:10'; - } else if (builder.atKeyObj.toString() != '@bob:shared_key@alice') { + } else if (builder.atKey.toString() != '@bob:shared_key@alice') { print(builder.buildCommand()); throw Exception( 'mockRemoteSecondary.executeVerb called with unexpected UpdateVerbBuilder'); @@ -487,7 +489,7 @@ void main() { print('DeleteVerbBuilder: ${builder.buildCommand()}'); if (builder.buildKey() == atKey.toString()) { print( - 'mockRemoteSecondary.executeVerb with DeleteVerbBuilder for ${builder.atKeyObj.toString()} as expected'); + 'mockRemoteSecondary.executeVerb with DeleteVerbBuilder for ${builder.atKey.toString()} as expected'); executedRemotely = true; return 'data:10'; } else { diff --git a/packages/at_client/test/local_secondary_test.dart b/packages/at_client/test/local_secondary_test.dart index 794913bdd..0007ca78f 100644 --- a/packages/at_client/test/local_secondary_test.dart +++ b/packages/at_client/test/local_secondary_test.dart @@ -35,6 +35,7 @@ class MockSecondaryKeyStore extends Mock implements SecondaryKeyStore { waviOtherNonHiddenKey, otherWaviOtherNonHiddenKey ]; + @override List getKeys({String? regex}) { if (regex != null) { @@ -151,10 +152,11 @@ void main() { atClientManager: atClientManager); final localSecondary = LocalSecondary(atClient); final verbBuilder = UpdateVerbBuilder() - ..isPublic = true - ..value = 'alice@gmail.com' - ..atKey = 'email' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = 'email' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)) + ..value = 'alice@gmail.com'; final executeResult = await localSecondary.executeVerb(verbBuilder, sync: false); expect(executeResult, isNotNull); @@ -170,15 +172,17 @@ void main() { atClientManager: atClientManager); final localSecondary = LocalSecondary(atClient); final verbBuilder = UpdateVerbBuilder() - ..isPublic = true - ..value = 'alice@gmail.com' - ..atKey = 'email' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = 'email' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)) + ..value = 'alice@gmail.com'; await localSecondary.executeVerb(verbBuilder, sync: false); final llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = 'email' - ..sharedBy = atSign - ..isPublic = true; + ..atKey = (AtKey() + ..key = 'email' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)); final llookupResult = await localSecondary.executeVerb(llookupVerbBuilder, sync: false); expect(llookupResult, 'data:alice@gmail.com'); @@ -193,20 +197,23 @@ void main() { atClientManager: atClientManager); final localSecondary = LocalSecondary(atClient); final verbBuilder = UpdateVerbBuilder() - ..isPublic = true - ..value = 'alice@gmail.com' - ..atKey = 'email' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = 'email' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)) + ..value = 'alice@gmail.com'; await localSecondary.executeVerb(verbBuilder, sync: false); final deleteVerbBuilder = DeleteVerbBuilder() - ..atKey = 'email' - ..sharedBy = atSign - ..isPublic = true; + ..atKey = (AtKey() + ..key = 'email' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)); await localSecondary.executeVerb(deleteVerbBuilder, sync: false); final llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = 'email' - ..sharedBy = atSign - ..isPublic = true; + ..atKey = (AtKey() + ..key = 'email' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)); expect(localSecondary.executeVerb(llookupVerbBuilder, sync: false), throwsA(isA())); }); @@ -220,15 +227,17 @@ void main() { atClientManager: atClientManager); final localSecondary = LocalSecondary(atClient); final verbBuilder_1 = UpdateVerbBuilder() - ..isPublic = true - ..value = 'alice@gmail.com' - ..atKey = 'email' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = 'email' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)) + ..value = 'alice@gmail.com'; await localSecondary.executeVerb(verbBuilder_1, sync: false); final verbBuilder_2 = UpdateVerbBuilder() - ..value = '+101-202-303' - ..atKey = 'phone' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = 'phone' + ..sharedBy = atSign) + ..value = '+101-202-303'; await localSecondary.executeVerb(verbBuilder_2, sync: false); final scanVerbBuilder = ScanVerbBuilder(); final scanResult = diff --git a/packages/at_client/test/notification_service_test.dart b/packages/at_client/test/notification_service_test.dart index bf5dfd7ee..fb3f570c3 100644 --- a/packages/at_client/test/notification_service_test.dart +++ b/packages/at_client/test/notification_service_test.dart @@ -65,8 +65,8 @@ class MockSharedKeyEncryptionImpl extends Mock implements SharedKeyEncryption { //Set encryptionMetadata to atKey metadata atKey.metadata = Metadata(); if (storeSharedKeyEncryptedWithData) { - atKey.metadata!.sharedKeyEnc = 'sharedKeyEnc'; - atKey.metadata!.pubKeyCS = 'publicKeyCS'; + atKey.metadata.sharedKeyEnc = 'sharedKeyEnc'; + atKey.metadata.pubKeyCS = 'publicKeyCS'; } return 'encryptedValue'; } @@ -119,8 +119,8 @@ void main() { AtClientPreference()..namespace = 'wavi', SharedKeyEncryption(mockAtClientImpl)) .transform(notificationParams); - expect(notifyVerbBuilder.atKey, 'phone.wavi'); - expect(notifyVerbBuilder.sharedWith, '@bob'); + expect(notifyVerbBuilder.atKey.key, 'phone.wavi'); + expect(notifyVerbBuilder.atKey.sharedWith, '@bob'); expect(notifyVerbBuilder.messageType, MessageTypeEnum.key); expect(notifyVerbBuilder.priority, PriorityEnum.low); expect(notifyVerbBuilder.strategy, StrategyEnum.all); @@ -145,14 +145,14 @@ void main() { AtClientPreference()..namespace = 'wavi', mockSharedKeyEncryptionImpl) .transform(notificationParams); - expect(notifyVerbBuilder.atKey, 'phone.wavi'); - expect(notifyVerbBuilder.sharedWith, '@bob'); + expect(notifyVerbBuilder.atKey.key, 'phone.wavi'); + expect(notifyVerbBuilder.atKey.sharedWith, '@bob'); expect(notifyVerbBuilder.messageType, MessageTypeEnum.key); expect(notifyVerbBuilder.priority, PriorityEnum.high); expect(notifyVerbBuilder.strategy, StrategyEnum.latest); expect(notifyVerbBuilder.value, 'encryptedValue'); - expect(notifyVerbBuilder.sharedKeyEncrypted, 'sharedKeyEnc'); - expect(notifyVerbBuilder.pubKeyChecksum, 'publicKeyCS'); + expect(notifyVerbBuilder.atKey.metadata.sharedKeyEnc, 'sharedKeyEnc'); + expect(notifyVerbBuilder.atKey.metadata.pubKeyCS, 'publicKeyCS'); expect(notifyVerbBuilder.notifier, 'test-notifier'); expect(notifyVerbBuilder.latestN, 2); expect(notifyVerbBuilder.ttln, Duration(minutes: 1).inMilliseconds); @@ -169,8 +169,8 @@ void main() { mockSharedKeyEncryptionImpl) .transform(notificationParams); //upper case should be preserved in forText notifications - expect(notifyVerbBuilder.atKey, 'Hi How are you'); - expect(notifyVerbBuilder.sharedWith, '@bob'); + expect(notifyVerbBuilder.atKey.key, 'Hi How are you'); + expect(notifyVerbBuilder.atKey.sharedWith, '@bob'); expect(notifyVerbBuilder.messageType, MessageTypeEnum.text); expect(notifyVerbBuilder.priority, PriorityEnum.low); expect(notifyVerbBuilder.strategy, StrategyEnum.all); @@ -187,8 +187,8 @@ void main() { AtClientPreference()..namespace = 'wavi', mockSharedKeyEncryptionImpl) .transform(notificationParams); - expect(notifyVerbBuilder.atKey, 'encryptedValue'); - expect(notifyVerbBuilder.sharedWith, '@bob'); + expect(notifyVerbBuilder.atKey.key, 'encryptedValue'); + expect(notifyVerbBuilder.atKey.sharedWith, '@bob'); expect(notifyVerbBuilder.messageType, MessageTypeEnum.text); expect(notifyVerbBuilder.priority, PriorityEnum.low); expect(notifyVerbBuilder.strategy, StrategyEnum.all); @@ -486,7 +486,7 @@ void main() { NotificationParams notificationParams = NotificationParams.forUpdate(atKey, value: value); NotifyVerbBuilder notifyVerbBuilder = NotifyVerbBuilder() - ..atKey = atKey.toString() + ..atKey = atKey ..messageType = MessageTypeEnum.key ..value = 'demo-value'; @@ -509,7 +509,7 @@ void main() { NotificationParams notificationParams = NotificationParams.forText('Hello bob', '@bob'); NotifyVerbBuilder notifyVerbBuilder = NotifyVerbBuilder() - ..atKey = '@bob:Hello bob'; + ..atKey.key = '@bob:Hello bob'; expect( () => notificationServiceImpl.notificationValueValidation( @@ -1117,7 +1117,7 @@ class StatsAtKeyMatcher extends Matcher { @override bool matches(item, Map matchState) { - if (item is AtKey && item.key!.contains('_latestNotificationIdv2')) { + if (item is AtKey && item.key.contains('_latestNotificationIdv2')) { return true; } return false; diff --git a/packages/at_client/test/put_request_test.dart b/packages/at_client/test/put_request_test.dart index c80bafc93..22425e73b 100644 --- a/packages/at_client/test/put_request_test.dart +++ b/packages/at_client/test/put_request_test.dart @@ -62,10 +62,12 @@ void main() { .transform(tuple, encryptionPrivateKey: encryptionPrivateKey); expect(updateVerbBuilder.value.contains('\n'), expectedResults['isNewLineCharPresentInOutput']); - expect(updateVerbBuilder.encoding, expectedResults['encoding']); - expect(updateVerbBuilder.dataSignature.isNotNull, + expect(updateVerbBuilder.atKey.metadata.encoding, + expectedResults['encoding']); + expect(updateVerbBuilder.atKey.metadata.dataSignature.isNotNull, expectedResults['isDataSignaturePresent']); - final dataSignatureWithoutAtChops = updateVerbBuilder.dataSignature; + final dataSignatureWithoutAtChops = + updateVerbBuilder.atKey.metadata.dataSignature; when(() => mockAtClient.getPreferences()) .thenAnswer((_) => atClientPreferenceWithAtChops); @@ -75,10 +77,12 @@ void main() { encryptionPrivateKey: encryptionPrivateKey); expect(updateVerbBuilder.value.contains('\n'), expectedResults['isNewLineCharPresentInOutput']); - expect(updateVerbBuilder.encoding, expectedResults['encoding']); - expect(updateVerbBuilder.dataSignature.isNotNull, + expect(updateVerbBuilder.atKey.metadata.encoding, + expectedResults['encoding']); + expect(updateVerbBuilder.atKey.metadata.dataSignature.isNotNull, expectedResults['isDataSignaturePresent']); - expect(updateVerbBuilder.dataSignature, dataSignatureWithoutAtChops); + expect(updateVerbBuilder.atKey.metadata.dataSignature, + dataSignatureWithoutAtChops); }); }); }); diff --git a/packages/at_client/test/remote_secondary_test.dart b/packages/at_client/test/remote_secondary_test.dart index d83a0ed7e..050e40594 100644 --- a/packages/at_client/test/remote_secondary_test.dart +++ b/packages/at_client/test/remote_secondary_test.dart @@ -64,8 +64,9 @@ void main() { test('executeAndParse using llookup', () async { String fakeLookupData = 'data:lookup data stub'; LookupVerbBuilder lookupVerbBuilder = LookupVerbBuilder() - ..atKey = 'dummy_key' - ..sharedBy = '@alice'; + ..atKey = (AtKey() + ..key = 'dummy_key' + ..sharedBy = '@alice'); when(() => mockAtLookUp.executeVerb(lookupVerbBuilder)) .thenAnswer((_) async => fakeLookupData); RemoteSecondary remoteSecondary = diff --git a/packages/at_client/test/self_key_encryption_test.dart b/packages/at_client/test/self_key_encryption_test.dart new file mode 100644 index 000000000..671c47a10 --- /dev/null +++ b/packages/at_client/test/self_key_encryption_test.dart @@ -0,0 +1,78 @@ +import 'package:at_chops/at_chops.dart'; +import 'package:at_client/src/decryption_service/self_key_decryption.dart'; +import 'package:at_client/src/encryption_service/self_key_encryption.dart'; +import 'package:at_commons/at_builders.dart'; +import 'package:test/test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:at_client/at_client.dart'; +import 'package:at_lookup/at_lookup.dart'; + +class MockAtClientImpl extends Mock implements AtClient {} + +class MockLocalSecondary extends Mock implements LocalSecondary {} + +class MockRemoteSecondary extends Mock implements RemoteSecondary {} + +class MockAtLookupImpl extends Mock implements AtLookUp {} + +class FakeLocalLookUpVerbBuilder extends Fake implements LLookupVerbBuilder {} + +void main() { + AtClient mockAtClient = MockAtClientImpl(); + AtLookUp mockAtLookUp = MockAtLookupImpl(); + LocalSecondary mockLocalSecondary = MockLocalSecondary(); + RemoteSecondary mockRemoteSecondary = MockRemoteSecondary(); + setUp(() { + reset(mockAtLookUp); + when(() => mockAtClient.getLocalSecondary()) + .thenAnswer((_) => mockLocalSecondary); + when(() => mockAtClient.getRemoteSecondary()) + .thenAnswer((_) => mockRemoteSecondary); + + registerFallbackValue(FakeLocalLookUpVerbBuilder()); + }); + + test('test to check encryption/decryption of self keys', () async { + // This test encrypts a self key value and then checks whether decrypted value is same as original value + // If @alice wants to maintain a location without sharing to anyone then the key-value format will be @alice:location@alice New Jersey + // @alice uses self encryption AES key generated during onboarding process to encrypt the value. Same key is used for decryption + var selfKeyEncryption = SelfKeyEncryption(mockAtClient); + var selfKeyDecryption = SelfKeyDecryption(mockAtClient); + // generate new AES key for the test + var aliceSelfEncryptionKey = + AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256).key; + // set atChops + AtChopsKeys atChopsKeys = AtChopsKeys.create(null, null); + atChopsKeys.selfEncryptionKey = AESKey(aliceSelfEncryptionKey); + var atChopsImpl = AtChopsImpl(atChopsKeys); + when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl); + when(() => mockLocalSecondary.getEncryptionSelfKey()) + .thenAnswer((_) => Future.value(aliceSelfEncryptionKey)); + var selfKey = AtKey() + ..sharedBy = '@alice' + ..sharedWith = '@bob' + ..key = 'location'; + var location = 'New Jersey'; + var encryptedValue = await selfKeyEncryption.encrypt(selfKey, location); + expect(encryptedValue != location, true); + var decryptionResult = + await selfKeyDecryption.decrypt(selfKey, encryptedValue); + expect(decryptionResult, location); + }); + test( + 'test to check self key encryption throws exception when passed value is not string type', + () async { + var selfKeyEncryption = SelfKeyEncryption(mockAtClient); + var selfKey = AtKey() + ..sharedBy = '@alice' + ..sharedWith = '@bob' + ..key = 'location'; + var locations = ['new jersey', 'new york']; + expect( + () async => await selfKeyEncryption.encrypt(selfKey, locations), + throwsA(predicate((dynamic e) => + e is AtEncryptionException && + e.message == + 'Invalid value type found: List. Valid value type is String'))); + }); +} diff --git a/packages/at_client/test/shared_key_encryption_test.dart b/packages/at_client/test/shared_key_encryption_test.dart new file mode 100644 index 000000000..5f3e31328 --- /dev/null +++ b/packages/at_client/test/shared_key_encryption_test.dart @@ -0,0 +1,391 @@ +import 'package:at_chops/at_chops.dart'; +import 'package:at_client/src/decryption_service/shared_key_decryption.dart'; +import 'package:at_client/src/encryption_service/shared_key_encryption.dart'; +import 'package:at_commons/at_builders.dart'; +import 'package:test/test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:at_client/at_client.dart'; +import 'package:at_lookup/at_lookup.dart'; + +class MockAtClientImpl extends Mock implements AtClient {} + +class MockLocalSecondary extends Mock implements LocalSecondary {} + +class MockRemoteSecondary extends Mock implements RemoteSecondary {} + +class MockAtLookupImpl extends Mock implements AtLookUp {} + +class FakeLocalLookUpVerbBuilder extends Fake implements LLookupVerbBuilder {} + +class FakeDeleteVerbBuilder extends Fake implements DeleteVerbBuilder {} + +void main() { + AtClient mockAtClient = MockAtClientImpl(); + AtLookUp mockAtLookUp = MockAtLookupImpl(); + LocalSecondary mockLocalSecondary = MockLocalSecondary(); + RemoteSecondary mockRemoteSecondary = MockRemoteSecondary(); + setUp(() { + reset(mockAtLookUp); + when(() => mockAtClient.getLocalSecondary()) + .thenAnswer((_) => mockLocalSecondary); + when(() => mockAtClient.getRemoteSecondary()) + .thenAnswer((_) => mockRemoteSecondary); + + registerFallbackValue(FakeLocalLookUpVerbBuilder()); + registerFallbackValue(FakeDeleteVerbBuilder()); + }); + + test( + 'test to verify encryption and decryption of a key shared by @alice with @bob - without IV', + () async { + // This test verifies encryption and decryption of a shared key value without using Initialization vector(IV) + // Value of a shared key is encrypted and then test asserts whether decrypted value is same as original value + // If @alice wants to share location value with bob, then key-value format is @bob:location@alice California + // @alice will generate a AES key and will encrypt the location value - California + // The AES key will be encrypted with @bob's public key and stored in @bob:shared_key@alice + // When @bob wants to decrypt the @alice's location, @bob will read the encrypted AES key from @bob:shared_key@alice + // @bob will decrypt the AES key using @bob's private key + // @bob will decrypt the location value - California with AES key + + var sharedKeyEncryption = SharedKeyEncryption(mockAtClient); + var bobMockAtClient = MockAtClientImpl(); + var bobMockLocalSecondary = MockLocalSecondary(); + // set up encryption key pair for @alice. This will be used during encryption process + var aliceEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair(); + var aliceEncryptionPublicKey = aliceEncryptionKeyPair.atPublicKey.publicKey; + // Set up encryption key pair for @bob. This will be used during decryption process + var bobEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair(); + var bobEncryptionPublicKey = bobEncryptionKeyPair.atPublicKey.publicKey; + + // Generate the AES for encrypting the location value + var aesSharedKey = + AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256).key; + // local copy of the AES key that @alice maintains - shared_key.bob@alice + var sharedKeyEncryptedWithAlicePublicKey = + EncryptionUtil.encryptKey(aesSharedKey, aliceEncryptionPublicKey); + + // set atChops for bob + AtChopsKeys bobAtChopsKeys = AtChopsKeys.create(bobEncryptionKeyPair, null); + var bobAtChopsImpl = AtChopsImpl(bobAtChopsKeys); + when(() => bobMockAtClient.atChops).thenAnswer((_) => bobAtChopsImpl); + when(() => bobMockAtClient.getLocalSecondary()) + .thenAnswer((_) => bobMockLocalSecondary); + when(() => bobMockAtClient.getCurrentAtSign()).thenReturn('@bob'); + when(() => bobMockLocalSecondary.getEncryptionPublicKey('@bob')) + .thenAnswer((_) => Future.value(bobEncryptionPublicKey)); + var sharedKeyDecryption = SharedKeyDecryption(bobMockAtClient); + + // encrypted AES key @bob:shared_key@alice + var sharedKeyEncryptedWithBobPublicKey = + EncryptionUtil.encryptKey(aesSharedKey, bobEncryptionPublicKey); + + var bobPublicKeyCheckSum = + EncryptionUtil.md5CheckSum(bobEncryptionPublicKey); + var location = 'California'; + + // set atChops for alice + AtChopsKeys atChopsKeys = AtChopsKeys.create(aliceEncryptionKeyPair, null); + var atChopsImpl = AtChopsImpl(atChopsKeys); + when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl); + when(() => mockAtClient.getCurrentAtSign()).thenReturn('@alice'); + when(() => mockLocalSecondary.getEncryptionPublicKey('@alice')) + .thenAnswer((_) => Future.value(aliceEncryptionPublicKey)); + when(() => mockLocalSecondary.executeVerb(any())) + .thenAnswer((Invocation invocation) { + final builder = invocation.positionalArguments[0] as LLookupVerbBuilder; + final buildKeyValue = builder.buildKey(); + if (buildKeyValue == 'shared_key.bob@alice') { + return Future.value('data:$sharedKeyEncryptedWithAlicePublicKey'); + } else if (buildKeyValue == 'cached:public:publickey@bob') { + return Future.value('data:$bobEncryptionPublicKey'); + } else if (buildKeyValue == '@bob:shared_key@alice') { + return Future.value('data:$sharedKeyEncryptedWithBobPublicKey'); + } else { + return Future.value('data:null'); + } + }); + var sharedKey = AtKey() + ..sharedBy = '@alice' + ..sharedWith = '@bob' + ..key = 'location'; + sharedKey.metadata = (Metadata()..pubKeyCS = bobPublicKeyCheckSum); + var encryptionResult = + await sharedKeyEncryption.encrypt(sharedKey, location); + expect(encryptionResult != location, true); + var decryptionResult = + await sharedKeyDecryption.decrypt(sharedKey, encryptionResult); + expect(decryptionResult, location); + }); + + test( + 'test to verify encryption and decryption of a key shared by @alice with @bob - with IV', + () async { + // This test verifies encryption and decryption of a shared key value by using Initialization vector(IV) + // If @alice wants to share location value with bob, then key-value format is @bob:location@alice California + // @alice will generate a AES key and will encrypt the location value - California + // The AES key will be encrypted with @bob's public key and stored in @bob:shared_key@alice + // When @bob wants to decrypt the @alice's location, @bob will read the encrypted AES key from @bob:shared_key@alice + // @bob will decrypt the AES key using @bob's private key + // @bob will decrypt the location value - California with AES key + + var sharedKeyEncryption = SharedKeyEncryption(mockAtClient); + var bobMockAtClient = MockAtClientImpl(); + var bobMockLocalSecondary = MockLocalSecondary(); + // set up encryption key pair for @alice. This will be used during encryption process + var aliceEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair(); + var aliceEncryptionPublicKey = aliceEncryptionKeyPair.atPublicKey.publicKey; + // Set up encryption key pair for @bob. This will be used during decryption process + var bobEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair(); + var bobEncryptionPublicKey = bobEncryptionKeyPair.atPublicKey.publicKey; + + // Generate the AES for encrypting the location value + var aesSharedKey = + AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256).key; + // set atChops for bob + AtChopsKeys bobAtChopsKeys = AtChopsKeys.create(bobEncryptionKeyPair, null); + var bobAtChopsImpl = AtChopsImpl(bobAtChopsKeys); + when(() => bobMockAtClient.atChops).thenAnswer((_) => bobAtChopsImpl); + when(() => bobMockAtClient.getLocalSecondary()) + .thenAnswer((_) => bobMockLocalSecondary); + when(() => bobMockAtClient.getCurrentAtSign()).thenReturn('@bob'); + when(() => bobMockLocalSecondary.getEncryptionPublicKey('@bob')) + .thenAnswer((_) => Future.value(bobEncryptionPublicKey)); + var sharedKeyDecryption = SharedKeyDecryption(bobMockAtClient); + + // encrypted AES key @bob:shared_key@alice + var sharedKeyEncryptedWithBobPublicKey = + EncryptionUtil.encryptKey(aesSharedKey, bobEncryptionPublicKey); + + // local copy of the AES key that @alice maintains - shared_key.bob@alice + var sharedKeyEncryptedWithAlicePublicKey = + EncryptionUtil.encryptKey(aesSharedKey, aliceEncryptionPublicKey); + + var bobPublicKeyCheckSum = + EncryptionUtil.md5CheckSum(bobEncryptionPublicKey); + var location = 'California'; + + // set atChops for alice + AtChopsKeys atChopsKeys = AtChopsKeys.create(aliceEncryptionKeyPair, null); + var atChopsImpl = AtChopsImpl(atChopsKeys); + when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl); + when(() => mockAtClient.getCurrentAtSign()).thenReturn('@alice'); + when(() => mockLocalSecondary.getEncryptionPublicKey('@alice')) + .thenAnswer((_) => Future.value(aliceEncryptionPublicKey)); + when(() => mockLocalSecondary.executeVerb(any())) + .thenAnswer((Invocation invocation) { + final builder = invocation.positionalArguments[0] as LLookupVerbBuilder; + final buildKeyValue = builder.buildKey(); + if (buildKeyValue == 'shared_key.bob@alice') { + return Future.value('data:$sharedKeyEncryptedWithAlicePublicKey'); + } else if (buildKeyValue == 'cached:public:publickey@bob') { + return Future.value('data:$bobEncryptionPublicKey'); + } else if (buildKeyValue == '@bob:shared_key@alice') { + return Future.value('data:$sharedKeyEncryptedWithBobPublicKey'); + } else { + return Future.value('data:null'); + } + }); + var sharedKey = AtKey() + ..sharedBy = '@alice' + ..sharedWith = '@bob' + ..key = 'location'; + // random IV string + var ivBase64String = 'YmFzZTY0IGVuY29kaW5n'; + sharedKey.metadata = Metadata() + ..pubKeyCS = bobPublicKeyCheckSum + ..ivNonce = ivBase64String; + var encryptionResult = + await sharedKeyEncryption.encrypt(sharedKey, location); + expect(encryptionResult != location, true); + var decryptionResult = + await sharedKeyDecryption.decrypt(sharedKey, encryptionResult); + expect(decryptionResult, location); + }); + test( + 'test to verify encryption and decryption of a key shared by @alice with @bob - without IV - local copy of shared AES key is null', + () async { + // This test verifies encryption and decryption of a shared key value without using Initialization vector(IV) + // Local copy shared_key.bob@alice is null. Remote copy shared_key.bob@alice exists in @alice secondary + // Value of a shared key is encrypted and then test asserts whether decrypted value is same as original value + // If @alice wants to share location value with bob, then key-value format is @bob:location@alice California + // @alice will generate a AES key and will encrypt the location value - California + // The AES key will be encrypted with @bob's public key and stored in @bob:shared_key@alice + // When @bob wants to decrypt the @alice's location, @bob will read the encrypted AES key from @bob:shared_key@alice + // @bob will decrypt the AES key using @bob's private key + // @bob will decrypt the location value - California with AES key + + var sharedKeyEncryption = SharedKeyEncryption(mockAtClient); + var bobMockAtClient = MockAtClientImpl(); + var bobMockLocalSecondary = MockLocalSecondary(); + // set up encryption key pair for @alice. This will be used during encryption process + var aliceEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair(); + var aliceEncryptionPublicKey = aliceEncryptionKeyPair.atPublicKey.publicKey; + // Set up encryption key pair for @bob. This will be used during decryption process + var bobEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair(); + var bobEncryptionPublicKey = bobEncryptionKeyPair.atPublicKey.publicKey; + + // Generate the AES for encrypting the location value + var aesSharedKey = + AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256).key; + + // remote copy of the AES key from @alice secondary - shared_key.bob@alice + var sharedKeyEncryptedWithAlicePublicKey = + EncryptionUtil.encryptKey(aesSharedKey, aliceEncryptionPublicKey); + + // encrypted AES key @bob:shared_key@alice + var sharedKeyEncryptedWithBobPublicKey = + EncryptionUtil.encryptKey(aesSharedKey, bobEncryptionPublicKey); + + // set atChops for bob + AtChopsKeys bobAtChopsKeys = AtChopsKeys.create(bobEncryptionKeyPair, null); + var bobAtChopsImpl = AtChopsImpl(bobAtChopsKeys); + when(() => bobMockAtClient.atChops).thenAnswer((_) => bobAtChopsImpl); + when(() => bobMockAtClient.getLocalSecondary()) + .thenAnswer((_) => bobMockLocalSecondary); + when(() => bobMockAtClient.getCurrentAtSign()).thenReturn('@bob'); + when(() => bobMockLocalSecondary.getEncryptionPublicKey('@bob')) + .thenAnswer((_) => Future.value(bobEncryptionPublicKey)); + var sharedKeyDecryption = SharedKeyDecryption(bobMockAtClient); + + var bobPublicKeyCheckSum = + EncryptionUtil.md5CheckSum(bobEncryptionPublicKey); + var location = 'California'; + + // set atChops for alice + AtChopsKeys atChopsKeys = AtChopsKeys.create(aliceEncryptionKeyPair, null); + var atChopsImpl = AtChopsImpl(atChopsKeys); + when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl); + when(() => mockAtClient.getCurrentAtSign()).thenReturn('@alice'); + when(() => mockLocalSecondary.getEncryptionPublicKey('@alice')) + .thenAnswer((_) => Future.value(aliceEncryptionPublicKey)); + when(() => + mockLocalSecondary.executeVerb( + any(that: LLookupLocalSharedKeyMatcher()))).thenAnswer((_) => + throw KeyNotFoundException('local key shared_key.bob@alice not found')); + when(() => mockLocalSecondary.executeVerb( + any(that: DeleteLocalSharedKeyMatcher()), + sync: false)).thenAnswer((_) => Future.value('data:1')); + when(() => mockLocalSecondary.executeVerb( + any(that: UpdateLocalSharedKeyMatcher()), + sync: false)).thenAnswer((_) => Future.value('data:2')); + when(() => mockRemoteSecondary.executeVerb( + any(that: LLookupLocalSharedKeyMatcher()), + sync: false)) + .thenAnswer( + (_) => Future.value('data:$sharedKeyEncryptedWithAlicePublicKey')); + when(() => mockLocalSecondary + .executeVerb(any(that: LLookupTheirSharedKeyMatcher()))) + .thenAnswer( + (_) => Future.value('data:$sharedKeyEncryptedWithBobPublicKey')); + when(() => mockLocalSecondary + .executeVerb(any(that: LLookupCachedBobPublicKeyMatcher()))) + .thenAnswer((_) => Future.value('data:$bobEncryptionPublicKey')); + var sharedKey = AtKey() + ..sharedBy = '@alice' + ..sharedWith = '@bob' + ..key = 'location'; + sharedKey.metadata = (Metadata()..pubKeyCS = bobPublicKeyCheckSum); + var encryptionResult = + await sharedKeyEncryption.encrypt(sharedKey, location); + expect(encryptionResult != location, true); + var decryptionResult = + await sharedKeyDecryption.decrypt(sharedKey, encryptionResult); + expect(decryptionResult, location); + }); + + test( + 'test to check shared key encryption throws exception when passed value is not string type', + () async { + var sharedKeyEncryption = SharedKeyEncryption(mockAtClient); + var selfKey = AtKey() + ..sharedBy = '@alice' + ..sharedWith = '@bob' + ..key = 'location'; + var locations = ['new jersey', 'new york']; + expect( + () async => await sharedKeyEncryption.encrypt(selfKey, locations), + throwsA(predicate((dynamic e) => + e is AtEncryptionException && + e.message == + 'Invalid value type found: List. Valid value type is String'))); + }); +} + +class LLookupLocalSharedKeyMatcher extends Matcher { + @override + Description describe(Description description) => description + .add('A custom matcher to match LOOKUPS of encrypted shared key'); + + @override + bool matches(item, Map matchState) { + if (item is LLookupVerbBuilder && item.atKey.key == 'shared_key.bob') { + return true; + } + return false; + } +} + +class LLookupCachedBobPublicKeyMatcher extends Matcher { + @override + Description describe(Description description) => description + .add('A custom matcher to match LOOKUPS of encrypted shared key'); + + @override + bool matches(item, Map matchState) { + if (item is LLookupVerbBuilder && + item.atKey.key == 'publickey' && + item.atKey.sharedBy == '@bob' && + item.atKey.metadata.isPublic == true) { + return true; + } + return false; + } +} + +class LLookupTheirSharedKeyMatcher extends Matcher { + @override + Description describe(Description description) => description + .add('A custom matcher to match LOOKUPS of encrypted shared key'); + + @override + bool matches(item, Map matchState) { + if (item is LLookupVerbBuilder && + item.atKey.key == 'shared_key' && + item.atKey.sharedWith == '@bob' && + item.atKey.sharedBy == '@alice') { + return true; + } + return false; + } +} + +class UpdateLocalSharedKeyMatcher extends Matcher { + @override + Description describe(Description description) => description + .add('A custom matcher to match UPDATE of encrypted shared key'); + + @override + bool matches(item, Map matchState) { + if (item is UpdateVerbBuilder && item.atKey.key == 'shared_key.bob') { + return true; + } + return false; + } +} + +class DeleteLocalSharedKeyMatcher extends Matcher { + @override + Description describe(Description description) => description + .add('A custom matcher to match Deletes of encrypted shared key'); + + @override + bool matches(item, Map matchState) { + if (item is DeleteVerbBuilder && + item.atKey.key == 'shared_key' && + item.atKey.sharedWith == '@bob' && + item.atKey.sharedBy == '@alice') { + return true; + } + return false; + } +} diff --git a/packages/at_client/test/sync_new_test.dart b/packages/at_client/test/sync_new_test.dart index 26e11746d..1a816fb38 100644 --- a/packages/at_client/test/sync_new_test.dart +++ b/packages/at_client/test/sync_new_test.dart @@ -787,10 +787,8 @@ void main() { var atData = AtData(); atData.data = encryptionPrivateKey; //------------Operation--------------------------------- - String atKey = (AtKey.self(AtConstants.atEncryptionPrivateKey, - sharedBy: TestResources.atsign)) - .build() - .toString(); + String atKey = + (AtKey.self(AtConstants.atEncryptionPrivateKey)).build().toString(); int putCommitId = await keystore!.put(atKey, atData); // -----------Assertions--------------------------------- // verifying the key in the key store @@ -829,10 +827,8 @@ void main() { var atData = AtData(); atData.data = pkamPrivateKey; //------------Operation--------------------------------- - String atKey = (AtKey.self(AtConstants.atPkamPrivateKey, - sharedBy: TestResources.atsign)) - .build() - .toString(); + String atKey = + (AtKey.self(AtConstants.atPkamPrivateKey)).build().toString(); int putCommitId = await keystore!.put(atKey, atData); // -----------Assertions--------------------------------- // verifying the key in the key store @@ -2076,22 +2072,25 @@ void main() { // Create uncommitted entries in local storage await localSecondary.executeVerb(UpdateVerbBuilder() - ..atKey = 'firstKey' - ..sharedBy = TestResources.atsign - ..sharedWith = '@bob' + ..atKey = (AtKey() + ..key = 'firstKey' + ..sharedBy = TestResources.atsign + ..sharedWith = '@bob') ..value = 'value1'); UpdateVerbBuilder updateBuilderForSecondKey = UpdateVerbBuilder() - ..atKey = 'secondKey' - ..sharedBy = TestResources.atsign - ..sharedWith = '@bob' + ..atKey = (AtKey() + ..key = 'secondKey' + ..sharedBy = TestResources.atsign + ..sharedWith = '@bob') ..value = 'value1'; await localSecondary.executeVerb(updateBuilderForSecondKey); DeleteVerbBuilder deleteBuilderForThirdKey = DeleteVerbBuilder() - ..atKey = 'firstKey' - ..sharedBy = TestResources.atsign - ..sharedWith = '@bob'; + ..atKey = (AtKey() + ..key = 'firstKey' + ..sharedBy = TestResources.atsign + ..sharedWith = '@bob'); await localSecondary.executeVerb(deleteBuilderForThirdKey); // Mock Responses @@ -3012,9 +3011,10 @@ void main() { throw KeyNotFoundException('key is not found in keystore')); await localSecondary.executeVerb(DeleteVerbBuilder() - ..sharedWith = '@alice' - ..atKey = 'conflict-key' - ..sharedBy = TestResources.atsign); + ..atKey = (AtKey() + ..key = 'conflict-key' + ..sharedWith = '@alice' + ..sharedBy = TestResources.atsign)); CustomSyncProgressListener progressListener = CustomSyncProgressListener(); syncService.addProgressListener(progressListener); @@ -4400,7 +4400,7 @@ class LastReceivedServerCommitIdMatcher extends Matcher { @override bool matches(item, Map matchState) { - if (item is AtKey && item.key!.startsWith('lastreceivedservercommitid')) { + if (item is AtKey && item.key.startsWith('lastreceivedservercommitid')) { return true; } return false; @@ -4415,7 +4415,7 @@ class ConflictKeyMatcher extends Matcher { @override bool matches(item, Map matchState) { - if (item is AtKey && item.key!.contains('conflict')) { + if (item is AtKey && item.key.contains('conflict')) { return true; } return false; diff --git a/packages/at_client/test/sync_service_test.dart b/packages/at_client/test/sync_service_test.dart index c9b761e34..3bdec2daf 100644 --- a/packages/at_client/test/sync_service_test.dart +++ b/packages/at_client/test/sync_service_test.dart @@ -321,7 +321,7 @@ class LastReceivedServerCommitIdMatcher extends Matcher { @override bool matches(item, Map matchState) { - if (item is AtKey && item.key!.startsWith('lastreceivedservercommitid')) { + if (item is AtKey && item.key.startsWith('lastreceivedservercommitid')) { return true; } return false; diff --git a/packages/at_client_mobile/example/pubspec.yaml b/packages/at_client_mobile/example/pubspec.yaml index cec534f23..ad8c86a43 100644 --- a/packages/at_client_mobile/example/pubspec.yaml +++ b/packages/at_client_mobile/example/pubspec.yaml @@ -35,13 +35,11 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.4 at_app_flutter: ^5.2.0 - at_client: ^3.0.22 + at_client: ^3.0.71 dependency_overrides: path: ^1.8.3 async: ^2.10.0 - at_client: - path: ../../at_client dev_dependencies: flutter_test: diff --git a/packages/at_client_mobile/pubspec.yaml b/packages/at_client_mobile/pubspec.yaml index 55be38b0f..40c86c6b4 100644 --- a/packages/at_client_mobile/pubspec.yaml +++ b/packages/at_client_mobile/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: at_utils: ^3.0.15 at_chops: ^1.0.3 at_lookup: ^3.0.38 - at_client: ^3.0.64 + at_client: ^3.0.71 dev_dependencies: lints: ^2.0.0 diff --git a/tests/at_end2end_test/test/encryption_test.dart b/tests/at_end2end_test/test/encryption_test.dart index d4fab7563..55a0847bf 100644 --- a/tests/at_end2end_test/test/encryption_test.dart +++ b/tests/at_end2end_test/test/encryption_test.dart @@ -55,7 +55,7 @@ void main() { ..timeToLive(ttl)) .build(); await atClient_1.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNull); + expect(atKey.metadata.ivNonce, isNull); await E2ESyncService.getInstance().syncData(atClient_1.syncService); @@ -74,7 +74,7 @@ void main() { ..timeToLive(ttl)) .build(); await atClient_1.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNull); + expect(atKey.metadata.ivNonce, isNull); await E2ESyncService.getInstance().syncData(atClient_1.syncService); @@ -93,7 +93,7 @@ void main() { ..timeToLive(ttl)) .build(); await atClient_1.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNotNull); + expect(atKey.metadata.ivNonce, isNotNull); await E2ESyncService.getInstance().syncData(atClient_1.syncService); @@ -112,7 +112,7 @@ void main() { ..timeToLive(ttl)) .build(); await atClient_1.put(atKey, clearText); - expect(atKey.metadata?.ivNonce, isNotNull); + expect(atKey.metadata.ivNonce, isNotNull); await E2ESyncService.getInstance().syncData(atClient_1.syncService); @@ -139,9 +139,9 @@ void main() { ..timeToLive(ttl)) .build(); await atClient_1.put(atKey, clearText, putRequestOptions: options); - expect(atKey.metadata?.ivNonce, isNull); - expect(atKey.metadata?.sharedKeyEnc, isNull); - expect(atKey.metadata?.pubKeyCS, isNull); + expect(atKey.metadata.ivNonce, isNull); + expect(atKey.metadata.sharedKeyEnc, isNull); + expect(atKey.metadata.pubKeyCS, isNull); await E2ESyncService.getInstance().syncData(atClient_1.syncService); @@ -161,9 +161,9 @@ void main() { ..timeToLive(ttl)) .build(); await atClient_1.put(atKey, clearText, putRequestOptions: options); - expect(atKey.metadata?.ivNonce, isNull); - expect(atKey.metadata?.sharedKeyEnc, isNull); - expect(atKey.metadata?.pubKeyCS, isNull); + expect(atKey.metadata.ivNonce, isNull); + expect(atKey.metadata.sharedKeyEnc, isNull); + expect(atKey.metadata.pubKeyCS, isNull); await E2ESyncService.getInstance().syncData(atClient_1.syncService); @@ -183,9 +183,9 @@ void main() { ..timeToLive(ttl)) .build(); await atClient_1.put(atKey, clearText, putRequestOptions: options); - expect(atKey.metadata?.ivNonce, isNotNull); - expect(atKey.metadata?.sharedKeyEnc, isNull); - expect(atKey.metadata?.pubKeyCS, isNull); + expect(atKey.metadata.ivNonce, isNotNull); + expect(atKey.metadata.sharedKeyEnc, isNull); + expect(atKey.metadata.pubKeyCS, isNull); await E2ESyncService.getInstance().syncData(atClient_1.syncService); @@ -205,9 +205,9 @@ void main() { ..timeToLive(ttl)) .build(); await atClient_1.put(atKey, clearText, putRequestOptions: options); - expect(atKey.metadata?.ivNonce, isNotNull); - expect(atKey.metadata?.sharedKeyEnc, isNull); - expect(atKey.metadata?.pubKeyCS, isNull); + expect(atKey.metadata.ivNonce, isNotNull); + expect(atKey.metadata.sharedKeyEnc, isNull); + expect(atKey.metadata.pubKeyCS, isNull); await E2ESyncService.getInstance().syncData(atClient_1.syncService); diff --git a/tests/at_end2end_test/test/key_stream_test.dart b/tests/at_end2end_test/test/key_stream_test.dart index 4f387fbd6..7ca4c5823 100644 --- a/tests/at_end2end_test/test/key_stream_test.dart +++ b/tests/at_end2end_test/test/key_stream_test.dart @@ -225,7 +225,7 @@ void main() async { TestPreferences.getInstance().getPreference(sharedWithAtSign)); keyStream = MapKeyStream( regex: '$namespace@', - convert: (key, value) => MapEntry(key.key!, value.value), + convert: (key, value) => MapEntry(key.key, value.value), sharedBy: currentAtSign, sharedWith: sharedWithAtSign, shouldGetKeys: false, diff --git a/tests/at_end2end_test/test/notify_test.dart b/tests/at_end2end_test/test/notify_test.dart index 6e90cc96e..859639508 100644 --- a/tests/at_end2end_test/test/notify_test.dart +++ b/tests/at_end2end_test/test/notify_test.dart @@ -87,7 +87,7 @@ void main() async { shouldEncrypt: false): '$whomToNotify:$notifyText' }; inputToExpectedOutput.forEach((input, expectedOutput) { - test('Setting shouldEncrypt to ${input.atKey.metadata?.isEncrypted}', + test('Setting shouldEncrypt to ${input.atKey.metadata.isEncrypted}', () async { // Setting the AtClientManager instance to current atsign await AtClientManager.getInstance().setCurrentAtSign( @@ -110,13 +110,13 @@ void main() async { .atClient .notificationService .fetch(notificationResult.notificationID); - atNotification.isEncrypted = input.atKey.metadata!.isEncrypted; + atNotification.isEncrypted = input.atKey.metadata.isEncrypted; await NotificationResponseTransformer( sharedWithAtClientManager.atClient) .transform(Tuple() ..one = atNotification ..two = (NotificationConfig() - ..shouldDecrypt = input.atKey.metadata!.isEncrypted!)); + ..shouldDecrypt = input.atKey.metadata.isEncrypted)); expect(atNotification.id, notificationResult.notificationID); expect(atNotification.key, expectedOutput); }); diff --git a/tests/at_end2end_test/test/sharing_key_test.dart b/tests/at_end2end_test/test/sharing_key_test.dart index 5ac2027f8..b7074aed7 100644 --- a/tests/at_end2end_test/test/sharing_key_test.dart +++ b/tests/at_end2end_test/test/sharing_key_test.dart @@ -150,7 +150,7 @@ void main() async { var result = await currentAtClientManager.atClient .getRemoteSecondary()! .executeCommand( - 'update:ttl:300000:${locationKey.toString()} $encryptedValue\n', + 'update:ttl:300000:sharedKeyEnc:${locationKey.metadata.sharedKeyEnc}:pubKeyCS:${locationKey.metadata.pubKeyCS}:${locationKey.toString()} $encryptedValue\n', auth: true); expect(result != null, true); await E2ESyncService.getInstance() diff --git a/tests/at_functional_test/test/at_client_sync_test.dart b/tests/at_functional_test/test/at_client_sync_test.dart index ab9214c95..b9145adec 100644 --- a/tests/at_functional_test/test/at_client_sync_test.dart +++ b/tests/at_functional_test/test/at_client_sync_test.dart @@ -46,9 +46,10 @@ void main() { expect(serverCommitIdAfterPut! > serverCommitId!, true); // Getting value from remote secondary var llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = 'twitter.wavi' + ..atKey = (AtKey() + ..key = 'twitter.wavi' ..sharedWith = sharedWithAtSign - ..sharedBy = atSign + ..sharedBy = atSign) ..operation = 'all'; var getResponse = await atClient.getRemoteSecondary()!.executeVerb(llookupVerbBuilder); @@ -68,7 +69,7 @@ void main() { // twitter.me@alice🛠 var value = 'alice.linkedin'; var updateVerbBuilder = UpdateVerbBuilder() - ..atKeyObj = + ..atKey = AtKey.public('linkedin', namespace: namespace, sharedBy: atSign) .build() ..value = value; @@ -78,7 +79,7 @@ void main() { // Waits until key is synced to the remote secondary await FunctionalTestSyncService.getInstance().syncData(atClient.syncService, syncOptions: SyncOptions() - ..key = updateVerbBuilder.atKeyObj.toString()); + ..key = updateVerbBuilder.atKey.toString()); // Getting server commit id after put var localEntryAfterSync = await SyncUtil().getLastSyncedEntry('', atSign: atSign); @@ -136,9 +137,10 @@ void main() { expect(serverCommitIdAfterPut! > serverCommitId!, true); // Getting value from remote secondary var llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = 'quora.wavi' + ..atKey = (AtKey() + ..key ='quora.wavi' ..sharedWith = sharedWithAtSign - ..sharedBy = atSign + ..sharedBy = atSign) ..operation = 'all'; var getResponse = await atClient.getRemoteSecondary()!.executeVerb(llookupVerbBuilder); @@ -165,9 +167,10 @@ void main() { await FunctionalTestSyncService.getInstance().syncData(atClient.syncService, syncOptions: SyncOptions()..key = atKey.toString()); var llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = 'discord.wavi' + ..atKey = (AtKey() + ..key ='discord.wavi' ..sharedWith = sharedWithAtSign - ..sharedBy = atSign + ..sharedBy = atSign) ..operation = 'all'; var getResponse = await atClient.getRemoteSecondary()!.executeVerb(llookupVerbBuilder); @@ -196,8 +199,9 @@ void main() { expect(localEntryAfterSync!.atKey, isNot('local:localkey.wavi$atSign')); print('local synced entry $localEntryAfterSync'); var llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = 'local:localkey.wavi' - ..sharedBy = atSign + ..atKey = (AtKey() + ..key ='local:localkey.wavi' + ..sharedBy = atSign) ..operation = 'all'; expect( () async => await atClient @@ -223,8 +227,9 @@ void main() { await FunctionalTestSyncService.getInstance().syncData(atClient.syncService, syncOptions: SyncOptions()..key = atKey.toString()); var llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = 'key1.wavi' - ..sharedBy = atSign + ..atKey =(AtKey() + ..key= 'key1.wavi' + ..sharedBy = atSign) ..operation = 'all'; var getResponse = await atClient.getRemoteSecondary()!.executeVerb(llookupVerbBuilder); @@ -244,7 +249,7 @@ void main() { var putResult = await atClient.put(atKey, value); expect(putResult, true); var updateVerbBuilder = UpdateVerbBuilder() - ..atKeyObj = atKey + ..atKey = atKey ..value = value; var updateResponse = await atClient.getRemoteSecondary()!.executeVerb(updateVerbBuilder); @@ -254,10 +259,11 @@ void main() { syncOptions: SyncOptions()..key = atKey.toString()); var llookupVerbBuilder = LLookupVerbBuilder() - ..atKey = 'testkey.wavi' + ..atKey = (AtKey() + ..key = 'testkey.wavi' ..sharedBy = atSign - ..operation = 'all' - ..isPublic = true; + ..metadata = (Metadata() ..isPublic = true)) + ..operation = 'all'; var getResponse = await atClient.getRemoteSecondary()!.executeVerb(llookupVerbBuilder); var transformedValue = diff --git a/tests/at_functional_test/test/atclient_remote_secondary_test.dart b/tests/at_functional_test/test/atclient_remote_secondary_test.dart index 64ee841d9..9b50abfa0 100644 --- a/tests/at_functional_test/test/atclient_remote_secondary_test.dart +++ b/tests/at_functional_test/test/atclient_remote_secondary_test.dart @@ -19,43 +19,49 @@ void main() { test('sequence of put and get results', () async { var value = '+1 1111'; final phoneUpdateBuilder = UpdateVerbBuilder() - ..isPublic = true - ..atKey = 'phone' - ..sharedBy = atSign + ..atKey = (AtKey() + ..key = 'phone' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)) ..value = value; await atClientManager.atClient .getRemoteSecondary()! .executeVerb(phoneUpdateBuilder); final phoneLookupVerbBuilder = LLookupVerbBuilder() - ..isPublic = true - ..atKey = 'phone' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = 'phone' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)); final emailUpdateBuilder = UpdateVerbBuilder() - ..isPublic = true - ..atKey = 'email' - ..sharedBy = atSign + ..atKey = (AtKey() + ..key = 'email' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)) ..value = 'alice@gmail.com'; await atClientManager.atClient .getRemoteSecondary()! .executeVerb(emailUpdateBuilder); final emailLookupVerbBuilder = LLookupVerbBuilder() - ..isPublic = true - ..atKey = 'email' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = 'email' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)); final locationUpdateBuilder = UpdateVerbBuilder() - ..isPublic = true - ..atKey = 'location' - ..sharedBy = atSign + ..atKey = (AtKey() + ..key = 'location' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)) ..value = 'newyork'; await atClientManager.atClient .getRemoteSecondary()! .executeVerb(locationUpdateBuilder); final locationLookupVerbBuilder = LLookupVerbBuilder() - ..isPublic = true - ..atKey = 'location' - ..sharedBy = atSign; + ..atKey = (AtKey() + ..key = 'location' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)); final phoneFuture = atClientManager.atClient .getRemoteSecondary()! .executeVerb(phoneLookupVerbBuilder); diff --git a/tests/at_functional_test/test/atclient_sharedkey_test.dart b/tests/at_functional_test/test/atclient_sharedkey_test.dart index df4b48f5b..dbcbf3f3f 100644 --- a/tests/at_functional_test/test/atclient_sharedkey_test.dart +++ b/tests/at_functional_test/test/atclient_sharedkey_test.dart @@ -42,7 +42,7 @@ void main() { AtKeyEncryptionManager(atClient).get(phoneKey, currentAtSign); var encryptedValue = await encryptionService.encrypt(phoneKey, value); var result = await atClient.getRemoteSecondary()!.executeCommand( - 'update:sharedKeyEnc:${phoneKey.metadata?.sharedKeyEnc}:pubKeyCS:${phoneKey.metadata?.pubKeyCS}:${phoneKey.sharedWith}:${phoneKey.key}.$namespace$currentAtSign $encryptedValue\n', + 'update:sharedKeyEnc:${phoneKey.metadata.sharedKeyEnc}:pubKeyCS:${phoneKey.metadata.pubKeyCS}:${phoneKey.sharedWith}:${phoneKey.key}.$namespace$currentAtSign $encryptedValue\n', auth: true); expect(result != null, true); await FunctionalTestSyncService.getInstance() diff --git a/tests/at_functional_test/test/atclient_sync_callback_test.dart b/tests/at_functional_test/test/atclient_sync_callback_test.dart index dd68ae705..41ae3b22f 100644 --- a/tests/at_functional_test/test/atclient_sync_callback_test.dart +++ b/tests/at_functional_test/test/atclient_sync_callback_test.dart @@ -129,9 +129,10 @@ void main() { // username.me@alice🛠 var value = 'alice_1231'; var updateVerbBuilder = UpdateVerbBuilder() - ..atKey = 'fb_username-$uniqueId' - ..sharedBy = atSign - ..isPublic = true + ..atKey = (AtKey() + ..key = 'fb_username-$uniqueId' + ..sharedBy = atSign + ..metadata = (Metadata()..isPublic = true)) ..value = value; var updateResponse = await atClientManager.atClient .getRemoteSecondary()! diff --git a/tests/at_functional_test/test/atclient_sync_conflict_test.dart b/tests/at_functional_test/test/atclient_sync_conflict_test.dart index d09261f73..b4a43ef28 100644 --- a/tests/at_functional_test/test/atclient_sync_conflict_test.dart +++ b/tests/at_functional_test/test/atclient_sync_conflict_test.dart @@ -37,10 +37,12 @@ void main() async { // Update the key directly to remote secondary for having // the conflict key during sync final updateVerbBuilder = UpdateVerbBuilder() - ..sharedBy = atSign - ..atKey = 'phone_0.wavi' - ..value = 'sMBnYFctMOg+lqX67ah9UA==' //encrypted value of 4 - ..isEncrypted = true; + ..atKey = (AtKey() + ..key = 'phone_0.wavi' + ..sharedBy = atSign + ..metadata = (Metadata()..isEncrypted = true)) + ..value = 'sMBnYFctMOg+lqX67ah9UA=='; //encrypted value of 4 + await atClientManager.atClient .getRemoteSecondary()! .executeVerb(updateVerbBuilder); @@ -80,10 +82,12 @@ void main() async { // conflicting key during sync final remoteSecondary = atClientManager.atClient.getRemoteSecondary()!; final updateVerbBuilder = UpdateVerbBuilder() - ..sharedBy = atSign - ..atKey = 'test.$namespace' - ..ttl = 2 - ..isPublic = true + ..atKey = (AtKey() + ..key = 'test.$namespace' + ..sharedBy = atSign + ..metadata = (Metadata() + ..ttl = 2 + ..isPublic = true)) ..value = 'randomvalue'; await remoteSecondary.executeVerb(updateVerbBuilder); // Wait for 12 milliseconds to the key to expire