Skip to content
M. SALL
Work

Engagement at Engy Partners · July 2025

TerangaID

A mobile digital-identity wallet: certificate-based authentication, CSR generation, and private keys held by hardware with an explicit software fallback.

Problem
A sovereign digital identity cannot keep its private keys in the app's file system — it needs hardware isolation.
Outcome
A wallet shipped on Android and iOS: biometric authentication, certificate lifecycle management, private keys that cannot be extracted from the TEE.
Role
Mobile & security developer
React NativeTypeScriptKotlinPKI X.509CSRAndroid Keystorereact-native-keychainreact-native-biometricsWebCrypto

What problem does TerangaID solve?

A digital identity wallet is worth exactly one guarantee: the user's private key has never left their phone and cannot be made to.

Everything else — the interface, synchronisation, consent screens — is ordinary software. That guarantee is not: it cannot be obtained in software.

What is the structural constraint?

Storing a key in React Native's AsyncStorage, even encrypted, means storing the key and its encryption in the same place. On a rooted device, it is gone.

The answer is the TEE (Trusted Execution Environment) — Android Keystore on Android, Secure Enclave on iOS. The key is generated there and cannot be extracted: you can only ask it to sign.

That forces an inversion: the application never handles the key, it handles a reference to a key it will never see. All signing logic becomes asynchronous and fallible — the user can refuse biometrics, the OS can invalidate the key if the fingerprint set changes.

How is TerangaID architected?

Certificate-based authentication, not passwords. The device generates its own key pair, produces a certificate signing request (CSR) and is issued a certificate. Identity stops being a shared secret someone can steal: it becomes a key the device holds and proves possession of.

A native Kotlin bridge to the hardware. An Android key-management module exposes a minimal surface to React Native: generate a pair, sign, attest. The TypeScript code sees only those operations, never the key.

A factory that picks its keeper. This is the decision I am happiest with: a KeyManagerFactory chooses at runtime between a hardware-backed and a software-backed key manager. Not every device has a secure enclave — and a wallet that refuses to start on an entry-level phone serves nobody. The fallback is explicit and traced, so the level of guarantee is known to the application rather than assumed.

Recovery through a mnemonic phrase. A key held by hardware is a key you lose with the device. Encrypted backup and a recovery phrase answer the only scenario that genuinely matters to a user: the broken phone.

Biometrics unlock, they do not authenticate. The fingerprint releases use of the key; it is the key's signature that proves identity. Conflating the two means resting an identity on a sensor.

What did TerangaID teach me?

Useful security work was not adding layers of encryption but reducing the surface: identifying the single operation that must be inviolable, pushing it into hardware, and accepting that everything else is ordinary code to be audited as such.

A project of the same calibre ?

Based in Thiès, available in dakar & remote. I reply within 48 hours.

Let's talk