maui icon indicating copy to clipboard operation
maui copied to clipboard

[regression/8.0.0] [Maui][Android] Signature/MAC verification failed

Open devWR opened this issue 1 year ago • 31 comments

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

devWR avatar Oct 22 '23 11:10 devWR

@moljac

PureWeen avatar Oct 24 '23 18:10 PureWeen

@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.

moljac avatar Oct 24 '23 18:10 moljac

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.

ghost avatar Oct 25 '23 20:10 ghost

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> 

devWR avatar Oct 26 '23 17:10 devWR

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.

moljac avatar Oct 26 '23 18:10 moljac

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 avatar Oct 27 '23 06:10 devWR

@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.

cropyai avatar Nov 18 '23 18:11 cropyai

Same issue here but the workaround isn't working for me at all.

fekberg avatar Dec 13 '23 10:12 fekberg

I had the same issue. setting allowBackup to false fixed it for me.

RBeaubien avatar Dec 13 '23 22:12 RBeaubien

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.

plppp2001 avatar Dec 14 '23 20:12 plppp2001

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?

BurkusCat avatar Feb 10 '24 19:02 BurkusCat

The same for me in 8.0.7 version

denhaandrei avatar Feb 16 '24 15:02 denhaandrei

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.

EvgenyMuryshkin avatar Feb 21 '24 23:02 EvgenyMuryshkin

Below is the working auto_backup_rules.xml from under the \Platforms\Android\Resources\xml folder:

Edit: See below for correct examples

jukkaasikainen avatar Feb 29 '24 10:02 jukkaasikainen

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.

BurkusCat avatar Mar 19 '24 18:03 BurkusCat

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.

jukkaasikainen avatar Mar 20 '24 07:03 jukkaasikainen

Have the same issue on a Pixel 7 with Android 14, Maui 8.0.10.

Using `<application android:allowBackup="false" works for me

raindeer avatar Mar 21 '24 12:03 raindeer

This issue needs to be fixed so that we can have android:allowBackup="true"

plppp2001 avatar Mar 21 '24 12:03 plppp2001

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"/>

leonluc-dev avatar Mar 25 '24 17:03 leonluc-dev

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.

axylophon avatar Mar 26 '24 07:03 axylophon

@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 the VersionTracking 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)

image

BurkusCat avatar Mar 26 '24 20:03 BurkusCat

@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 the VersionTracking 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)

image

How can we notify the actual documentation writer to update it?

plppp2001 avatar Mar 27 '24 12:03 plppp2001

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

BurkusCat avatar Mar 27 '24 13:03 BurkusCat

How can we notify the actual documentation writer to update it?

Issue was raised.

moljac avatar Mar 27 '24 13:03 moljac

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.....

figuerres avatar Mar 31 '24 16:03 figuerres

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 avatar Mar 31 '24 16:03 figuerres

@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

South2AK avatar Apr 12 '24 23:04 South2AK

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

mmiller-d8 avatar May 09 '24 15:05 mmiller-d8

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

SpikeThatMike avatar May 21 '24 14:05 SpikeThatMike

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:

  1. Launch my .net8 app
  2. Run the Android Backup (Settings --> Backup --> Back up now)
  3. Uninstall/Reinstall the app
  4. 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.

gerhartz avatar May 21 '24 16:05 gerhartz