Android Keystore: Fort Knox or Glass Box?

3 min read

June 15, 2025

Android Keystore: Fort Knox or Glass Box?

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 or Cipher.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 or MobSF to decompile the APK
  • 🔐 Look for KeyGenParameterSpec, Cipher, or Keystore.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

🛠 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

Botón Anterior
Active Directory Enumeration: Mapping the Kingdom Before the Siege

Previous Issue

Cracking the iOS Keychain: What It Protects, Where It Fails

Next Issue

Enjoyed the article?

Subscribe to the newsletter and get technical insights, cybersecurity tips, and development content straight to your inbox. Or support my work with a coffee ☕ if you found it useful!

📫 Subscribe now ☕ Buy me a coffee