maui
maui copied to clipboard
[regression/8.0.0] [Maui][Android] Signature/MAC verification failed
Description
Since I updated to .NET8 RC2 SecureStorage.SetAsync does not work. It throws Javax.Crypto.AEADBadTagException with the following message: "Signature/MAC verification failed". Issue reproduced using Samsung A40 with Android 11. Case happens when backup rules exclude mauiessentials.xml file.
Below you can find stacktrace:
--- End of managed Android.Security.KeyStoreException stack trace ---
android.security.KeyStoreException: Signature/MAC verification failed
at android.security.KeyStore.getKeyStoreException(KeyStore.java:1461)
at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:186)
at android.security.keystore.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:373)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)
at javax.crypto.Cipher.doFinal(Cipher.java:2113)
at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decryptInternal(AndroidKeystoreAesGcm.java:118)
at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decrypt(AndroidKeystoreAesGcm.java:101)
at com.google.crypto.tink.KeysetHandle.decrypt(KeysetHandle.java:993)
at com.google.crypto.tink.KeysetHandle.readWithAssociatedData(KeysetHandle.java:878)
at com.google.crypto.tink.KeysetHandle.read(KeysetHandle.java:859)
at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.readMasterkeyDecryptAndParseKeyset(AndroidKeysetManager.java:378)
at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:298)
at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:169)
at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:130)
Steps to Reproduce
Invoke Microsoft.Maui.Storage.SecureStorage.SetAsync
Link to public reproduction project repository
No response
Version with bug
8.0.0-rc.2.9373
Is this a regression from previous behavior?
Yes, this used to work in .NET MAUI
Last version that worked well
8.0.0-rc.1.9171
Affected platforms
Android
Affected platform versions
No response
Did you find any workaround?
Yes
Issue doesn't happen when, in manifest, android:allowBackup is set to false as following: <application android:allowBackup="false" ... >
Relevant log output
No response
@moljac
@devWR
Can I see your AndroidManifest.xml
?
if you have
<application android:allowBackup="true" ... >
true
is default I think.
try setting it to
<application android:allowBackup="false" ... >
There are also other workarounds, but I'll need to dive in deeper.
And please report whether that worked.
Hi @devWR. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
Strange case. I just tested it on Samsung A51 with Android 12 and issue doesn't happen. @moljac, I've tried your workaround and it worked, thank you. Do you have any idea where the issue comes from? It started happening since I've upgraded to RC2. Before allowBackup was set to true. After issue started happening I added into manifest:
android:fullBackupContent="@xml/auto_backup_rules"
where auto_backup_rules is as following:
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="${applicationId}.mauiessentials.xml"/>
</full-backup-content>
Do you have any idea where the issue comes from?
Not completely. I checked native Android issues on SO and github and saw that as quick-n-dirty workaround. There are some other workarounds, but thosw will need deeper dives and curently I am not sure if I will have time for that.
Thank you for the workaround then. I believe that some solution shall be found as soon as possible because there is a number of applicaitons that need to store data securely - tokens, etc.
@devWR
Can I see your
AndroidManifest.xml
?if you have
<application android:allowBackup="true" ... >
true
is default I think.try setting it to
<application android:allowBackup="false" ... >
There are also other workarounds, but I'll need to dive in deeper.
And please report whether that worked.
I can confirm the issue happening in my case. The other workaround is to clear the storage and cache of the app from app settings.
Same issue here but the workaround isn't working for me at all.
I had the same issue. setting allowBackup to false fixed it for me.
Same issue here but the workaround isn't working for me at all.
I'm having the same issue, (on an actual samsung device - Release APK installation only). I'll try this workaround... not sure if it'll help.... it worked so far, but this issue needs to resolved @MAUI team
** UPDATE this work around worked for me so far, but I'll have to retest this again later.
where auto_backup_rules is as following:
@devWR what backup rules did you end up using that fixed the issue? Or did you not get it resolved and needed to fully disable backup?
The same for me in 8.0.7 version
The workaround does not work. The exception message said something about wrong encryption keys being used for storage.
I had an old version of the app deployed, but after upgrading to the latest Visual Studio (17.9) app started to crash. Also, there was an Android software update during this time, so not sure what exactly contributed.
Removing the app and deploying from scratch helps.
Below is the working auto_backup_rules.xml from under the \Platforms\Android\Resources\xml
folder:
Edit: See below for correct examples
Below is the working auto_backup_rules.xml from under the \Platforms\Android\Resources\xml folder:
Unfortunately, even with those rules on MAUI 8.0.10 I'm still getting secure storage exceptions:
Javax.Crypto.AEADBadTagException
I imagine a workaround is to disable backup entirely but that isn't a great solution since it means users will lose any historical data/statistics if they moved devices/uninstalled.
Stack trace
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: Javax.Crypto.AEADBadTagException: Exception of type 'Javax.Crypto.AEADBadTagException' was thrown.
[mono-rt] ---> Android.Security.KeyStoreException: Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish
[mono-rt]
[mono-rt] Caused by:
[mono-rt] 0: system/security/keystore2/src/operation.rs:426: Finish failed.
[mono-rt] 1: Error::Km(r#VERIFICATION_FAILED))
[mono-rt]
[mono-rt] --- End of managed Android.Security.KeyStoreException stack trace ---
[mono-rt] android.security.KeyStoreException: Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish
[mono-rt]
[mono-rt] Caused by:
[mono-rt] 0: system/security/keystore2/src/operation.rs:426: Finish failed.
[mono-rt] 1: Error::Km(r#VERIFICATION_FAILED)) (public error code: 10 internal Keystore code: -30)
[mono-rt] at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:386)
[mono-rt] at android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)
[mono-rt] at android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)
[mono-rt] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)
[mono-rt] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)
[mono-rt] at android.security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:396)
[mono-rt] at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:618)
[mono-rt] at javax.crypto.Cipher.doFinal(Cipher.java:2114)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decryptInternal(AndroidKeystoreAesGcm.java:118)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decrypt(AndroidKeystoreAesGcm.java:101)
[mono-rt] at com.google.crypto.tink.KeysetHandle.decrypt(KeysetHandle.java:993)
[mono-rt] at com.google.crypto.tink.KeysetHandle.readWithAssociatedData(KeysetHandle.java:878)
[mono-rt] at com.google.crypto.tink.KeysetHandle.read(KeysetHandle.java:859)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.readMasterkeyDecryptAndParseKeyset(AndroidKeysetManager.java:378)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:298)
[mono-rt] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:169)
[mono-rt] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:130)
[mono-rt] at mono.java.lang.RunnableImplementor.n_run(Native Method)
[mono-rt] at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:31)
[mono-rt] at android.os.Handler.handleCallback(Handler.java:958)
[mono-rt] at android.os.Handler.dispatchMessage(Handler.java:99)
[mono-rt] at android.os.Looper.loopOnce(Looper.java:205)
[mono-rt] at android.os.Looper.loop(Looper.java:294)
[mono-rt] at android.app.ActivityThread.main(ActivityThread.java:8248)
[mono-rt] at java.lang.reflect.Method.invoke(Native Method)
[mono-rt] at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
[mono-rt] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
[mono-rt]
[mono-rt] --- End of managed Android.Security.KeyStoreException stack trace ---
[mono-rt] android.security.KeyStoreException: Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish
[mono-rt]
[mono-rt] Caused by:
[mono-rt] 0: system/security/keystore2/src/operation.rs:426: Finish failed.
[mono-rt] 1: Error::Km(r#VERIFICATION_FAILED)) (public error code: 10 internal Keystore code: -30)
[mono-rt] at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:386)
[mono-rt] at android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)
[mono-rt] at android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)
[mono-rt] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)
[mono-rt] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)
[mono-rt] at android.security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:396)
[mono-rt] at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:618)
[mono-rt] at javax.crypto.Cipher.doFinal(Cipher.java:2114)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decryptInternal(AndroidKeystoreAesGcm.java:118)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decrypt(AndroidKeystoreAesGcm.java:101)
[mono-rt] at com.google.crypto.tink.KeysetHandle.decrypt(KeysetHandle.java:993)
[mono-rt] at com.google.crypto.tink.KeysetHandle.readWithAssociatedData(KeysetHandle.java:878)
[mono-rt] at com.google.crypto.tink.KeysetHandle.read(KeysetHandle.java:859)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.readMasterkeyDecryptAndParseKeyset(AndroidKeysetManager.java:378)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:298)
[mono-rt] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:169)
[mono-rt] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:130)
[mono-rt] at mono.java.lang.RunnableImplementor.n_run(Native Method)
[mono-rt] at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:31)
[mono-rt] at android.os.Handler.handleCallback(Handler.java:958)
[mono-rt] at android.os.Handler.dispatchMessage(Handler.java:99)
[mono-rt] at android.os.Looper.loopOnce(Looper.java:205)
[mono-rt] at android.os.Looper.loop(Looper.java:294)
[mono-rt] at android.app.ActivityThread.main(ActivityThread.java:8248)
[mono-rt] at java.lang.reflect.Method.invoke(Native Method)
[mono-rt] at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
[mono-rt] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
[mono-rt]
[mono-rt] --- End of inner exception stack trace ---
[mono-rt] at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference type, JniMethodInfo method, JniArgumentValue* args) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:line 21452
[mono-rt] at Java.Interop.JniPeerMembers.JniStaticMethods.InvokeObjectMethod(String encodedMember, JniArgumentValue* parameters) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticMethods.cs:line 165
[mono-rt] at AndroidX.Security.Crypto.EncryptedSharedPreferences.Create(Context context, String fileName, MasterKey masterKey, PrefKeyEncryptionScheme prefKeyEncryptionScheme, PrefValueEncryptionScheme prefValueEncryptionScheme) in C:\a\_work\1\s\generated\androidx.security.security-crypto\obj\Release
et6.0-android\generated\src\AndroidX.Security.Crypto.EncryptedSharedPreferences.cs:line 227
[mono-rt] at Microsoft.Maui.Storage.SecureStorageImplementation.GetEncryptedSharedPreferences() in D:\a\_work\1\s\src\Essentials\src\SecureStorage\SecureStorage.android.cs:line 93
[mono-rt] at Microsoft.Maui.Storage.SecureStorageImplementation.PlatformRemoveAll() in D:\a\_work\1\s\src\Essentials\src\SecureStorage\SecureStorage.android.cs:line 78
[mono-rt] at Microsoft.Maui.Storage.SecureStorageImplementation.RemoveAll() in D:\a\_work\1\s\src\Essentials\src\SecureStorage\SecureStorage.shared.cs:line 233
[mono-rt] at Catlists.Services.SettingsService.IsProductPurchased(IProduct product) in C:\Projects\cat-lists\src\Catlists\Services\SettingsService.cs:line 630
[mono-rt] at Catlists.Services.AdManager.ShouldShowAdsForThisUser() in C:\Projects\cat-lists\src\Catlists\Services\AdManager.cs:line 75
[mono-rt] at Catlists.ViewModels.SettingsViewModel.OnNavigatedTo(NavigationParameters parameters) in C:\Projects\cat-lists\src\Catlists\ViewModels\SettingsViewModel.cs:line 75
[mono-rt] at Burkus.Mvvm.Maui.LifecycleEventUtility.TriggerOnNavigatedTo(Object bindingContext, NavigationParameters navigationParameters)
[mono-rt] at Burkus.Mvvm.Maui.NavigationService.<HandleNavigation>d__14`1[[Catlists.Pages.SettingsPage, Catlists, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
[mono-rt] at Burkus.Mvvm.Maui.NavigationService.<Push>d__1`1[[Catlists.Pages.SettingsPage, Catlists, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
[mono-rt] at Burkus.Mvvm.Maui.NavigationService.<Push>d__0`1[[Catlists.Pages.SettingsPage, Catlists, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
[mono-rt] at Catlists.ViewModels.HomeViewModel.Settings() in C:\Projects\cat-lists\src\Catlists\ViewModels\HomeViewModel.cs:line 123
[mono-rt] at CommunityToolkit.Mvvm.Input.AsyncRelayCommand.AwaitAndThrowIfFailed(Task executionTask) in /_/src/CommunityToolkit.Mvvm/Input/AsyncRelayCommand.cs:line 351
[mono-rt] at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
[mono-rt] at Android.App.SyncContext.<>c__DisplayClass2_0.<Post>b__0() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.App/SyncContext.cs:line 36
[mono-rt] at Java.Lang.Thread.RunnableImplementor.Run() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Java.Lang/Thread.cs:line 36
[mono-rt] at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net8.0/android-34/mcw/Java.Lang.IRunnable.cs:line 84
[mono-rt] at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 26
[mono-rt] --- End of managed Javax.Crypto.AEADBadTagException stack trace ---
[mono-rt] javax.crypto.AEADBadTagException
[mono-rt] at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:626)
[mono-rt] at javax.crypto.Cipher.doFinal(Cipher.java:2114)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decryptInternal(AndroidKeystoreAesGcm.java:118)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decrypt(AndroidKeystoreAesGcm.java:101)
[mono-rt] at com.google.crypto.tink.KeysetHandle.decrypt(KeysetHandle.java:993)
[mono-rt] at com.google.crypto.tink.KeysetHandle.readWithAssociatedData(KeysetHandle.java:878)
[mono-rt] at com.google.crypto.tink.KeysetHandle.read(KeysetHandle.java:859)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.readMasterkeyDecryptAndParseKeyset(AndroidKeysetManager.java:378)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:298)
[mono-rt] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:169)
[mono-rt] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:130)
[mono-rt] at mono.java.lang.RunnableImplementor.n_run(Native Method)
[mono-rt] at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:31)
[mono-rt] at android.os.Handler.handleCallback(Handler.java:958)
[mono-rt] at android.os.Handler.dispatchMessage(Handler.java:99)
[mono-rt] at android.os.Looper.loopOnce(Looper.java:205)
[mono-rt] at android.os.Looper.loop(Looper.java:294)
[mono-rt] at android.app.ActivityThread.main(ActivityThread.java:8248)
[mono-rt] at java.lang.reflect.Method.invoke(Native Method)
[mono-rt] at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
[mono-rt] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
[mono-rt] Caused by: android.security.KeyStoreException: Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish
[mono-rt]
[mono-rt] Caused by:
[mono-rt] 0: system/security/keystore2/src/operation.rs:426: Finish failed.
[mono-rt] 1: Error::Km(r#VERIFICATION_FAILED)) (public error code: 10 internal Keystore code: -30)
[mono-rt] at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:386)
[mono-rt] at android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)
[mono-rt] at android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)
[mono-rt] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)
[mono-rt] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)
[mono-rt] at android.security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:396)
[mono-rt] at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:618)
[mono-rt] ... 20 more
[mono-rt]
[mono-rt] --- End of managed Javax.Crypto.AEADBadTagException stack trace ---
[mono-rt] javax.crypto.AEADBadTagException
[mono-rt] at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:626)
[mono-rt] at javax.crypto.Cipher.doFinal(Cipher.java:2114)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decryptInternal(AndroidKeystoreAesGcm.java:118)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decrypt(AndroidKeystoreAesGcm.java:101)
[mono-rt] at com.google.crypto.tink.KeysetHandle.decrypt(KeysetHandle.java:993)
[mono-rt] at com.google.crypto.tink.KeysetHandle.readWithAssociatedData(KeysetHandle.java:878)
[mono-rt] at com.google.crypto.tink.KeysetHandle.read(KeysetHandle.java:859)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.readMasterkeyDecryptAndParseKeyset(AndroidKeysetManager.java:378)
[mono-rt] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:298)
[mono-rt] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:169)
[mono-rt] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:130)
[mono-rt] at mono.java.lang.RunnableImplementor.n_run(Native Method)
[mono-rt] at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:31)
[mono-rt] at android.os.Handler.handleCallback(Handler.java:958)
[mono-rt] at android.os.Handler.dispatchMessage(Handler.java:99)
[mono-rt] at android.os.Looper.loopOnce(Looper.java:205)
[mono-rt] at android.os.Looper.loop(Looper.java:294)
[mono-rt] at android.app.ActivityThread.main(ActivityThread.java:8248)
[mono-rt] at java.lang.reflect.Method.invoke(Native Method)
[mono-rt] at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
[mono-rt] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
[mono-rt] Caused by: android.security.KeyStoreException: Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish
[mono-rt]
[mono-rt] Caused by:
[mono-rt] 0: system/security/keystore2/src/operation.rs:426: Finish failed.
[mono-rt] 1: Error::Km(r#VERIFICATION_FAILED)) (public error code: 10 internal Keystore code: -30)
[mono-rt] at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:386)
[mono-rt] at android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)
[mono-rt] at android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)
[mono-rt] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)
[mono-rt] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)
[mono-rt] at android.security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:396)
[mono-rt] at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:618)
[mono-rt] ... 20 more
[mono-rt]
The MAUI docs recommending removing secure storage keys if you get an exception on GetAsync or SetAsync so I am trying to do that with RemoveAll but still getting an exception.
https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/storage/secure-storage?view=net-maui-8.0&tabs=android#use-secure-storage
It's possible that an exception is thrown when calling GetAsync or SetAsync. This can be caused by a device not supporting > secure storage, encryption keys changing, or corruption of data. it's best to handle this by removing and adding the setting back if possible.
Unfortunately, even with those rules on MAUI 8.0.10 I'm still getting secure storage exceptions:
Javax.Crypto.AEADBadTagException
Thanks for letting me know. I've since then disabled the AndroidManifest.xml setting
<application android:allowBackup="false" android:fullBackupContent="@xml/auto_backup_rules" ... >
but keeping the auto_backup_rules.xml file, which may or may not do something in this scenario.
I think the app retains access to secure variables and values through updates, though now I'm not 100% sure anymore. I'll try to remember to update this when testing after next version update.
EDIT: Secure values do indeed stay within the device when updating the app without first uninstalling it.
Have the same issue on a Pixel 7 with Android 14, Maui 8.0.10.
Using `<application android:allowBackup="false" works for me
This issue needs to be fixed so that we can have android:allowBackup="true"
It seems the documentation for the backup configuration is slightly outdated. Here are the set of rules that worked for me, allowing me to keep backup enabled but solving this issue.
In the manifest set the following two properties on the <application>
tag:
<application
....
android:allowBackup="true"
android:dataExtractionRules="@xml/backup_rules"
android:fullBackupContent="@xml/backup_rules_legacy">
dataExtractionRules
is used for Android 12 and up. fullBackupContent
for Android 11 and lower.
backup_rules.xml
<?xml version="1.0" encoding="utf-8" ?>
<data-extraction-rules>
<cloud-backup disableIfNoEncryptionCapabilities="false">
<exclude domain="sharedpref" path="${applicationId}.microsoft.maui.essentials.preferences.xml"/>
</cloud-backup>
<device-transfer>
<exclude domain="sharedpref" path="${applicationId}.microsoft.maui.essentials.preferences.xml"/>
</device-transfer>
</data-extraction-rules>
backup_rules_legacy.xml
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="sharedpref" path="${applicationId}.microsoft.maui.essentials.preferences.xml"/>
</full-backup-content>
Note: For some of my projects I noticed ${applicationId}
isn't properly processed. If that is the case be sure to replace it with with your full application id. For example:
<exclude domain="sharedpref" path="org.example.MyAppName.microsoft.maui.essentials.preferences.xml"/>
Is there a fix planned for this issue? We also have the problem. Maui 8.0.10. When reinstalling our app crashes with the same exception as in the first post.
@leonluc-dev Great work tracking this down. I've not tested but I think you've hit the nail on the head. It looks like this has always been the file name for MAUI Secure storage (https://github.com/dotnet/maui/pull/4211/files#diff-93ca7559b0a2eaf2bab3285f6d90c92ed92eee598bfbc814b368201753a0ef29). The documentation writer probably just made an assumption that xamarinessentials
would change to mauiessentials
and therefore these errors would come from not setting the backup rules correctly.
- I've verified that
"${applicationId}.microsoft.maui.essentials.preferences.xml"
is what the secure storage preferences file is saved as. -
"${applicationId}.microsoft.maui.essentials.versiontracking.xml"
is for theVersionTracking
APIs (which you may also want to exclude if you use it). -
"${applicationId}_preferences.xml"
appears to be for normal unencrypted preferences which you likely do want to backup (example, if user chooses a setting for how often they want to sync, then when they move to a new device then that setting will automatically be set for them)
@leonluc-dev Great work tracking this down. I've not tested but I think you've hit the nail on the head. It looks like this has always been the file name for MAUI Secure storage (https://github.com/dotnet/maui/pull/4211/files#diff-93ca7559b0a2eaf2bab3285f6d90c92ed92eee598bfbc814b368201753a0ef29). The documentation writer probably just made an assumption that
xamarinessentials
would change tomauiessentials
and therefore these errors would come from not setting the backup rules correctly.
I've verified that
"${applicationId}.microsoft.maui.essentials.preferences.xml"
is what the secure storage preferences file is saved as.
"${applicationId}.microsoft.maui.essentials.versiontracking.xml"
is for theVersionTracking
APIs (which you may also want to exclude if you use it).
"${applicationId}_preferences.xml"
appears to be for normal unencrypted preferences which you likely do want to backup (example, if user chooses a setting for how often they want to sync, then when they move to a new device then that setting will automatically be set for them)
How can we notify the actual documentation writer to update it?
How can we notify the actual documentation writer to update it?
Leonluc already submitted a GitHub issue for the docs :) https://github.com/dotnet/docs-maui/issues/2167#issue-2206080449
How can we notify the actual documentation writer to update it?
Issue was raised.
Hello just found this, i think i am also getting hit by this.
i have a new app that when i run it for debug builds on my device i do not see a problem. when i build a release apk for ad hoc and run it i keep getting crashes and errors.
from my sentry logs i get messages like this:
android.security.keystore2.AndroidKeyStoreCipherSpiBase in engineDoFinal at line 632 javax.crypto.Cipher in doFinal at line 2114 com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm in decryptInternal at line 118 com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm in decrypt at line 101 com.google.crypto.tink.KeysetHandle in decrypt at line 993 com.google.crypto.tink.KeysetHandle in readWithAssociatedData at line 878 com.google.crypto.tink.KeysetHandle in read at line 859 com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder in readMasterkeyDecryptAndParseKeyset at line 378 com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder in build at line 298 androidx.security.crypto.EncryptedSharedPreferences in create at line 169 androidx.security.crypto.EncryptedSharedPreferences in create at line 130
and then
KeyStoreException Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish
Caused by: 0: system/security/keystore2/src/operation.rs:426: Finish failed. 1: Error::Km(r#VERIFICATION_FAILED)) android.security.KeyStore2 in getKeyStoreException at line 435 android.security.KeyStoreOperation in handleExceptions at line 78 android.security.KeyStoreOperation in finish at line 128 android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream in finish at line 228 android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer in doFinal at line 181 … .security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer in doFinal at line 396 android.security.keystore2.AndroidKeyStoreCipherSpiBase in engineDoFinal at line 624 javax.crypto.Cipher in doFinal at line 2114 com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm in decryptInternal at line 118 com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm in decrypt at line 101 com.google.crypto.tink.KeysetHandle in decrypt at line 993 com.google.crypto.tink.KeysetHandle in readWithAssociatedData at line 878 com.google.crypto.tink.KeysetHandle in read at line 859 com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder in readMasterkeyDecryptAndParseKeyset at line 378 com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder in build at line 298 androidx.security.crypto.EncryptedSharedPreferences in create at line 169 androidx.security.crypto.EncryptedSharedPreferences in create at line 130
android v14 samsung galaxy 22
also i see this:
JniObjectReference StaticMethods.CallStaticObjectMethod(JniObjectReference, JniMethodInfo, JniArgumentValue*) In App
Assembly: Java.Interop Version: 7.0.0.0 PublicKeyToken: 84e04ff9cfb79065 JniObjectReference JniStaticMethods.InvokeObjectMethod(string, JniArgumentValue*) In App
Called from: ISharedPreferences EncryptedSharedPreferences.Create(Context, string, MasterKey, PrefKeyEncryptionScheme, PrefValueEncryptionScheme)
Show 2 more frames
the app wants to use secure storage for user tokens.
try to login or resume from recent session and BOOM!
i will see if the info here lets me work past this.....
first test setting allow backup to false seems to stop the crash! also note that a debug build of the same app to the same device did NOT have the problem ! so why does debug not error and release does ??
@figuerres I have the error on both debug and release using MAUI 8.0.20
Also Allow Backup none doesn´t seem to be a workaround since all saved data get´s deleted after a restart of the app.
I´m having the same error when using any SecureStorage command:
[ViewRootImpl@5b71c8b[MainActivity]] ViewPostIme pointer 0
[ViewRootImpl@5b71c8b[MainActivity]] ViewPostIme pointer 1
[ViewRootImpl@5b71c8b[MainActivity]] onDisplayChanged oldDisplayState=2 newDisplayState=2
[DOTNET] at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference type, JniMethodInfo method, JniArgumentValue* args) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:line 21452
[DOTNET] at Java.Interop.JniPeerMembers.JniStaticMethods.InvokeObjectMethod(String encodedMember, JniArgumentValue* parameters) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticMethods.cs:line 165
[DOTNET] at AndroidX.Security.Crypto.EncryptedSharedPreferences.Create(Context context, String fileName, MasterKey masterKey, PrefKeyEncryptionScheme prefKeyEncryptionScheme, PrefValueEncryptionScheme prefValueEncryptionScheme) in C:\a\_work\1\s\generated\androidx.security.security-crypto\obj\Release
et6.0-android\generated\src\AndroidX.Security.Crypto.EncryptedSharedPreferences.cs:line 227
[DOTNET] at Microsoft.Maui.Storage.SecureStorageImplementation.GetEncryptedSharedPreferences() in D:\a\_work\1\s\src\Essentials\src\SecureStorage\SecureStorage.android.cs:line 93
[DOTNET] at Microsoft.Maui.Storage.SecureStorageImplementation.<>c__DisplayClass6_0.<PlatformSetAsync>b__0() in D:\a\_work\1\s\src\Essentials\src\SecureStorage\SecureStorage.android.cs:line 53
[DOTNET] at System.Threading.Tasks.Task.InnerInvoke()
[DOTNET] at System.Threading.Tasks.Task.<>c.<.cctor>b__281_0(Object obj)
[DOTNET] at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
[DOTNET] --- End of stack trace from previous location ---
[DOTNET] at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
[DOTNET] at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
[DOTNET] --- End of stack trace from previous location ---
[DOTNET] at Schaden_Digital.Views.PageLogin.Button_Clicked_1(Object sender, EventArgs e) in F:\Sourcecode\Online Gutachten\Online Gutachten\Views\Login\PageLogin.xaml.cs:line 77
[DOTNET] --- End of managed Javax.Crypto.AEADBadTagException stack trace ---
[DOTNET] javax.crypto.AEADBadTagException
[DOTNET] at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:632)
[DOTNET] at javax.crypto.Cipher.doFinal(Cipher.java:2114)
[DOTNET] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decryptInternal(AndroidKeystoreAesGcm.java:118)
[DOTNET] at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decrypt(AndroidKeystoreAesGcm.java:101)
[DOTNET] at com.google.crypto.tink.KeysetHandle.decrypt(KeysetHandle.java:993)
[DOTNET] at com.google.crypto.tink.KeysetHandle.readWithAssociatedData(KeysetHandle.java:878)
[DOTNET] at com.google.crypto.tink.KeysetHandle.read(KeysetHandle.java:859)
[DOTNET] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.readMasterkeyDecryptAndParseKeyset(AndroidKeysetManager.java:378)
[DOTNET] at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:298)
[DOTNET] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:169)
[DOTNET] at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:130)
[DOTNET] Caused by: android.security.KeyStoreException: Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish
[DOTNET]
[DOTNET] Caused by:
[DOTNET] 0: system/security/keystore2/src/operation.rs:426: Finish failed.
[DOTNET] 1: Error::Km(r#VERIFICATION_FAILED)) (public error code: 10 internal Keystore code: -30)
[DOTNET] at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:435)
[DOTNET] at android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)
[DOTNET] at android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)
[DOTNET] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)
[DOTNET] at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)
[DOTNET] at android.security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:396)
[DOTNET] at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:624)
[DOTNET] ... 10 more
[DOTNET] Exception of type 'Javax.Crypto.AEADBadTagException' was thrown.
[ViewRootImpl@5b71c8b[MainActivity]] onDisplayChanged oldDisplayState=2 newDisplayState=2
To add another wrinkle to this, the documentation says:
NET MAUI automatically handles this case by removing the key so it can be reset. Alternatively, you can disable Auto Backup.
First, it doesn't handle the case because it still fails. Second, and more importantly, removing the key myself doesn't work either. It seems that calling SetValue must be attempting to read the value before setting it because the call still fails with the same exception.
@leonluc-dev Thank you for putting the complete workaround. Unfortunately for me, I still can't set secure storage values. I'm getting Signature/MAC verification failed (internal Keystore code: -30 message: In KeystoreOperation::finish
Same problem as @mmiller-d8, I have done the work around @leonluc-dev posted but its crashing on
Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish
Same issue as @mmiller-d8. Seeing this exception on my Android 14 / Pixel 6a device. Building with Maui 8.0.21, NET SDK 8.0.300, Xcode 15.4
I was struggling to consistently reproduce the issue but figured out a process:
- Launch my .net8 app
- Run the Android Backup (Settings --> Backup --> Back up now)
- Uninstall/Reinstall the app
- Launch app. Any call to secure storage fails. Trying to remove keys also fails.
Clearing the app storage avoids the problem (not suggesting that as a solution). But for anyone else that feels the issue is happening randomly for them I realized that my phone does auto-backup after 2hrs of inactivity which made the problem pop up again the next time I rebuilt after clearing app storage.