The Strongbox and the Secure Enclave are hardware implementations physically separated from the main processor and are designed to withstand powerful adversaries that gain root control over the OS. They store private keys that never leave the chip (device) and can be used to perform certain cryptographic operations.
Cryptography
Unfortunately, both the Strongbox and the Secure Enclave currently don’t support Zenon’s Ed25519 signature scheme. They only have support for ECDSA, namely NIST P-256 over the secp256r1 curve.
Fortunately, we can use Elliptic-curve Diffie–Hellman or ECDH to encrypt a secret using the public key and decrypt it using the corresponding private key.
Here are the operations that will provide hardware level security for the Zenon wallet:
Generate 2 keypairs inside the Secure Enclave for the shared secret
Ask the user for a PIN/passphrase
Use a Key Derivation Function (KDF) over the PIN/passphrase such as Argon2 (already used in Zenon)
Encrypt the user’s PIN/passphrase with the shared secret using AES-256-GCM (already used in Zenon)
Generate a strong, random password for the Zenon keystore
Encrypt the password using the user provided PIN/passphrase
Encrypt the keystore using the strong password generated earlier
Authenticate the secure enclave operations using biometric hardware (TouchID/FaceID)
The whole idea is to never expose the PIN/passphrase that is needed to decrypt the password, which in turn is needed to decrypt the keystore (wallet) in the device’s memory.
The user creates and confirms a 6 digit PIN, user_pin. The user_pin in encrypted using ECDH and the secure enclave’s* public keys. Class 3 Biometrics are required to decrypt the user_pin and all the operations are performed inside the secure enclave. On Android, Strongbox is preferred over TEE.
A strong keystore_password is generated securely using Random.secure() function. The user_pin is used to encrypt using Argon2 KDF and AES-256-GCM the keystore_password. The keystore_password is stored using flutter_secure_storage.
The keystore_password is used to encrypt the Zenon keystore that is stored in the application’s directory.
(*) All recent iPhone models and flagship Android phones have support for secure element chips that are physically separated from the main processor.
The timeout for biometric authentication is 10 seconds. The user_pin is never present in the RAM. The keystore_password is securely cleared (by overwriting data) from the RAM as soon as a sign event is done and the keystore is encrypted right away.
B. Time-based One-Time Password
TOTP will be used to secure sensitive operations within the mobile wallet such as viewing the seed, signing transactions or disabling security features (such as FaceID or TouchID). The shared_secret will be encrypted using the user_pin. The 6 digits TOTP codes will be generated using Algorithm.SHA256 and will be valid for 30 seconds. They will be compatible with popular TOTP apps such as Google Authenticator.
C. Audit log
Audit log with timestamps for accessing sensitive information (for example view_seed_phrase/dump_mnemonic event).
D. Cooldown period
Minimum cooldown periods with exponential backoff for wrong PIN or invalid TOTP code input.
E. Anti Blind Signing
Show the user all the information regarding what is being signed on the device.
F. Advanced mobile security: Mobile Runtime Application Self-Protection
Integration of an in-app SDK with advanced self-protection capabilities:
Root or jailbreak detection
Hooking framework detection
Untrusted installation method detection
App/Device (un)binding detection
Brute-force attack detection
Application runtime integrity checks
@cagri if you have other ideas regarding the security of the mobile wallet, please let me know.
Some additional thoughts, although not technology specific:
-Challenge for biometric unlock whenever the app is swapped, closed or minimized
-Challenge for biometric unlock for tx confirmation
-Prevent screenshot when showing mnemonic - but I would allow copy/paste
This is the main problem with cryptocurrency mnemonics: every digital copy - in a text file, a screenshot or even a simple paste from the clipboard can be considered a leak of your private keys.
If you allow copy-pasting the mnemonic you undermine the security of your users.
The only safe backup is the one using strong encryption like Syrius desktop wallet is offering: AES-256-GCM paired with a strong KDF like Argon2.
Agreed from a security perspective, but from a usability perspective users might want to copy to an offline storage mechanism or password vault. I think it would be fair to go either way with the copy/paste, but if it is prevented then maybe make it clear via popup it’s for their own security.
On android, screenshots get stored to image gallery immediately, and possibly uploaded to Google cloud etc. and with their automated AI it would likely OCR the words and have that stored in clear text - so it’s a definite no for that aspect imo
Secure enclave encryption
Time-based One-Time Password
Audit log for seed
Cooldown period for PIN
Anti Blind Signing for transactions
Advanced mobile security (root/jailbreak detection, emulator detection, etc.)
I’ve paved the way for this feature: YubiKey support for RSA-KEM (using AES-GCM) encryption, decryption, and key management. If you have a Yubikey, please help me test this implementation: