a41eeb8bfa
The reported pain: changing the pattern destroys the local cache every time. That is Android doing exactly what it promises - a key created with setUserAuthenticationRequired is invalidated the moment the screen lock changes, so a new lock cannot open data sealed under the old one. No storage format changes that, which is why SQLite would not have helped: the problem is what the key is tied to, not what the file looks like. So the cache gains a third sealing format, VER_PIN, with two layers: inner - AES-GCM under PBKDF2(code, 100k) : it takes the code outer - the Keystore AES key WITHOUT the auth constraint : it takes the device The outer key is never invalidated, so the file survives any change to the screen lock; the code restores the protection that removing the constraint would otherwise cost. 100k iterations rather than 600k because a four to six digit code carries little entropy - more rounds mostly slow the honest user, and the real barrier is the outer layer requiring this phone. The code lives in a fourth settings field and is NEVER stored: empty at every launch, typed to open, and used to re-seal on every write. That is what separates it from the token, whose persistence is a convenience with no consequence since it only opens ciphertext. Built but NOT installed - the phone went off the network. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>