mibrito707 / cordova-plugin-secure-storage-echo

Secure storage plugin for Apache Cordova
MIT License
73 stars 73 forks source link

Not working on Android Xiaomi MI A1 #55

Open Gizmo8690 opened 4 years ago

Gizmo8690 commented 4 years ago

On Xiaomi MI A1 the plugin is still not working. The constructor new cordova.plugins.SecureStorage() fails with error:

Error: User not authenticated
    at fail (securestorage.js:42)
leolio86400 commented 4 years ago

Not sure it is related to the plugin but more to the device itself. But it is true that this is happening a lot on Android devices.

The only thing that seems to make it work is to screen lock the device and unlock using pin (not biometrics).

Does anybody have better solution than that ?

leolio86400 commented 4 years ago

Probably related https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder.html#setUserAuthenticationValidityDurationSeconds(int)

https://github.com/mibrito707/cordova-plugin-secure-storage-echo/issues/27

Gizmo8690 commented 4 years ago

The only thing that seems to make it work is to screen lock the device and unlock using pin (not biometrics).

I have already tried setting unlock using pin but it is still not working...

faugusztin commented 4 years ago

While i am not using this plugin anymore and the stacktrace i will post is old, it should give some insight in the issue.

If i remember correctly (i have a Mi A1 here if needed), the issue was the following combination:

In this case, Crypho's original plugin failed with following stacktrace:

09-18 10:43:48.955 15570 16023 E SecureStorage: Decrypt failed :
09-18 10:43:48.955 15570 16023 E SecureStorage: java.security.InvalidKeyException: Keystore operation failed
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.KeyStore.getInvalidKeyException(KeyStore.java:901)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.KeyStore.getInvalidKeyException(KeyStore.java:926)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.tryCombinations(Cipher.java:2891)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.init(Cipher.java:1143)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.init(Cipher.java:1084)
09-18 10:43:48.955 15570 16023 E SecureStorage: at com.crypho.plugins.RSA.runCipher(RSA.java:97)
09-18 10:43:48.955 15570 16023 E SecureStorage: at com.crypho.plugins.RSA.decrypt(RSA.java:41)
09-18 10:43:48.955 15570 16023 E SecureStorage: at com.crypho.plugins.SecureStorage$3.run(SecureStorage.java:151)
09-18 10:43:48.955 15570 16023 E SecureStorage: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
09-18 10:43:48.955 15570 16023 E SecureStorage: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
09-18 10:43:48.955 15570 16023 E SecureStorage: at java.lang.Thread.run(Thread.java:764)
09-18 10:43:48.955 15570 16023 E SecureStorage: Caused by: android.security.KeyStoreException: Invalid user authentication validity duration
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.KeyStore.getKeyStoreException(KeyStore.java:835)
09-18 10:43:48.955 15570 16023 E SecureStorage: ... 17 more

I suspect the issue is on firmware level, and because Mi A1 is an 'obsolete' phone, the bug is unlikely to be fixed on HW level.

If someone has some demo application source code i can build with current version of this plugin, i am willing to test out if it is still the case.

leolio86400 commented 4 years ago

@faugusztin yeah it seems to be a recurrent issue with low price brand phones.

Did you find any plugin that could replace this one? This plugin have been the core of lot of issues we have, so we are really considering moving out of it.

faugusztin commented 4 years ago

Unfortunately my answer won't help you - we reconsidered if we really needed secure storage (we did not), so we just save the few client side settings in JSON file (as local storage in browser could be wiped if disk space is an issue).

You could still keep using this plugin on compatible phones, and via phone model detection add an alternative, maybe a bit less secure storage (like the JSON file i mentioned above) for phones with issues.

Unless there is a magic combination of settings which could make this plugin work on Mi A1, that is your best alternative.

faugusztin commented 4 years ago

More detailed description of what happens (created a minimal case by creating a new cordova project, adding the secure storage plugin to it, then adding the android platform, adding the "Create a namespaced storage." example from the documentation to www/js/index.js of the default Cordova project).

In code it runs like this:

Then i tried to use a different alias (to generate new keys) and with the following options:

{
   android: {
      userAuthenticationValidityDuration: 5*60 
   }
} 

Same result.

As i said, i suspect a firmware bug on Xiaomi Mi A1, which somehow breaks RSA decryption (or the keys) in case fingerprint unlock is enabled. Without fingerprint unlock, the code works just fine.

faugusztin commented 4 years ago

The only alternative to consider on plugin's side is to have a list of devices which are not compatible with userAuthenticationRequired setting, and for those drop those two settings (setUserAuthenticationRequired and setUserAuthenticationValidityDurationSeconds) in https://github.com/mibrito707/cordova-plugin-secure-storage-echo/blob/master/src/android/RSA.java#L48. Without those two settings, there keys work fine for the encryption test, but obviously do not trigger the need for secure unlock and do not get invalidated in case of security modifications, like enrolling a new fingerprint or disabling the secure lock, which is a drawback. On other side, at least it would make the plugin usable on those devices.

leolio86400 commented 4 years ago

Thanks @faugusztin, I opted for another way and designed a solution to remove the plugin as well. I tried to upgrade it and use the setUserAuthenticationValidityDurationSeconds up to 1 month, it got somehow worse... so better moving out of this than keeping it. Thanks for the help though 👍