← Blog ·

Mobile Attestation: The Missing Link in Secrets Security

What Is Mobile Attestation?

Mobile attestation is a cryptographic proof that a request to your backend — or a request to decrypt a secret — really comes from a genuine, untampered instance of your app, running on real hardware. Not an emulator, not a rooted device, not a script pretending to be your app.

Apple's implementation is App Attest. Google's is Play Integrity. Both work the same way at a high level: the OS and a hardware-backed secure enclave generate a key pair tied to that specific app installation, and every attestation request produces a signed statement the vendor can verify was generated by real hardware running your real binary.

Why This Matters for Secrets, Not Just Logins

Most authentication systems answer one question: does this user have valid credentials? That tells you who is asking. It doesn't tell you where the request is coming from, or whether the client executing it is the one you actually built.

If your mobile app needs to decrypt an API key, a database credential, or an OAuth token client-side, credentials alone aren't enough. A stolen session token, a repackaged APK, or a script hitting your API directly can impersonate a legitimate session without ever touching your real app binary.

That's the gap mobile attestation closes: it verifies the client, not just the user.

How Koove Uses Attestation

Koove is a zero-knowledge secrets manager: secrets are encrypted client-side with X25519 + AES-256-GCM envelope encryption (HKDF-SHA256 for key derivation), and the server only ever stores ciphertext. It never sees plaintext secrets, and it can't decrypt them either.

That means the private key that unlocks a secret has to live somewhere — and that somewhere is the device. Attestation is what lets Koove trust that device before releasing key material to it.

Concretely:

  • On mobile, the @koove/sdk package handles this for you. You initialize a client, and init() runs attestation and registers the device:
import { KooveClient } from '@koove/sdk';

const client = new KooveClient({
  apiUrl: 'https://api.koove.io',
  appId: 'app_xxxxxx',
  appToken: 'tok_xxxxxx',
});

await client.init(); // attests the device + registers it
const secret = await client.decryptSecret(envelope); // gated by biometrics
  • init() runs App Attest on iOS or Play Integrity on Android under the hood. Only after that attestation succeeds does the device get added as a valid recipient of encrypted secrets.
  • decryptSecret() then requires biometrics on top of that — attestation proves the app instance is genuine, biometrics proves the human holding it is authorized.

Since July 14, 2026 on iPhone and July 17, 2026 on Pixel devices, this attestation is verified end-to-end on physical hardware on both platforms. There's no developer bypass mode — you can't skip attestation in production to make testing easier, and that's intentional. A "just for dev" shortcut is exactly the kind of hole that ships to production by accident.

Where Secrets Actually Come From

In practice, most teams manage this asymmetry with @koove/secrets-cli:

koove set STRIPE_SECRET_KEY sk_live_xxx --env prod
koove set DATABASE_URL postgres://... --env prod
koove list --env prod

Your code never sees the raw value at write time — you or your AI coding assistant stores it once via the CLI, and application code only ever references it by name. This matters more every quarter: AI pair-programming tools routinely paste live credentials into commits, chat logs, and generated .env files, because they don't know a string is a secret. We cover this in more depth in our piece on AI-era security.

When a mobile client needs that secret, it isn't asking a server "please send me STRIPE_SECRET_KEY." It's presenting an attested identity, decrypting a ciphertext envelope it already has (or was just handed, still encrypted), and only then exposing the plaintext value to your app's memory, behind biometrics.

Managing Devices

Attestation happens per install, so device lifecycle matters. The CLI gives you visibility and control:

koove devices --env prod
koove device-approve <device-id>
koove device-revoke <device-id>
koove rewrap --env prod

device-revoke removes a device as a valid recipient going forward. rewrap re-encrypts secrets for the current, approved set of recipients. It's worth being precise about what this does and doesn't do: revoking a device stops it from decrypting future requests and rewrapped envelopes — it does not, and cannot, un-deliver a secret value that a compromised device already decrypted and read before revocation. No secrets system, Koove included, can honestly claim otherwise. If a secret was exposed, rotate it.

What Attestation Does Not Solve

Being upfront about limits is part of being trustworthy here:

  • Attestation doesn't defend against a fully compromised OS or kernel-level exploit on a device that somehow still passes the check — it raises the bar significantly, it doesn't make an app "unhackable."
  • Koove's encryption scheme has no forward secrecy (no Signal-style ratchet). It's envelope encryption with per-recipient key wrapping, not a messaging protocol, and we don't claim otherwise.
  • Attestation confirms the app instance and, with biometrics, the human holding it — it doesn't replace access control policy. You still decide who gets access to which environment.

The Missing Link

Encryption alone protects data in transit and at rest. Access control alone protects who's allowed to ask. Mobile attestation is what ties both to what's actually running — the piece most secrets tooling skips, because it's genuinely harder to build than a login form.

If you want the full architecture — how key wrapping, recovery, and attestation binding fit together — it's documented on our security and trust page. Pricing for teams that need this on mobile is on /plans, with current limits and answers at /faq.

Try It

If your app decrypts secrets on a phone — for a backend proxy, an internal tool, or a client that talks directly to third-party APIs — attestation isn't optional hardening, it's the baseline. Create a Koove account and wire up @koove/sdk in an afternoon; the CLI alone is worth it just for koove set.

AI-generated code

Your AI writes the code. Who guards the secrets?

The most common security failure in AI-generated apps is exposed credentials. With Koove, your own assistant stores every token from the CLI — encrypted on your machine, never in the code or the repo.