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 d7991eb
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 84 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
@@ -1,16 +1,22 @@
/*
* Copyright (c) 2019 ForgeRock. All rights reserved.
* 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import android.content.Context;
import android.content.SharedPreferences;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -22,8 +28,6 @@
import java.util.Set;
import java.util.concurrent.CountDownLatch;

import static org.junit.Assert.*;

/**
*
* Instrumented test, which will execute on an Android device.
Expand Down Expand Up @@ -55,24 +59,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

0 comments on commit d7991eb

Please sign in to comment.