Hello, what's the best option to store and secure ...
# android
a
Hello, what's the best option to store and secure your API keys ?
google 1
stackoverflow 2
o
I was looking into AccountManager these days for exactly the same use case. I’m curios what you came up with too. https://developer.android.com/reference/android/accounts/AccountManager
f
c
Plus one to encrypted shares preferences, very quick to setup and secure enough for most people
a
EncryptedFile is probably a better choice. SharedPreferences itself is broken by design and we may or may not let EncryptedSharedPreferences ever leave alpha because it implies that people should continue using it :)
(SharedPreferences will block the main thread to fsync on activities hitting onStop, doesn't correctly report errors, and reflects newly committed data immediately even if it hasn't been safely persisted to storage.)
😮 2
If you're using it for anything worth encrypting you should probably care about these things. 🙂
v
Wouldn’t encrypted shares preferences only work if you’re retrieving keys at runtime?
c
They were just talking about Encrypted Shared Prefs at Dev summit. Talking with security folks during sandbox hours they also had no objection to using it
There doesn’t appear to be a warning or anything either for this documentation: https://developer.android.com/topic/security/data
a
security-wise yes, it's secure. It just might fail to save your data and you will never know about it, or ANR your app between activities 🙂
c
Oh I gotcha, that makes more sense. 😬
d
also note that androidx.security has minimum SDK 23
c
Eh 21 is overrated anyway 😉 but that’s a good point. Our lowest version is thankfully 23
i
Java bytecode is weakest point of secure API keys
l
@Adam Powell Why are
SharedPreferences
doing an
fsync
in
onStop
and blocking the main thread?? And how come this is not documented? And finally, why isn't there recommendation from the javadoc to use something else if it's broken by design (for error handling mainly)?
a
For the fsync, the original intent was to ensure the write completed before potential process death. For the rest, longer story. 🙂 Historically things in Android have lasted for quite a while until a complete replacement can be presented.
l
Why the
fsync
thing hasn't been removed in recent Android versions? A lot of Android apps are still using
SharedPreferences
and this is not changing anytime soon given the friction plus the fact that the doc doesn't even mention it. End users would still benefit if a change is added into Android 11 to not do it on the main UI thread.
a
kind of an ongoing debate over how much value the documented "guarantee" it provides is actually adding, plus the associated work involved in changing the contract between ActivityManagerService and apps to make activity stop partially async to finish pending work like that. Since most people who care about this stopped using SharedPreferences a long time ago and enforce their own guarantees it hasn't gotten a lot of traction.
It's only a problem for SharedPreferences since it eagerly reflects changes to other observers within your app before the fsync happens so there's a possibility for inconsistency. More robust systems that need consistency don't do that and don't have the problem.
tl;dr: SharedPreferences is fine for storing whether the user wants to see a list or grid view, or light vs. dark mode. For storing actual data where any part of ACID matters it's not the right tool. And for most things you'd want to encrypt, at least one part of ACID matters.
l
BTW,
SharedPreferences
is an interface that can be implemented by anything that would not bring this performance issue to the users (let's be honest, the users pay the cost, the devs don't bother much…)
Actually, I implemented it with
NSUserDefaults
on macOS and iOS with Kotlin/Native, works great.
a
it's not a very good interface. 🙂
you have to make significant behavioral changes from the stock implementation to approach something more useful
l
That's right, but implementing it with a better thing than what's currently available allows to easily migrate old code.
a
sure, in an academic sense, but it's also just a map. Migrating old code even to something significantly different isn't a large task.
l
I completely agree with you that it's better to use something else with another API, but I've yet to see an alternative that is a good example for the same use cases like storing simple user preferences, and there's ton of code using it, that is making many/all phones slower with that
fsync
happening at the wrong time.
Migrating old code even to something significantly different isn't a large task.
You have to take into account ensuring you didn't break anything, and other considerations that actually make people not migrate that quickly or at all from poor APIs. So it's all relative, and right now, no one but us is aware that it's not great to use it, and I won't migrate all that tomorrow in all my projects, even the one I work on the most
a
that's up to you then ¯\_(ツ)_/¯
l
How would you design a SharedPreferences replacement that is reliable and never does I/O on the main thread? Because for now, I understood you'd not use
SharedPreferences
, but what you would do exactly instead is not clear to me.
a
if you can assume kotlin it's a lot easier, imo 🙂 for my own usage I generally lean on data classes, moshi's codegen plugin, and serializing to/from files, then a conflated
Flow<T>
to reflect changes to other interested parties only after they're written.
if you need to make all of that pleasant to use from java language callers it gets rougher
you can do something kind of like android's AtomicFile to make sure you don't end up with broken file contents for whatever reason https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/util/AtomicFile.java
l
Using
writeText()
or
writeBytes()
is not a good idea for this?
a
probably fine, the question is what do you do to prevent half-written files and other similar edge cases
l
So if I think about that (all linked to process death), I can make my own AtomicFile analogue with the Kotlin API I want safely?
a
Not even just linked to process death; unexpected shutdowns, errors in your app code during the write itself, plenty of reasons. 🙂 But yes, you can do a write to temp file and rename or any other atomic file techniques too
l
a
Yes
better answer not made from my phone: yes, and I was planning to take a look at it after the Thanksgiving holiday
c
It’d be worth calling this out more deliberately I’m documentation, folks on Reddit are very confused about what is writing with it. https://kotlinlang.slack.com/archives/C0B8M7BUY/p1574250911017900