Blog
Notes from the code
Short write-ups on decisions I made in Cipher, Vigil and Fathom, with the code that backs them up.
What happens when a bank SMS reaches Cipher
How Cipher turns an incoming bank SMS into an encrypted ledger entry on Android: goAsync, a coroutine scope, a parser that returns null, and why the timestamp isn't the arrival time.
Where Cipher's database key lives, and what happens when it disappears
How Cipher protects its SQLCipher passphrase with the Android Keystore, migrates the old EncryptedSharedPreferences key, and refuses to silently replace a key it can't decrypt.
Reading DNS off an Android VPN without routing your traffic
How Vigil uses VpnService to see DNS queries only: a single /32 route to a sentinel resolver, a hand-written packet parser with bounds checks, and a protected socket that forwards every query upstream.
Matching 90,000 tracker domains with a reverse-label trie
Why Vigil stores its tracker list in a trie keyed by domain labels from the right: lookups cost the length of the name, and a match on a domain covers all its subdomains.
Which app asked? Attributing DNS queries to apps on Android
How Vigil maps a DNS query to the app that sent it using ConnectivityManager.getConnectionOwnerUid, and why a small LRU cache keeps it cheap.