diff --git a/packages/at_auth/lib/src/at_auth_impl.dart b/packages/at_auth/lib/src/at_auth_impl.dart index 3861137d..357801f8 100644 --- a/packages/at_auth/lib/src/at_auth_impl.dart +++ b/packages/at_auth/lib/src/at_auth_impl.dart @@ -72,10 +72,12 @@ class AtAuthImpl implements AtAuth { 'Unable to read PkamPrivateKey from provided atKeys file/atAuthKeys object', exceptionScenario: ExceptionScenario.invalidValueProvided); } - atLookUp ??= AtLookupImpl( - atAuthRequest.atSign, atAuthRequest.rootDomain, atAuthRequest.rootPort); // ??= to support mocking atChops ??= _createAtChops(atAuthKeys); + atLookUp ??= AtLookupImpl( + atAuthRequest.atSign, atAuthRequest.rootDomain, atAuthRequest.rootPort); + atLookUp!.signingAlgoType = atAuthRequest.signingAlgoType; + atLookUp!.hashingAlgoType = atAuthRequest.hashingAlgoType; atLookUp!.atChops = atChops; _logger.finer('Authenticating using PKAM'); @@ -103,10 +105,17 @@ class AtAuthImpl implements AtAuth { @override Future onboard( AtOnboardingRequest atOnboardingRequest, String cramSecret) async { + if (atOnboardingRequest.authMode == PkamAuthMode.sim && atChops == null) { + throw AtPublicKeyNotFoundException( + 'AtChops cannot be null when AuthMode is sim. ' + 'PKAMPublicKey needs to be read from sim using AtChops'); + } var atOnboardingResponse = AtOnboardingResponse(atOnboardingRequest.atSign); atEnrollmentBase = AtEnrollmentImpl(atOnboardingRequest.atSign); atLookUp ??= AtLookupImpl(atOnboardingRequest.atSign, atOnboardingRequest.rootDomain, atOnboardingRequest.rootPort); + atLookUp?.signingAlgoType = atOnboardingRequest.signingAlgoType; + atLookUp?.hashingAlgoType = atOnboardingRequest.hashingAlgoType; //1. cram auth cramAuthenticator ??= @@ -132,20 +141,15 @@ class AtAuthImpl implements AtAuth { atOnboardingRequest, atAuthKeys, atLookUp!); atAuthKeys.enrollmentId = enrollmentIdFromServer; - //4. Close connection to server + //4. Close existing authenticated connection to server try { await (atLookUp as AtLookupImpl).close(); } on Exception catch (e) { _logger.severe('error while closing connection to server: $e'); } - //5. Init _atLookUp again and attempt pkam auth - // atLookUp = AtLookupImpl(atOnboardingRequest.atSign, - // atOnboardingRequest.rootDomain, atOnboardingRequest.rootPort); - atLookUp!.atChops = atChops; - var isPkamAuthenticated = false; - //6. Do pkam auth + //5. Do pkam auth pkamAuthenticator ??= PkamAuthenticator(atOnboardingRequest.atSign, atLookUp!); try { @@ -156,10 +160,10 @@ class AtAuthImpl implements AtAuth { throw AtAuthenticationException('Pkam auth failed - $e '); } if (!isPkamAuthenticated) { - throw AtAuthenticationException('Pkam auth returned false'); + throw AtAuthenticationException('Pkam auth unsuccessful'); } - //7. If Pkam auth is success, update encryption public key to secondary + //6. If Pkam auth is success, update encryption public key to secondary // and delete cram key from server final encryptionPublicKey = atAuthKeys.defaultEncryptionPublicKey; UpdateVerbBuilder updateBuilder = UpdateVerbBuilder() @@ -171,7 +175,7 @@ class AtAuthImpl implements AtAuth { String? encryptKeyUpdateResult = await atLookUp!.executeVerb(updateBuilder); _logger.info('Encryption public key update result $encryptKeyUpdateResult'); - //8. Delete cram secret from the keystore as cram auth is complete + //7. Delete cram secret from the keystore as cram auth is complete DeleteVerbBuilder deleteBuilder = DeleteVerbBuilder() ..atKey = (AtKey()..key = AtConstants.atCramSecret); String? deleteResponse = await atLookUp!.executeVerb(deleteBuilder); @@ -326,7 +330,7 @@ class AtAuthImpl implements AtAuth { } else if (authMode == PkamAuthMode.sim) { // get the public key from secure element pkamPublicKey = atChops!.readPublicKey(publicKeyId!); - _logger.info('pkam public key from sim: ${atKeysFile.apkamPublicKey}'); + _logger.info('PKAM public key from sim: $pkamPublicKey'); // encryption key pair and self encryption symmetric key // are not available to injected at_chops. Set it here @@ -335,8 +339,8 @@ class AtAuthImpl implements AtAuth { atChops!.atChopsKeys.apkamSymmetricKey = apkamSymmetricKey; } atKeysFile.apkamPublicKey = pkamPublicKey; - //Standard order of an atKeys file is -> - // pkam keypair -> encryption keypair -> selfEncryption key -> enrollmentId --> apkam symmetric key --> + // Standard order of an atKeys file is -> pkam keypair -> encryption keypair + // --> selfEncryption key -> enrollmentId --> apkam symmetric key --> // @sign: selfEncryptionKey[self encryption key again] // note: "->" stands for "followed by" atKeysFile.defaultEncryptionPublicKey = diff --git a/packages/at_auth/lib/src/auth/cram_authenticator.dart b/packages/at_auth/lib/src/auth/cram_authenticator.dart index d88ec55e..8d185e7e 100644 --- a/packages/at_auth/lib/src/auth/cram_authenticator.dart +++ b/packages/at_auth/lib/src/auth/cram_authenticator.dart @@ -12,9 +12,8 @@ class CramAuthenticator { Future authenticate() async { var authResult = AtAuthResponse(_atSign); try { - bool cramResult = + authResult.isSuccessful = await (atLookup as AtLookupImpl).cramAuthenticate(_cramSecret); - authResult.isSuccessful = cramResult; } on UnAuthenticatedException catch (e) { throw UnAuthenticatedException( 'cram auth failed for $_atSign - ${e.toString()}'); diff --git a/packages/at_auth/lib/src/auth/pkam_authenticator.dart b/packages/at_auth/lib/src/auth/pkam_authenticator.dart index af97be7a..3fa08f66 100644 --- a/packages/at_auth/lib/src/auth/pkam_authenticator.dart +++ b/packages/at_auth/lib/src/auth/pkam_authenticator.dart @@ -10,9 +10,8 @@ class PkamAuthenticator { Future authenticate({String? enrollmentId}) async { var authResult = AtAuthResponse(_atSign); try { - bool pkamResult = + authResult.isSuccessful = await _atLookup.pkamAuthenticate(enrollmentId: enrollmentId); - authResult.isSuccessful = pkamResult; } on UnAuthenticatedException catch (e) { throw UnAuthenticatedException( 'pkam auth failed for $_atSign - ${e.toString()}'); diff --git a/packages/at_auth/lib/src/onboard/at_onboarding_response.dart b/packages/at_auth/lib/src/onboard/at_onboarding_response.dart index 28c422dd..0079eaad 100644 --- a/packages/at_auth/lib/src/onboard/at_onboarding_response.dart +++ b/packages/at_auth/lib/src/onboard/at_onboarding_response.dart @@ -9,6 +9,6 @@ class AtOnboardingResponse { @override String toString() { - return 'AtOnboardingResponse{atSign: $atSign, enrollmentId: $enrollmentId, isSuccessful: $isSuccessful}'; + return 'AtOnboardingResponse: {atSign: $atSign, enrollmentId: $enrollmentId, isSuccessful: $isSuccessful}'; } } diff --git a/packages/at_onboarding_cli/lib/src/onboard/at_onboarding_service_impl.dart b/packages/at_onboarding_cli/lib/src/onboard/at_onboarding_service_impl.dart index b65b3843..034a64c1 100644 --- a/packages/at_onboarding_cli/lib/src/onboard/at_onboarding_service_impl.dart +++ b/packages/at_onboarding_cli/lib/src/onboard/at_onboarding_service_impl.dart @@ -116,6 +116,10 @@ class AtOnboardingServiceImpl implements AtOnboardingService { atOnboardingRequest.deviceName = atOnboardingPreference.deviceName; atOnboardingRequest.publicKeyId = atOnboardingPreference.publicKeyId; atOnboardingRequest.authMode = atOnboardingPreference.authMode; + atOnboardingRequest.signingAlgoType = + atOnboardingPreference.signingAlgoType; + atOnboardingRequest.hashingAlgoType = + atOnboardingPreference.hashingAlgoType; AtOnboardingResponse atOnboardingResponse = await atAuth! .onboard(atOnboardingRequest, atOnboardingPreference.cramSecret!); @@ -481,7 +485,9 @@ class AtOnboardingServiceImpl implements AtOnboardingService { ..authMode = atOnboardingPreference.authMode ..rootDomain = atOnboardingPreference.rootDomain ..rootPort = atOnboardingPreference.rootPort - ..publicKeyId = atOnboardingPreference.publicKeyId; + ..publicKeyId = atOnboardingPreference.publicKeyId + ..signingAlgoType = atOnboardingPreference.signingAlgoType + ..hashingAlgoType = atOnboardingPreference.hashingAlgoType; var atAuthResponse = await atAuth!.authenticate(atAuthRequest); logger.finer('Auth response: $atAuthResponse'); if (atAuthResponse.isSuccessful && @@ -654,7 +660,8 @@ class AtOnboardingServiceImpl implements AtOnboardingService { @override Future close() async { logger.info('Closing'); - if (_atLookUp != null && (_atLookUp as AtLookupImpl).isConnectionAvailable()) { + if (_atLookUp != null && + (_atLookUp as AtLookupImpl).isConnectionAvailable()) { await _atLookUp!.close(); } atClient?.notificationService.stopAllSubscriptions(); diff --git a/tests/at_onboarding_cli_functional_tests/test/at_onboarding_cli_test.dart b/tests/at_onboarding_cli_functional_tests/test/at_onboarding_cli_test.dart index 97709459..c28f217c 100644 --- a/tests/at_onboarding_cli_functional_tests/test/at_onboarding_cli_test.dart +++ b/tests/at_onboarding_cli_functional_tests/test/at_onboarding_cli_test.dart @@ -9,6 +9,8 @@ import 'package:at_onboarding_cli/src/activate_cli/activate_cli.dart' as activate_cli; import 'package:at_utils/at_utils.dart'; import 'package:test/test.dart'; +import 'package:at_auth/src/at_auth_impl.dart'; +import 'package:at_chops/at_chops.dart'; import 'utils/onboarding_service_impl_override.dart'; @@ -77,7 +79,7 @@ void main() { AtOnboardingService onboardingService = AtOnboardingServiceImpl(atSign, preference); await onboardingService.authenticate(); - AtClient? atClient = await onboardingService.atClient; + AtClient? atClient = onboardingService.atClient; AtKey key = AtKey(); key.key = 'testKey3'; key.namespace = 'wavi'; @@ -86,6 +88,29 @@ void main() { expect('value3', response?.value); }); + test( + 'validate that signing algo and hashing algo set in AtOnboardingPreference is passed forward to AtAuth instance', + () async { + String atSign = '@eve🛠'; + await _createKeys(atSign); + AtOnboardingPreference preference = getPreferences(atSign); + await generateAtKeysFile(atSign, preference.atKeysFilePath!); + SigningAlgoType signingAlgo = SigningAlgoType.rsa2048; + HashingAlgoType hashingAlgo = HashingAlgoType.sha512; + preference.hashingAlgoType = hashingAlgo; + preference.signingAlgoType = signingAlgo; + AtOnboardingService onboardingService = + AtOnboardingServiceImpl(atSign, preference); + await onboardingService.authenticate(); + // validating on the atLookup instance in AtAuth to ensure that the algo's + // passed through OnboardingPref are passed to the AtLookup instance that + // communicates with the at_server + AtLookupImpl? atLookupImpl = + (onboardingService.atAuth as AtAuthImpl).atLookUp as AtLookupImpl?; + expect(atLookupImpl!.signingAlgoType, signingAlgo); + expect(atLookupImpl.hashingAlgoType, hashingAlgo); + }); + test('A test to verify atKeysFilePath is set when null is provided', () async { String atSign = '@eve🛠'; @@ -115,7 +140,7 @@ void main() { await generateAtKeysFile(atSign, atOnboardingPreference.atKeysFilePath!); await _createKeys(atSign); bool status = await atOnboardingService.authenticate(); - atClient = await atOnboardingService.atClient; + atClient = atOnboardingService.atClient; expect(true, status); expect(at_demos.pkamPrivateKeyMap[atSign], @@ -146,6 +171,7 @@ void main() { () async { AtOnboardingService atOnboardingService = AtOnboardingServiceImpl(atSign, atOnboardingPreference); + bool status = await atOnboardingService.onboard(); expect(status, true); bool status2 = await atOnboardingService.authenticate(); @@ -165,9 +191,6 @@ void main() { // Skipping this test until the issue can be resolved group('A group of tests to verify activate_cli', () { String atSign = '@murali🛠'; - AtOnboardingPreference onboardingPreference = getPreferences(atSign); - AtOnboardingService onboardingService = - OnboardingServiceImplOverride(atSign, onboardingPreference); test( 'A test to verify atSign is activated and .atKeys file is generated using activate_cli', () async { @@ -182,10 +205,9 @@ void main() { // perform activation of atSign await activate_cli.wrappedMain(args); - /// ToDo: test should NOT exit with status 0 after activation is complete - /// Exiting with status 0 is ideal behaviour, but for the sake of the test we need to be - /// able to run the following assertions. - + AtOnboardingPreference onboardingPreference = getPreferences(atSign); + AtOnboardingService onboardingService = + AtOnboardingServiceImpl(atSign, onboardingPreference); // Authenticate atSign with the .atKeys file generated via the activate_cli tool expect(await File(onboardingPreference.atKeysFilePath!).exists(), true); expect(await onboardingService.authenticate(), true); diff --git a/tests/at_onboarding_cli_functional_tests/test/ecc_secure_element_mock_test.dart b/tests/at_onboarding_cli_functional_tests/test/ecc_secure_element_mock_test.dart index 543559bb..1e963828 100644 --- a/tests/at_onboarding_cli_functional_tests/test/ecc_secure_element_mock_test.dart +++ b/tests/at_onboarding_cli_functional_tests/test/ecc_secure_element_mock_test.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:at_chops/at_chops.dart'; import 'package:at_client/at_client.dart'; -import 'package:at_lookup/at_lookup.dart'; import 'package:at_onboarding_cli/at_onboarding_cli.dart'; import 'package:at_utils/at_logger.dart'; import 'package:test/test.dart'; @@ -16,23 +15,20 @@ import 'utils/onboarding_service_impl_override.dart'; void main() { AtSignLogger.root_level = 'WARNING'; var logger = AtSignLogger('OnboardSecureElementTest'); - final atSign = '@egcreditbureau🛠'.trim(); - test('Test auth functionality using secure element mock', () async { + + test('Validate auth functionality using secure element mock', () async { AtOnboardingPreference preference = getPreferences(atSign); AtOnboardingService onboardingService = OnboardingServiceImplOverride(atSign, preference); // create empty keys in AtChops. Encryption key pair will be set later on after generation final atChopsImpl = AtChopsSecureElementMock(AtChopsKeys.create(null, null)); - AtLookUp atLookupInstance = - AtLookupImpl(atSign, preference.rootDomain, preference.rootPort); - atLookupInstance.signingAlgoType = preference.signingAlgoType; - atLookupInstance.hashingAlgoType = preference.hashingAlgoType; - at_auth.AtAuth atAuthInstance = at_auth.atAuthBase - .atAuth(atLookUp: atLookupInstance, atChops: atChopsImpl); + at_auth.AtAuth atAuthInstance = + at_auth.atAuthBase.atAuth(atChops: atChopsImpl); onboardingService.atAuth = atAuthInstance; atChopsImpl.init(); + logger.info('Onboarding the atSign: $atSign'); bool isOnboarded = await onboardingService.onboard(); expect(isOnboarded, true); @@ -44,7 +40,7 @@ void main() { logger.info('Authentication completed successfully for atSign: $atSign'); // update a key - AtClient? atClient = await onboardingService.atClient; + AtClient? atClient = onboardingService.atClient; await insertSelfEncKey(atClient, atSign, selfEncryptionKey: await getSelfEncryptionKey(preference.atKeysFilePath!)); @@ -79,7 +75,7 @@ AtOnboardingPreference getPreferences(String atSign) { ..commitLogPath = 'storage/commitLog' ..rootDomain = 'vip.ve.atsign.zone' ..fetchOfflineNotifications = true - ..atKeysFilePath = 'test/storage/files/$atSign' + '_key.atKeys' + ..atKeysFilePath = 'test/storage/files/${atSign}_key.atKeys' ..signingAlgoType = SigningAlgoType.ecc_secp256r1 ..hashingAlgoType = HashingAlgoType.sha256 ..authMode = PkamAuthMode.sim diff --git a/tests/at_onboarding_cli_functional_tests/test/utils/at_chops_secure_element_mock.dart b/tests/at_onboarding_cli_functional_tests/test/utils/at_chops_secure_element_mock.dart index e40207a7..03038c8c 100644 --- a/tests/at_onboarding_cli_functional_tests/test/utils/at_chops_secure_element_mock.dart +++ b/tests/at_onboarding_cli_functional_tests/test/utils/at_chops_secure_element_mock.dart @@ -29,7 +29,7 @@ class AtChopsSecureElementMock extends AtChopsImpl { ..result = base64Signature ..atSigningMetaData = atSigningMetadata ..atSigningResultType = AtSigningResultType.string; - print('at signing result: $atSigningResult'); + print('[AtChopsSecureElementMock] AtSigningResult: $atSigningResult'); return atSigningResult; } @@ -46,7 +46,7 @@ class AtChopsSecureElementMock extends AtChopsImpl { @override String readPublicKey(String publicKeyId) { - print('public key in read public key: ${eccPublicKey.toString()}'); + print('[AtChopsSecureElementMock] Reading public key from SIM: ${eccPublicKey.toString()}'); return eccPublicKey.toString(); } }