Evaluate cryptographic controls in a mobile app by following each key rather than each algorithm. For every key, ask what it protects, where it is created, which code can reach it, how it changes and how it is replaced when a device is lost. Otukan keeps key material out of readable code, moves it into the Android Keystore and iOS Keychain wherever the platform offers them, hardens the code that uses keys and detects instrumentation attached to it, across Android, iOS, Flutter and React Native apps. Encryption protects data at rest and in transit. It does not protect plaintext while your app is using it, which is where runtime controls take over.
Data inventory
Most apps use cryptography in more places than their teams expect. The evaluation starts by naming each one and the boundary it defends.
| What is protected | Typical key | Boundary it defends | Where the key should live |
|---|---|---|---|
| Local records and cached files | Symmetric data key | Files on the device if another process or a backup reads them | Wrapped by a platform-backed key |
| Session and refresh tokens | Wrapping key | Token theft from storage | Android Keystore or iOS Keychain |
| Request signatures | Private signing key | Requests forged outside the genuine app | Created on the device, never exported |
| Payment or identity payloads | Server public key | Payloads read in transit beyond TLS | Public key in the app; private key on the server |
| Offline licences | Server verification key | Licence files edited by the user | Public key in the app, integrity-protected |
Two patterns show up in almost every review. A symmetric key sits in code or a resource file because it was the quickest way to ship. And a server credential sits in the app because a feature once needed it offline. Both belong elsewhere, and Otukan’s build report makes them visible.
Stored-data design for each platform is covered on Android app data encryption and iOS app data encryption.
Key lifecycle
Every key has four moments, and each moment has an owner. Writing the owners down is the most useful document an evaluation produces.
| Moment | Platform | Your app with Otukan | Your backend |
|---|---|---|---|
| Generation | Creates keys inside the key store, hardware-backed on Android devices that support it | Requests keys with the right usage limits | Issues server-side keys and registers device public keys |
| Access | Enforces user authentication or biometric gating where set | Reaches keys only through hardened code paths, and watches for hooking | Checks signatures and runtime signals |
| Rotation | Stores the new key | Re-wraps local data under the new key | Decides when rotation is due and retires old keys |
| Recovery | Does not move device-only keys to a new phone | Re-enrols after the user proves identity | Revokes old device keys and issues new ones |
Platform facts to respect
On Android, the Keystore keeps key material outside the app’s process, and on devices with secure hardware it can hold keys there. On iOS, the Keychain stores items under accessibility classes, and the device-only classes keep an item out of migration to a new phone. On supported iPhones, the Secure Enclave holds certain private keys for signing and key agreement. It is not a bulk encryption engine. Otukan handles each platform on its own terms.
Runtime scope
Encryption ends where use begins. To show a statement, the app decrypts it. To sign a request, the app calls the signing key. Those moments are what attackers target on a device they control.
When plaintext is needed
- Displaying decrypted records on screen.
- Building a request body before it is signed or encrypted.
- Comparing a user’s input with a stored secret.
What encryption does not prevent
- A hooked function returning plaintext to an attacker as it passes through.
- A debugger pausing the app just after decryption.
- A modified device on which the OS no longer isolates the key store.
- Screen capture of decrypted content.
Otukan closes this gap with runtime controls: it detects hooking of cryptographic functions, checks device integrity before sensitive key operations and sends signals to your backend so the server can reject a request that was signed on a compromised path. Controls for plaintext held in memory are on memory data protection.
Testing the key flows
Your team and ours agree a key map and test it. In an authorised lab, we hook the signing function on a protected build and confirm the signal fires and the server rejects the request. On a clean device, the same journey signs and verifies with no signal. Rotation and recovery are rehearsed on real devices, then install, update and sign-in are repeated for each protected release, with versions, results and reviewer recorded.
How key handling sits beside obfuscation, asset encryption and screen controls is covered on code and data protection.