【问题标题】:Robolectric AndroidKeyStore not found, KeyStore.getInstance未找到 Robolectric AndroidKeyStore,KeyStore.getInstance
【发布时间】:2022-11-06 06:29:32
【问题描述】:

我有一些单元测试,其中底层代码使用了 EncryptedSharedPreferences。由于上述代码,我收到了 Robolectric 无法处理和隐藏本机 KeyStore 实现的异常。目前在 Robolectric 的 Github 上有一个未解决的问题,可以找到 here。但它似乎在 Android >= 11 上没有任何修复。有什么想法,或者你可能遇到过同样的问题?

正在抛出 KeyStoreException

AndroidKeyStore not found
java.security.KeyStoreException: AndroidKeyStore not found
    at java.base/java.security.KeyStore.getInstance(KeyStore.java:878)
    at androidx.security.crypto.MasterKeys.keyExists(MasterKeys.java:135)
    at androidx.security.crypto.MasterKeys.getOrCreate(MasterKeys.java:87)
    at ...auth.EncryptedAuthState.sharedPreferences(EncryptedAuthState.kt:88)
    at ...auth.EncryptedAuthState.readState(EncryptedAuthState.kt:57)
    at ...auth.EncryptedAuthState.getCurrent(EncryptedAuthState.kt:40)
    at ...auth.EncryptedAuthState.updateAfterTokenResponse(EncryptedAuthState.kt:74)
    at ...EncryptedAuthStateTest.updateIdTokenOnTokenResponse(EncryptedAuthStateTest.kt:126)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:591)
    at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:274)
    at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:88)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.security.NoSuchAlgorithmException: AndroidKeyStore KeyStore not available
    at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:159)
    at java.base/java.security.Security.getImpl(Security.java:700)
    at java.base/java.security.KeyStore.getInstance(KeyStore.java:875)

运行测试时,例如

@ExperimentalFoundationApi
@ExperimentalStdlibApi
@RunWith(RobolectricTestRunner::class)
@Config(shadows = [KeyStoreShadow::class])
class EncryptedAuthStateTest {
    @Test
    fun initialAuthState() {
        val state =
            EncryptedAuthState(InstrumentationRegistry.getInstrumentation().targetContext)
                .getCurrent()

        Assert.assertFalse(state.isAuthorized)
        Assert.assertNull(state.accessToken)
        Assert.assertNull(state.accessTokenExpirationTime)
        Assert.assertNull(state.idToken)
        Assert.assertNull(state.refreshToken)
        Assert.assertNull(state.lastAuthorizationResponse)
        Assert.assertNull(state.lastTokenResponse)
        Assert.assertNull(state.lastRegistrationResponse)
        Assert.assertNull(state.scope)
        Assert.assertNull(state.scopeSet)
    }
}

加密的 AuthState

private fun sharedPreferences(): SharedPreferences {
        val masterKey: MasterKey = MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
            .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
            .build()

        return EncryptedSharedPreferences.create(
            context,
            "AuthState",
            masterKey,
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
        )
    }

我试图创建一个影子类,但这没有被触发:

import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

@Implements(KeyStore.class)
public class KeyStoreShadow {
    @Implementation
    public static KeyStore getInstance(String type)
            throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(new FileInputStream(
                System.getProperty("java.home") + "/lib/security/cacerts"), null);
        return keyStore;
    }
}

资源

【问题讨论】:

    标签: java android kotlin robolectric robolectric-shadows


    【解决方案1】:

    我也有同样的问题。你能解决这个问题@kevin-etore 吗?

    【讨论】:

    猜你喜欢
    • 2015-12-21
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 2015-09-03
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 2018-02-05
    相关资源
    最近更新 更多