While reviewing some code I noticed that MasterKeys was deprecated in androids newest crypto library. I changed my code around following This stackoverflow answer. It works fine on every device I have tried EXCEPT for my Pixel4XL on Android 11 Beta (RPB1.200504.020).
I wrote a separate class for getting the masterkey so that it could be accessed from two different activities. Here:
import android.security.keystore.KeyProperties;
import androidx.security.crypto.MasterKey;
import java.io.IOException;
import java.security.GeneralSecurityException;
public class GetMKey {
public MasterKey getmkeym(Context context) {
KeyGenParameterSpec spec = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
spec = new KeyGenParameterSpec.Builder(
MasterKey.DEFAULT_MASTER_KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setUserAuthenticationRequired(false)
.setUnlockedDeviceRequired(true)
.setIsStrongBoxBacked(true)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setKeySize(256)
.build();
} else {
spec = new KeyGenParameterSpec.Builder(
MasterKey.DEFAULT_MASTER_KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setKeySize(256)
.setUserAuthenticationRequired(false)
.build();
}
try {
MasterKey masterKey = new MasterKey.Builder(context)
.setKeyGenParameterSpec(spec)
.build();
return masterKey;
} catch (GeneralSecurityException | IOException e) {
e.printStackTrace();
return null;
}
}
}
I then use this (in Kotlin) with:
var mk = GetMkey()
val sharedprefernces = EncryptedSharedPreferences.create(this, "ENCRYPTEDSHAREDPREF", mk.getmkeym(this), EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM)
On the Android studio emulators P3a API29 and P3a API30 as well as my GalaxyS10+(API28) it runs perfectly fine. However on my Pixel 4XL running the android 11 beta it throws a "User not authenticated" error: EDIT NOTE: After further investigation, it appears that on the pixel it works after the phone is unlocked for around 10 seconds. Tried turning on authenticationrequired and setting authenticationvalidityduration to a higher amount but to no avail. Still throws error only on this device
2020-07-03 21:08:03.018 27585-27585/REDACTED E/AndroidRuntime: FATAL EXCEPTION: main
Process: REDACTED, PID: 27585
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Caused by: android.security.keystore.UserNotAuthenticatedException: User not authenticated
at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1346)
at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1388)
at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109)
at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984)
at javax.crypto.Cipher.tryCombinations(Cipher.java:2891)
at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
at javax.crypto.Cipher.init(Cipher.java:1143)
at javax.crypto.Cipher.init(Cipher.java:1084)
at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.encrypt(AndroidKeystoreAesGcm.java:64)
at com.google.crypto.tink.KeysetHandle.encrypt(KeysetHandle.java:180)
at com.google.crypto.tink.KeysetHandle.write(KeysetHandle.java:157)
at com.google.crypto.tink.integration.android.AndroidKeysetManager.write(AndroidKeysetManager.java:385)
at com.google.crypto.tink.integration.android.AndroidKeysetManager.readOrGenerateNewKeyset(AndroidKeysetManager.java:350)
at com.google.crypto.tink.integration.android.AndroidKeysetManager.<init>(AndroidKeysetManager.java:133)
at com.google.crypto.tink.integration.android.AndroidKeysetManager.<init>(AndroidKeysetManager.java:96)
at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:208)
at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:153)
at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:119)
at REDACTED.LoginActivity$onCreate$1.onClick(LoginActivity.kt:54)
at android.view.View.performClick(View.java:7438)
at android.view.View.performClickInternal(View.java:7415)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28286)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7523)
Not sure if this is a problem with the beta or if I have implemented it incorrectly. Any help would be much appreciated and I would be happy to provide more info if needed. Thanks!