Security

Last Updated: May 23, 2026
The short version: Your passkeys are standard WebAuthn ECDSA P-256 credentials, stored on your personal MIFARE DESFire EV3 NFC card under AES-128 application keys derived from your PIN. Nothing about a passkey ever persists on the phone—while in use, keys live only in RAM and are envelope-encrypted under a non-exportable Android Keystore key. There is no cloud, and there is no Login backend.

Why we publish this

Security that relies on being secret is brittle. Login is built on published, auditable standards (WebAuthn/FIDO2, AES, PBKDF2, ECDSA P-256) because standards survive scrutiny—and customers buying authentication for frontline workers have a right to know exactly what they’re trusting.

What follows is the architecture at the altitude an informed buyer needs. Lower-level implementation notes and our internal security review live in the project repository and are shared with customers and auditors on request.

Design principles

Threat model

What Login protects against

ScenarioWhat protects you
Phone is lost or stolen No passkeys persist on disk. The card is required to load them; without it, there is nothing to extract.
Card is lost or stolen No PIN ⇒ no access. Application keys are derived from the PIN; without it, the card data is unreadable.
Attacker tries PIN guessing on the phone After 3 wrong attempts, the in-memory cache, the stored PIN hash, and any locally held passkey state are wiped. The user has to tap their card again to start a new session. The card itself authenticates with a key derived from the PIN; a wrong PIN yields a wrong key and authentication fails, offering no oracle.
NFC eavesdropping during read/write All NFC traffic is sent in DESFire Enciphered mode with per-session keys negotiated during authentication.
ADB backup extraction Disabled at the manifest level.
Phishing site impersonating a real login page WebAuthn passkeys are origin-bound by the browser. A passkey for github.com cannot be used on g1thub.com, even if the user is fooled.
Static reverse engineering of the APK Release builds are obfuscated with R8 and signed via Google Play App Signing. Obfuscation slows analysis; it doesn’t replace the cryptographic protections above.

What Login does not protect against

Honest disclosure matters more than marketing claims. These are the scenarios where Login cannot help, by design.

Building blocks

Layer What we use Why
Passkey cryptography ECDSA on the NIST P-256 curve (WebAuthn COSE algorithm -7) The default WebAuthn algorithm; supported by every relying party that supports passkeys.
Card primary storage MIFARE DESFire EV3 with AES-128 application keys Hardware-isolated application domain. Authentication required for any read or write.
PIN-to-key derivation PBKDF2-HMAC-SHA256, card UID as salt, 600,000 iterations by default (configurable up to 2,000,000) Meets OWASP 2023 guidance at the default; higher levels available for cards that warrant them. Per-card salt prevents a single shared rainbow table.
Stored PIN hash on phone PBKDF2-HMAC-SHA256, 600,000 iterations, random 16-byte salt per device Lets the app verify an entered PIN before going to the card. The PIN itself is not stored or recoverable.
NFC over-the-air DESFire CommunicationType.Enciphered with per-session keys Defeats passive eavesdropping, including specialised NFC sniffing rigs.
Passkey use on the phone In-memory only. Each private key is envelope-encrypted with AES-256-GCM under a non-exportable Android Keystore wrapping key; nothing persists on disk. Nothing for forensic tooling to extract from a powered-off or factory-reset device.
App distribution Google Play App Signing (Google manages the production signing key) Removes the risk of a leaked or lost private signing key.
Release builds R8 minification & obfuscation, release-only logging stripped Raises the cost of static analysis. Not a substitute for cryptographic security.

What we do not have

See the Privacy Policy for the full list.

Independent verification

Reporting a vulnerability

If you believe you’ve found a security issue, please email support@phenomenal.se with the details. Please do not post details publicly until we’ve had a chance to respond. We treat security reports as high priority.

What changes here

Cryptography evolves. We will update this page when we change parameters (for example, raising PBKDF2 iteration counts), adopt new algorithms (such as hardware-backed ECDSA on Android Keystore for non-synced credentials), or learn about a vulnerability in a primitive we depend on. The “Last Updated” date at the top reflects material changes.