Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
keycache
Welcome to keycache
🎉
keycache
is an application that can cache passwords and other secret data in a semipermanent way, without exposing
them to the filesystem or similar. It works by sealing the key with the built-in secure element and storing the
encrypted, sealed keyfile instead.
keycache
provides a quick-and-easy compromise that allows you to store and provide individual secrets in a
non-interactive way for scripts etc, or in a fast-interactive way via PIN or biometry; as opposed to plaintext files or
dedicated one-size-fits-all password manager setups.
Authentication Levels
keycache
provides different authentication levels when it comes to unlocking a sealed key:
unauthenticated
: Anyone, who has access to the sealed keyfile can unlock the key, if the secure element is available and cooperative.interactive
: In addition to the sealed keyfile, the user must provide a PIN, or perform a similar interactive challenge to unseal the key.biometry
: In addition to the sealed keyfile, the user must perform a biometric challenge to ensure that they themselves are physically present to unseal the key. Please note that for security reasons, implementations may invalidate cached keys if the enrolled biometry changes.
Implementation
To seal a key, we generate an (indirectly) hardware-backed key-encryption-key, and seal the key with AES256-GCM and a random nonce. The encrypted key is then stored in a file, together with the necessary metadata.
Supported Platforms and Platform Specific Implementation: macOS
For macOS, we use the secure enclave to seal the key:
- We request the SEP to generate a new hardware-backed P256 ECDH keypair with the correct access level.
Currently we use
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
for access levelunauthenticated
,kSecAttrAccessibleWhenUnlockedThisDeviceOnly
withkSecAccessControlUserPresence
for access levelinteractive
, andkSecAccessControlBiometryCurrentSet
for access levelbiometry
. - We generate another random P256 ECDH keypair, and immediately drop the private key so we end up with a valid static public key only.
- We ask the SEP to derive an ECDH shared secret with the hardware-backed private key, and the other static public key. The resulting shared secret is hashed with SHA256 – the resulting output is the key-encryption-key.
Security Considerations
As always, security assessments depend on the attack scenarios they should protect against. Neither hardware security elements, not biometry offer perfect security. There have been successful attacks against biometry sensors, as well as secure elements to trick them or extract secret key material. Additionally, challenges like PIN entry are usually susceptible to keyloggers or similar attacks, and thus cannot guarantee "true interactivity" either.
As always, if you have specific security requirements, it is mandatory that you evaluate the specific implementation and authentication level you intend to use against the potential attack scenarios you want to protect the secrets against.
⚠️ HAZMAT ⚠️ – Backups and Long Term Storage
Critically, as with other caches, keycache
stored data is not suited for long-term or permanent storage. As the
secrets are encrypted with hardware-backed keys, they are effectively lost if the secure element refuses decryption. TPM
reset? – cache is invalidated. Unexpected change in system state? – cache is invalidated. New biometry enrolled? – cache
is invalidated. Hardware defect? – cache is invalidated.
And while the cache should remain valid for most of the time during normal daily operations, you must remain aware that
supposedly small changes like software or firmware updates could invalidate the cache sometimes. Therefore, it is
crucial that you use keycache
only – as the name implies – as cache, and not as long-term-storage solution.
Long-term secrets should always be stored somewhere else and then imported into keycache
, so if the cache is
invalidated by whatever reason, you don't loose any data.