react-native-keychain: getGenericPassword is too slow on android 10
I have slow startup on android 10 , After checking , I understand that getGenericPassword methods takes 7-8 seconds on android 10
I run on android 7 and 6 too , It takes about 600-700ms
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 18
- Comments: 69 (12 by maintainers)
Commits related to this issue
- Use strongbox detection and warmup for secret key Speeds up strongbox detection on certain devices: https://github.com/oblador/react-native-keychain/issues/337#issuecomment-639335445 Use `warmingUp... — committed to SowaLabs/react-native-keychain by andrejcesen 4 years ago
- Use strongbox detection and warmup for secret key Speeds up strongbox detection on certain devices: https://github.com/oblador/react-native-keychain/issues/337#issuecomment-639335445 Use `warmingUp... — committed to SowaLabs/react-native-keychain by andrejcesen 4 years ago
- Use strongbox detection and warmup for secret key Speeds up strongbox detection on certain devices: https://github.com/oblador/react-native-keychain/issues/337#issuecomment-639335445 Use `warmingUp... — committed to SowaLabs/react-native-keychain by andrejcesen 4 years ago
- Improve biometrics and strongbox feature detection Speeds up strongbox detection on certain devices: https://github.com/oblador/react-native-keychain/issues/337#issuecomment-639335445 — committed to SowaLabs/react-native-keychain by andrejcesen 4 years ago
- Improve biometrics and strongbox feature detection Speeds up strongbox detection on certain devices: https://github.com/oblador/react-native-keychain/issues/337#issuecomment-639335445 — committed to SowaLabs/react-native-keychain by andrejcesen 4 years ago
I dont know if i understood correctly, but you dont have to call
.withoutWarmUp()in this file: https://github.com/oblador/react-native-keychain/blob/master/android/src/main/java/com/oblador/keychain/KeychainPackage.java, you have to do it in yourMainApplication.java. So for that you have to import:And then, in the
getPackages()method, yo have to add the package manually like that:And because
react-native-keychainhas autolinking, i had to disable it in order to add the package manually. For that, i created areact-native.config.jsfile in the root of my project with the following code:I hope it works for you!
@sm2017 here’s a quick answer to that: https://twitter.com/vonovak/status/1283895813903654912?s=20
hope this makes sense 🙂
from 4.0.5:
from 6.0.0
Measurements taken using
System.nanoTime()right before/after the call. Samsung Galaxy S10+, running Android 10.Edit: yup, i’m stumped. The only thing that looks different is that there is now a cache on the keystore (https://github.com/oblador/react-native-keychain/blob/e6090b2966a0965b9326da44f849978c50e6fe2a/android/src/main/java/com/oblador/keychain/cipherStorage/CipherStorageBase.java#L282) whereas that didn’t used to be there
Edit edit: Tried making it not a cached instance, tho i am not sure quite how or why that would fix it. It didn’t fix it. So it seems that the same method call is taking longer, when the only variable is the package version 😅
Edit: looking into this on a bit further, based on @patrickschmelter’s comment. Looking in the android source, it seems like
StrongBoxis not available on the particular hardware. and throwing early in thetryGenerateStrongBoxSecurityKey(before actually attempting to generate the key) makes the behaviour fast again.OK. Looks like that’s a bit of a red herring. I’ve been playing around a lot and it seems like the “warm up” happens, and it also gets stuck. Until a log line appears that says
CertificatePolicyCache: Creating new instance of CertificatePolicyCache. Then that completes, and it seems to work fast again. Googling around forCertificatePolicyCachedoesn’t really yield any results 😞.Final edit for a while: seems like the new RSA type is what’s doing it. There seems to be a lock involved, and the system hangs until it’s ready. I managed to get the
setGenericPasswordto work fairly quickly by explicitly settingstorage: Keychain.STORAGE_TYPE.AES,, but unfortunately thegetGenericPasswordis still slow 😞@nicolaslazzos @aranda-adapptor
You guys are stars! 👍🏻 - It worked, many thanks!
For other new users like me that have the same problem: Apart from changing
MainApplication.javaas the @nicolaslazzos mentioned above and all the other file changes he posted. You will also need to addcompile project(':react-native-keychain')inside your dependencies { } of/android/app/build.gradleAnd my JS setGenericPassword for passing AES looks like:
await Keychain.setGenericPassword("some_user", "123456", {storage: Keychain.STORAGE_TYPE.AES })Good luck
@john-y-pazekha as you joined 5 hours ago to github, and send us an APK file I cannot trust you and I don’t install that apk
I can send you exact details about model of device
@sm2017 @patrickschmelter @deecewan @tommeier @vonovak
Gentlemen, I need your help to reproduce this issue. Since it happens only on specific combination of phone and Android version, I need to know what exactly you’re running.
Could you please use this APK and attach here the report it produced? get-device-info.apk.zip
Best regards, John
I can confirm that downgrading to 4.0.5 solves the issue. Maybe linked to #314
Ok, I also will revert to
4.0.5because:6.2.0extracting one key on Android 8.1: In debug: 8 sec In release APK: 15 sec4.0.5extracting one key on Android 8.1: In debug: 3 secI tried disabling the warming, but that didn’t seem to help much. However changing the code in
getGenericPasswordhere did help. https://github.com/oblador/react-native-keychain/blob/master/android/src/main/java/com/oblador/keychain/KeychainModule.java#L292From this:
To this (same code used in
setGenericPassword):My Samsung Galaxy S8 went from 3+ seconds (sometimes 5 or 10) to < 1 second. I am also specifying storage of
AESexplicitly in the RN options for both get and set operations. I’m guessing this will only help if you don’t need RSA, ie fingerprint.react-native-keychain: 6.0.0 react-native: 0.62.2
Same issue for me. In Simulator (API28) and on a Huawei P30 Pro (API29) it works super fast, on a Samsung SM-J730F (API28) it takes way beyond 10 seconds sometimes and fails with following exception. I experience it only happening the very first time after installing the app or wiping app data.
I downgraded to v4.0.5 , it is fast on android 10 , just 30ms
Please try out 8.0.0 which has performance improvements
No
This solves the issue for me, because after trying commenting and changing some code, i found that the
getCipherStorageForCurrentAPILevelmethod its too slow in some devices. So if you replace that code with thegetSelectedStoragemethod (the same used insetGenericPassword), this method first check if you are calling it with thestorageoption, and in that case, returns that one. If you are not passing it, then thegetCipherStorageForCurrentAPILevelmethod is called, so the logic is the same. So if you know what type of storage are going to use (as in my case), you only need to replace that code and pass thestorageoption both insetGenericPasswordandgetGenericPassword.Also yo need to disable the warmup.
Are there possibilities to add this change in the next release or is it made that way for some specific reason? I haven’t gone far enough into the source code.
@tranquan not sure if will help your use case, but I had good results specifying storage option AES and altering the getGenericPassword function as per: https://github.com/oblador/react-native-keychain/issues/337#issuecomment-639323583
Possible optimization:
Instead of trying and catching the exception we can check the hardware features availability.
src: https://stackoverflow.com/questions/58502299/how-to-check-for-strongbox-keymaster-hardware-availability-before-key-generation
Don’t forget put this to project/settings.gradle
include ':react-native-keychain' project(':react-native-keychain').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keychain/android')@juanektbb not sure if disabling warmup is required, but for me the slowdown persisted until I made those native changes you’ve mentioned and explicitly passed
storage: Keychain.STORAGE_TYPE.AESto bothsetGenericPasswordandgetGenericPasswordin the JS.i’m not sure we explicitly need more device info here. the cause is the lack of strongbox and how long the OS is taking to tell us that. there’s a path to a solution that more info isn’t necessarily going to help.
Issue is easily reproduced on Xiaomi Redmi Note 8 Pro (MIUI 11.0.3.0, Android 9), app launch can take up to 45 seconds, blocking the main thread while getting generic password. Downgrading
react-native-keychainto 4.0.5 fixes the issue.On google devices and emulators it works fine.
@forkeer Thanks a lot! What was the startup time?
I updated the APK, should work now. Sorry for the inconvenience.
Alternatively, you can clone the source from this repo and run it in Android Studio.
@sm2017: I can vouch for @john-y-pazekha
I totally understand your concern. Please rest assured that this APK is not malicious.
When installing an APK, you have a chance to review the permissions it requests. You can see that this one requests no permissions at all. There is no virus in it (sorry, I was too lazy, maybe in the next version 😃)))
Alternatively, you can clone the source from this repo and run it.
@sm2017 @patrickschmelter @deecewan @tommeier @vonovak Please use either way to produce the log. I really need this information.
@sm2017 given more than one person is seeing this, I guess the issue is indeed present. I’m dealing with other stuff now and this is not a priority for me.
Cc @OleksandrKucherenko as he might have more insight.
As always, if you have an issue, I recommend you contribute a PR with a fix. Thank you!