Skip to content

Commit

Permalink
SDKS-3104 - Improvemnets in caching the key reference
Browse files Browse the repository at this point in the history
  • Loading branch information
jeyanthanperiyasamy committed Apr 16, 2024
1 parent 4444228 commit 26406ba
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 80 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright (c) 2019 - 2024 ForgeRock. All rights reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
package org.forgerock.android.auth

import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.io.IOException
import java.security.GeneralSecurityException
import java.security.KeyStore
import java.util.concurrent.atomic.AtomicReference
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey

/**
* Provide data encryption and decryption for Android M device.
*/
internal open class AndroidMEncryptor(keyAlias: String) : AbstractSymmetricEncryptor(keyAlias) {
@JvmField
val specBuilder: KeyGenParameterSpec.Builder = KeyGenParameterSpec.Builder(
keyAlias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setRandomizedEncryptionRequired(true)
.setUserAuthenticationRequired(false)
.setKeySize(KEY_SIZE)

@Throws(GeneralSecurityException::class, IOException::class)
override fun getSecretKey(): SecretKey {
keyReferenceCache.get()?.let {
return it
}
if (keyStore.containsAlias(keyAlias)) {
return (keyStore.getEntry(keyAlias, null) as KeyStore.SecretKeyEntry).secretKey.also {
keyReferenceCache.set(it)
}
} else {
val keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE
)
keyGenerator.init(specBuilder.build())
return keyGenerator.generateKey().also {
keyReferenceCache.set(it)
}
}
}

@Throws(GeneralSecurityException::class, IOException::class)
public override fun init(cipher: Cipher): ByteArray {
//Generate a random IV See KeyGenParameterSpec.Builder.setRandomizedEncryptionRequired
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
return cipher.iv
}

@Throws(GeneralSecurityException::class, IOException::class)
override fun reset() {
keyStore.deleteEntry(keyAlias)
keyReferenceCache.set(null)
}

companion object {
//Hold the current key.
val keyReferenceCache = AtomicReference<SecretKey>()
}

/**
* Retrieve and load the Android KeyStore
*
* @return The AndroidKeyStore
*/
@get:Throws(GeneralSecurityException::class, IOException::class)
private val keyStore: KeyStore
get() {
val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
keyStore.load(null)
return keyStore
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;

import java.io.File;
import java.security.KeyStore;
Expand Down Expand Up @@ -55,24 +58,37 @@ public static void tearDown() throws Exception {
String filePath = context.getFilesDir().getParent() + "/shared_prefs/test.xml";
File deletePrefFile = new File(filePath);
deletePrefFile.delete();
AndroidMEncryptor.Companion.getKeyReferenceCache().set(null);
}

@Test
public void testCache() {
AndroidMEncryptor.Companion.getKeyReferenceCache().set(null);
sharedPreferences.edit().putString("Test", "Value").commit();
assertEquals("Value", sharedPreferences.getString("Test", null));
assertNotNull(AndroidMEncryptor.Companion.getKeyReferenceCache().get());
}


@Test
public void testPutString() {
sharedPreferences.edit().putString("Test", "Value").commit();
assertEquals("Value", sharedPreferences.getString("Test", null));
assertNotNull(AndroidMEncryptor.Companion.getKeyReferenceCache().get());
}

@Test
public void testPutInt() {
sharedPreferences.edit().putInt("Test", 100).commit();
assertEquals(100, sharedPreferences.getInt("Test", 0));
assertNotNull(AndroidMEncryptor.Companion.getKeyReferenceCache().get());
}

@Test
public void testPutFloat() {
sharedPreferences.edit().putFloat("Test", 1.5f).commit();
assertEquals(1.5f, sharedPreferences.getFloat("Test", 1.5f), 0);
assertNotNull(AndroidMEncryptor.Companion.getKeyReferenceCache().get());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.ContextCompat
import com.google.android.gms.fido.fido2.api.common.ResidentKeyRequirement
import net.openid.appauth.AuthorizationRequest
import org.forgerock.android.auth.AccessToken
import org.forgerock.android.auth.FRListener
Expand Down Expand Up @@ -228,6 +229,7 @@ class MainActivity : AppCompatActivity(), NodeListener<FRUser>, ActivityListener
}
"WebAuthnRegistrationCallback" -> {
val callback = node.getCallback(WebAuthnRegistrationCallback::class.java)
callback?.setResidentKeyRequirement(ResidentKeyRequirement.RESIDENT_KEY_DISCOURAGED)
callback?.register(this, node= node, listener = object : FRListener<Void?> {
override fun onSuccess(result: Void?) {
node.next(activity, activity)
Expand Down

0 comments on commit 26406ba

Please sign in to comment.