dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
21.63k stars 1.62k forks source link

MAUI Essentials - Secure storage Legacy migration errors on some Android devices - Javax.Crypto.BadPaddingException #22094

Open IainS1986 opened 2 weeks ago

IainS1986 commented 2 weeks ago

Hi

I've implemented the Legacy secure storage migration logic that uses AndroidKeystore.

https://learn.microsoft.com/en-us/dotnet/maui/migration/secure-storage?view=net-maui-8.0 I'm seeing some exceptions come through on App center.

Here's the stack...

{
  "length": 0,
  "offset": 0,
  "id": "60bd2319-add4-4094-9b8e-729c4edd4c99",
  "exception": {
    "type": "Javax.Crypto.BadPaddingException",
    "message": "Exception_WasThrown, Javax.Crypto.BadPaddingException",
    "stackTrace": "   at Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualObjectMethod(JniObjectReference , JniObjectReference , JniMethodInfo , JniArgumentValue* )\n   at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualObjectMethod(String , IJavaPeerable , JniArgumentValue* )\n   at Javax.Crypto.Cipher.DoFinal(Byte[] , Int32 , Int32 )\n   at App.Droid.Services.AndroidKeyStore.Decrypt(Byte[] data)\n   at App.Droid.Services.DroidLegacySecureStorage.GetAsync(String key)\n   at App.Core.Services.SecureStorageService.MigrateLegacyXamarin()\n  --- End of managed Javax.Crypto.BadPaddingException stack trace ---\njavax.crypto.AEADBadTagException\n\tat android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:632)\n\tat javax.crypto.Cipher.doFinal(Cipher.java:2114)\nCaused by: android.security.KeyStoreException: Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish\n\nCaused by:\n    0: system/security/keystore2/src/operation.rs:426: Finish failed.\n    1: Error::Km(r#VERIFICATION_FAILED)) (public error code: 10 internal Keystore code: -30)\n\tat android.security.KeyStore2.getKeyStoreException(KeyStore2.java:435)\n\tat android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)\n\tat android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)\n\tat android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)\n\tat android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)\n\tat android.security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:396)\n\tat android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:624)\n\t... 1 more\n",
    "innerExceptions": [
      {
        "type": "Java.Lang.Exception",
        "message": "Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish\n\nCaused by:\n    0: system/security/keystore2/src/operation.rs:426: Finish failed.\n    1: Error::Km(r#VERIFICATION_FAILED))",
        "stackTrace": "\n  --- End of managed Java.Lang.Exception stack trace ---\nandroid.security.KeyStoreException: Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish\n\nCaused by:\n    0: system/security/keystore2/src/operation.rs:426: Finish failed.\n    1: Error::Km(r#VERIFICATION_FAILED)) (public error code: 10 internal Keystore code: -30)\n\tat android.security.KeyStore2.getKeyStoreException(KeyStore2.java:435)\n\tat android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)\n\tat android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)\n\tat android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)\n\tat android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)\n\tat android.security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:396)\n\tat android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:624)\n\tat javax.crypto.Cipher.doFinal(Cipher.java:2114)\n",
        "wrapperSdkName": "appcenter.xamarin"
      }
    ],
    "wrapperSdkName": "appcenter.xamarin"
  },
  "appId": "dc5e541c-83f2-479a-94fd-52aaa6bfc967",
  "installId": "d578b0c5-cb26-43c8-9dc4-b96d1f1c92cb",
  "isTestMessage": false,
  "timestamp": "2024-04-27T09:46:47.57Z",
  "sid": "93c8acff-81f7-42eb-a511-23a4866264b0",
  "device": {
    "sdkName": "appcenter.android",
    "sdkVersion": "5.0.3",
    "wrapperSdkVersion": "5.0.3",
    "wrapperSdkName": "appcenter.xamarin",
    "model": "SM-S928U1",
    "oemName": "samsung",
    "osName": "Android",
    "osVersion": "14",
    "osBuild": "UP1A.231005.007",
    "osApiLevel": 34,
    "locale": "en_US",
    "timeZoneOffset": -240,
    "screenSize": "1440x2839",
    "appVersion": "2.2.4.1697",
    "carrierName": "T-Mobile",
    "carrierCountry": "us",
    "appBuild": "1697",
    "appNamespace": "com.moasure.moasureapp",
    "wrapperRuntimeVersion": "34.0.1.94"
  }
}

Edit - sorry trying to sort the formatting on the GitHub mobile app. Bit like pulling teeth.

Exception_WasThrown, Javax.Crypto.BadPaddingException

at Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualObjectMethod(JniObjectReference , JniObjectReference , JniMethodInfo , JniArgumentValue* )
   at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualObjectMethod(String , IJavaPeerable , JniArgumentValue* )
   at Javax.Crypto.Cipher.DoFinal(Byte[] , Int32 , Int32 )
   at App.Droid.Services.AndroidKeyStore.Decrypt(Byte[] data)
   at App.Droid.Services.DroidLegacySecureStorage.GetAsync(String key)
   at App.Core.Services.SecureStorageService.MigrateLegacyXamarin()
  --- End of managed Javax.Crypto.BadPaddingException stack trace ---
javax.crypto.AEADBadTagException\n\tat android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:632)
    at javax.crypto.Cipher.doFinal(Cipher.java:2114)\nCaused by: android.security.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)) (public error code: 10 internal Keystore code: -30)
    at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:435)
    at android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)
    at android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)
    at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)
    at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)
    at android.security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:396)
   at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:624)

Inner exception:

  --- End of managed Java.Lang.Exception stack trace ---
android.security.KeyStoreException: Signature/MAC verification failed (internal Keystore code: -30 message: system/security/keystore2/src/operation.rs:850: KeystoreOperation::finish\n\nCaused by:
    0: system/security/keystore2/src/operation.rs:426: Finish failed.
    1: Error::Km(r#VERIFICATION_FAILED)) (public error code: 10 internal Keystore code: -30)
    at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:435)
    at android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)
    at android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)
    at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)
    at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)
    at android.security.keystore2.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:396)
    at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:624)
    at javax.crypto.Cipher.doFinal(Cipher.java:2114)

We're using .net8 - I'm not 100% on what version. Can update once I get back to my desktop.

MAUI Essentials - 8.0.6

IainS1986 commented 2 weeks ago

So far, Android 14 and Android 13 devices have been reported, Samsung, Xiaomi and 'Other'

Only a handful so far but the update has only been live for a day so far.

phillippschmedt commented 2 weeks ago

See: https://github.com/dotnet/maui/issues/18230

IainS1986 commented 2 weeks ago

Not sure it's the same thing.

The exception above is not thrown on Secure Storage Get/Set

It's thrown on the Legacy Storage code when trying to get the old xamaring essentials secure storage data using the provided AndroidKeystore.cs code.

I am doing auto backup but I do have (I think) the correct exclusion

<exclude domain="sharedpref" path="${applicationId}.microsoft.maui.essentials.preferences.xml"/>