Android Keystore: Fort Knox or Glass Box?
3 min read
June 15, 2025

Table of contents
👋 Introduction
Hey everyone!
When it comes to mobile security, most developers trust the Keystore like it’s untouchable.
But what is the Android Keystore really? What does it protect? What doesn’t it? And more importantly, how can we, as pentesters, test whether it’s used properly?
In this issue, we’ll break down what the Keystore is, how it works, where it fails, and how to test apps that rely on it.
Let’s crack open the vault 👇
🧠 What is the Android Keystore?
The Android Keystore is a secure system service that allows apps to generate, store, and use cryptographic keys without exposing them to the app or the filesystem.
These keys are:
- Non-exportable – you can use them, but you can't read them.
- Stored securely – ideally in the TEE (Trusted Execution Environment) or StrongBox, a hardware-backed secure element.
The Keystore is designed to allow secure usage of:
- RSA, AES, EC keys
- Key signing, encryption/decryption
- Keys bound to user authentication or hardware state
But here’s the kicker: you don’t store secrets in the Keystore you store keys. If you want to protect a token or password, you encrypt it with a Keystore-managed key and store the ciphertext.
🧨 Common Developer Mistakes
The Keystore sounds great but it’s often misused. Here are the most common mistakes developers make, and what they really mean in practice:
Saving the encrypted data in external storage
“But it’s encrypted, so it should be fine, right?”
Even if you encrypt a secret using a Keystore key, storing the encrypted blob in public locations like /sdcard/
or Downloads/
is dangerous. Other apps or attackers can access it.
💥 As an attacker: Grab the encrypted file, hook the app with Frida, and dump the decrypted content when it’s used.
Not requiring user authentication to use the key
“The key is stored in the TEE, that means it’s secure!”
Not necessarily. If setUserAuthenticationRequired(true)
wasn’t used during key creation, the app (and malware) can use the key at any time, even if the device is locked.
💥 As an attacker: Hook Cipher.doFinal()
to decrypt data without unlocking the phone.
Assuming keys are hardware-backed
“I’m using StrongBox, so the key is safe.”
Many apps don’t check whether the key is truly stored in secure hardware. If not supported, Android silently falls back to software storage less secure and more exposed.
💥 As an attacker: On emulators or rooted devices, software Keystore keys are easier to extract or abuse.
✅ Dev tip: Use KeyInfo.isInsideSecureHardware()
to verify.
Storing secrets directly in SharedPreferences
“It’s just a token, I’ll store it in prefs for now.”
Big mistake. SharedPreferences
files are stored as plain XML. Even if encrypted, if not done properly with Keystore + internal storage, they can be exposed.
💥 As an attacker: Dump the preferences file or memory and extract the secret.
Hardcoding secrets or crypto keys in the source code
“It’s just a small AES key for internal use.”
Anything hardcoded in your app is recoverable. With tools like jadx
, static secrets are one Ctrl+F
away.
💥 As an attacker: Reverse the APK, extract the key, and decrypt any data protected with it.
🛠️ Tools of the Trade
Use these tools to detect and exploit poor Keystore usage:
- Frida – Hook crypto functions like
Cipher.init
orCipher.doFinal
- objection – Quick Android app inspection & dynamic testing
- MobSF – Detect improper Keystore/API usage via static analysis
- jadx – Reverse engineer APKs to detect hardcoded keys/secrets
🧪 Labs & Practice
Unlike other issues, there’s no Hack The Box machine or CTF lab recommendation this time.
Keystore vulnerabilities are highly app-specific and subtle there’s no standard environment that captures all the edge cases.
So instead of following a guided challenge… you’ll have to get your hands dirty.
Here’s how you can practice:
🔍 Option 1: Reverse a real app
Pick any Android app (even a simple one) and analyze how it handles sensitive data:
- 🔎 Use
jadx
orMobSF
to decompile the APK - 🔐 Look for
KeyGenParameterSpec
,Cipher
, orKeystore.getInstance
- 🧩 Check if keys require authentication (
setUserAuthenticationRequired
) - 🗝️ Check how secrets are encrypted and where they’re stored (internal? external? SharedPreferences?)
- ⚔️ Hook the app with Frida and try to:
- Call
Cipher.doFinal()
directly - Bypass biometric UI checks
- Extract secrets from memory
- Call
🛠 Option 2: Build your own test app
Want full control over the environment? Write a minimal app that:
- Generates a key using Android Keystore
- Encrypts a token with that key
- Asks for fingerprint before decrypting
Then try to break your own implementation:
- What happens if you remove
setUserAuthenticationRequired(true)
? - Can you still decrypt the token with Frida or via memory dumps?
- Can you extract the ciphertext from internal storage and reuse it?
Final Thoughts
The Keystore isn’t a silver bullet. It’s a powerful tool but only if used properly.
As pentesters, we need to understand:
- What the Keystore actually protects
- What parts of the chain are still vulnerable (storage, memory, usage)
- How to spot and exploit weak implementations
Next time you hear “don’t worry, it’s in the Keystore” smile, nod, and open up Frida.
Until next time,
Stay sharp, stay testing,
Ruben 🚀
Chapters

Previous Issue
Next Issue
