From 54e67bd31eb64cf05a3c9b1252228713e5a6ea3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juraj=20=C4=8Eurech?= Date: Tue, 8 Oct 2024 14:32:10 +0200 Subject: [PATCH 1/2] Android: Fix #635: Temporary key expiration --- .../tests/StandardActivationTest.java | 39 +++++++++++++++++++ .../sdk/impl/DefaultKeystoreService.java | 2 +- .../PowerAuth2/private/PA2KeystoreService.m | 2 +- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/integration/tests/StandardActivationTest.java b/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/integration/tests/StandardActivationTest.java index ba32531c..232b3c18 100644 --- a/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/integration/tests/StandardActivationTest.java +++ b/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/integration/tests/StandardActivationTest.java @@ -549,4 +549,43 @@ public void onGetEciesEncryptorFailed(@NonNull Throwable t) { }); assertNotNull(encryptor); } + + /* + @Test + public void testEciesTemporaryKeyExpiration() throws Exception { + // This test requires PAS configured for a very short temporary key lifespan. + activationHelper.createStandardActivation(true, null); + + Boolean result = AsyncHelper.await(resultCatcher -> { + powerAuthSDK.fetchEncryptionKey(testHelper.getContext(), activationHelper.getValidAuthentication(), 1000, new IFetchEncryptionKeyListener() { + @Override + public void onFetchEncryptionKeySucceed(@NonNull byte[] encryptedEncryptionKey) { + resultCatcher.completeWithResult(true); + } + + @Override + public void onFetchEncryptionKeyFailed(@NonNull Throwable t) { + resultCatcher.completeWithResult(false); + } + }); + }); + assertTrue(result); + + Thread.sleep(15_000); + result = AsyncHelper.await(resultCatcher -> { + powerAuthSDK.fetchEncryptionKey(testHelper.getContext(), activationHelper.getValidAuthentication(), 1000, new IFetchEncryptionKeyListener() { + @Override + public void onFetchEncryptionKeySucceed(@NonNull byte[] encryptedEncryptionKey) { + resultCatcher.completeWithResult(true); + } + + @Override + public void onFetchEncryptionKeyFailed(@NonNull Throwable t) { + resultCatcher.completeWithResult(false); + } + }); + }); + assertTrue(result); + } + */ } diff --git a/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/sdk/impl/DefaultKeystoreService.java b/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/sdk/impl/DefaultKeystoreService.java index eefac1c7..b5cd9d8c 100644 --- a/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/sdk/impl/DefaultKeystoreService.java +++ b/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/sdk/impl/DefaultKeystoreService.java @@ -82,7 +82,7 @@ public boolean containsKeyForEncryptor(int scope) { lock.lock(); if (session.hasPublicKeyForEciesScope(scope)) { final PublicKeyInfo publicKeyInfo = getPublicKeyInfoForScope(scope); - if (publicKeyInfo.expiration >= 0 && publicKeyInfo.expiration - EXPIRATION_THRESHOLD < timeService.getCurrentTime()) { + if (publicKeyInfo.expiration >= 0 && (timeService.getCurrentTime() < publicKeyInfo.expiration - EXPIRATION_THRESHOLD)) { return true; } PowerAuthLog.d("Removing expired public key for ECIES encryptor " + scope); diff --git a/proj-xcode/PowerAuth2/private/PA2KeystoreService.m b/proj-xcode/PowerAuth2/private/PA2KeystoreService.m index b91842fb..f43005fb 100644 --- a/proj-xcode/PowerAuth2/private/PA2KeystoreService.m +++ b/proj-xcode/PowerAuth2/private/PA2KeystoreService.m @@ -125,7 +125,7 @@ - (BOOL) hasKeyForEncryptorScope:(PowerAuthCoreEciesEncryptorScope)encryptorScop PA2PublicKeyInfo * pki = [self pkiForScope:encryptorScope]; NSTimeInterval expiration = pki.expiration; keyIsSet = expiration >= 0.0; - keyIsExpired = expiration - PUBLIC_KEY_EXPIRATION_THRESHOLD < [_timeService currentTime]; + keyIsExpired = [_timeService currentTime] >= expiration - PUBLIC_KEY_EXPIRATION_THRESHOLD; if (keyIsExpired) { pki.expiration = -1; } From 0cf4a7f3d03e06f27a2a5f478f656b417e028570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juraj=20=C4=8Eurech?= Date: Tue, 8 Oct 2024 17:17:09 +0200 Subject: [PATCH 2/2] Apple: #635: Added test for temporary key expiration --- .../tests/StandardActivationTest.java | 2 -- .../PowerAuthSDKDefaultTests.m | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/integration/tests/StandardActivationTest.java b/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/integration/tests/StandardActivationTest.java index 232b3c18..38fe9897 100644 --- a/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/integration/tests/StandardActivationTest.java +++ b/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/integration/tests/StandardActivationTest.java @@ -550,7 +550,6 @@ public void onGetEciesEncryptorFailed(@NonNull Throwable t) { assertNotNull(encryptor); } - /* @Test public void testEciesTemporaryKeyExpiration() throws Exception { // This test requires PAS configured for a very short temporary key lifespan. @@ -587,5 +586,4 @@ public void onFetchEncryptionKeyFailed(@NonNull Throwable t) { }); assertTrue(result); } - */ } diff --git a/proj-xcode/PowerAuth2IntegrationTests/PowerAuthSDKDefaultTests.m b/proj-xcode/PowerAuth2IntegrationTests/PowerAuthSDKDefaultTests.m index 18c100a7..aa4b0bbd 100644 --- a/proj-xcode/PowerAuth2IntegrationTests/PowerAuthSDKDefaultTests.m +++ b/proj-xcode/PowerAuth2IntegrationTests/PowerAuthSDKDefaultTests.m @@ -1395,4 +1395,32 @@ - (void) testEncryptorCreation XCTAssertNotNil(encryptor); } + +- (void) testTemporaryKeyExpiration +{ + // This test requires PAS configured for a very short temporary key lifespan. + CHECK_TEST_CONFIG(); + + PowerAuthSdkActivation * activation = [_helper createActivation:YES]; + if (!activation) { + return; + } + + BOOL result = [[AsyncHelper synchronizeAsynchronousBlock:^(AsyncHelper *waiting) { + [_sdk fetchEncryptionKey:_helper.authPossessionWithKnowledge index:1000 callback:^(NSData * _Nullable encryptionKey, NSError * _Nullable error) { + [waiting reportCompletion:@(error == nil)]; + }]; + }] boolValue]; + XCTAssertTrue(result); + + [NSThread sleepForTimeInterval:15.0]; + + result = [[AsyncHelper synchronizeAsynchronousBlock:^(AsyncHelper *waiting) { + [_sdk fetchEncryptionKey:_helper.authPossessionWithKnowledge index:1000 callback:^(NSData * _Nullable encryptionKey, NSError * _Nullable error) { + [waiting reportCompletion:@(error == nil)]; + }]; + }] boolValue]; + XCTAssertTrue(result); +} + @end