FIDO2 Hardware Security Module key-manager. Interfaces directly with CTAP2 protocol locally in Python. Using your security key's hmac-secret extension using AES-256-GCM. More can be extended using python-cryptography or others. Limit to PIN is 63 chars UTF-8.
Works for any Fido2 compliant USB hardware: YubiKey (Yubico), Titan (Google), SoloKey (US based open-source), Nitrokey (German leader in HSM), ...
Why ?
- Cloud < hardware only
- Cannot fish hardware keys or harder to do (would need browser permissions).
- Cannot exfiltrate something that never leaves your device(s).
- Guided but enforced hardware binding
- If your key does get stolen, 8 PIN attempts and all keys are gone forever.
- Earns you time, sudoless sudo, etc and peace of mind
- Still works with respective web/mobile apps for auth on websites, etc
In case your distro doesn't package directly:
- KEKeys/ - Setup helpers for
pam-u2fto build from source latest version for any init system. - And integrate to
pam.dfor system-login, login-manager, etc...
Helps you blend HSM with software even if not packaged by your distro, if it is:
Set-up on arch (which asumes base-devel git tar openssl):
sudo pacman -S pam-u2f libfido2 python-fido2 python-cryptography
./terces list # List devices
./terces info <term> # Example "algo", empty for full info
./terces setup # Generate mappings file (prompts if PIN is setup already)
./terces help # Show all commandsGlobal mappings require sudo. Per-user mappings DO NOT.
./terces unlock # Test auth on .cfg
./terces gen <x> <name> # Generate password (optional: length, store as name)
# ^^^^ Name is empty DO NOT save just generate
./terces encrypt # Store secret (prompts: name, secret, optional description)
./terces decrypt # Retrieve secret (prompts: name)
./terces vault # List stored secrets in vault
./terces delete <name> # Delete a secret from vault
./terces reset # Deletes all locally stored keys
./terces test <type> <opt> # Run test type with options see /tests/βββ[04:56]β[systemuser_$@hostx]β[~/somewhere]β[04:56]β[git:master]
ββββΌ $ echo "##Terces Demo##"
##Terces Demo##
$ cat example.secret | sudo ./terces encrypt api-key "importantkey"
$ sudo ./terces decrypt api-key | xclip -sel clip
$ sk-abcdefghijklmnopqrstuvwxyz1234567890Pipe frienly ! Again sudo would not be required if using per-user mappings.
Tip
Set a strong PIN on your key but do make sure it's still relatively easy for you to enter, since 8 attempts is the default full lock-out value. Setup local usage since the integration with browsers is already pretty neat, wanted to have a way to achieve the same for local secrets.
See again KEKeys/ if you want to compile from scratch and understand a bit more in depth.
Important
If you've already have registered keys please see multi-hosts installs Portable Do not run setup again as you can keep your exisitng mappings if needed. Or start fresh if desired should be an option in app of provider.
- Keynames are up to you to remember. derived
nameandkey_handlewhich is never actually stored. - Delete files - After encryption, originals remain. Remove them when ready. Terces only print a reminder.
Disclaimer: The project will not be built as a backwards compatible one, terces expect the user to not update if they are keeping important data. Security is being pro-active and finding edge-cases, so building each piece of code with backwards compat would be both a risk and impossible to maintain.
You can use:
./terces version # Check for remote hash
./terces update # Clones fresh copy to different folderTip
Then re-enroll manually to upgrade/migrate. For this purpose keys are stored as a clear convention inside where TERCES/ lives as: .d/terces-0003
This also creates a sub-crypt which means the limit of serets is now not 100 but infinite. You obviously keep registering keys in the hardware too normally.
- Use
listandinfoto see key capabilities. - Use the
terces.cfgfile to configure to liking or control multiple FIDO2 devices.
See reference table: DevConfig
- Running from Python in isolated venv
There is a helper script zpya that downloads Python deps from pip in .venv
- Installing somewhere
You can place TERCES/ anywhere on the system or removable media
Then create a symlink either: Check paths: echo $PATH
sudo ln -s /home/johndoe/TECRES/terces /usr/local/bin/terces or any other bin/terces location.
Or alias terces='/path/to/TERCES/terces' To use only in shell env.
Note
Once this is setup you do not need the ./ before commands anymore.
To enroll existing you can see portable or simply copy existing mappings to target carefully.
And make sure that the original pam://hostname matched in rp_id of terces.cfg
cp path/to/mappings /path/to/usb/mappings
# perform the same inversly on the targetSome actions require several PIN/BIO auths for a simple reason: Terces never caches anything. Only interface directly with assertion patterns of the keys themselves. Some other actions do not need interaction at all.
Benchmarks α―ππ»ββοΈββ‘οΈ
Dell enterprise laptop (NVMe M.2 SSD 256GiB): Intel(R) Core(TM) i5-1345U (12) @ 4.70 GHz 16 GiB RAM - Intel Iris Xe Graphics @ 1.25 GHz On Ext4 Full Disk Encrypted.
| Operation | Size | Speed |
|---|---|---|
| File Enc | 10 GiB | 569 MiB/s |
| File Dec | 10 GiB | 540 MiB/s |
| File Dec | 2 GiB | 1295 MiB/s |
| Share | 2 GiB | 1097 MiB/s |
| Unshare | 2 GiB | 1297 MiB/s |
Using 100 files of 20MiB each /dev/urandom
| Compression | Tar | Enc | Dec |
|---|---|---|---|
lz4 |
3.6s | 881 MiB/s | 1239 MiB/s |
zstd |
3.7s | 812 MiB/s | 1257 MiB/s |
gzip |
35.2s | 944 MiB/s | 1240 MiB/s |
none |
1.2s | 757 MiB/s | 970 MiB/s |
./terces test large 2048 # Single file in MiB
./terces test asym 2048 # Asymmetric in MiB
./terces test folder 50 20 # 50 files x 20 MiBMore... π
Encrypt/decrypt files or folders using FIDO2 hmac-secret derived keys. Works from root dir where terces lives
./terces file enc /path/to/file <dest> # Creates file.trcs or folder.tar.trcs
./terces file dec /path/to/file.trcs <dest> # Restores original
destis optional and by default uses same dir of source file. Ex: file is in project root ofTERCES/
./terces file enc lol.jpg
./terces file dec lol.jpg.trcs ~/Pictures/ Important: Key is derived from key_handle + filename β renaming .trcs files breaks decryption. This also strips old metadata; only ciphertext + nonce and new file details remain.
./terces keypub <label> # Prepare for sender public key (optional label)
./terces share <file> <pubkey> # Encrypt for recipient (no need for FIDO2 key)
./terces unshare <file.shrd> <label> # Decrypt from sender using FIDO2 key (optional label)
labelis optional but makes keys non-deterministic like previous approaches in this repo.
Generate SSH keys backed by your security key. Requires terces auth before key generation.
./terces ssh <name> # Generate resident ed25519-sk key or --no-res
# Set it up with respective provider
./terces ssh test gitlab.com # Test directly (with your provider)Can find more info GITUTILS
Keys are saved to ~/.ssh/id_<name>_sk and public key is stored in terces vault as sshX:<name>. Can then be retrieved through decrypt function or locally.
Note: Uses OpenSSH's native FIDO2 support. Your key must support the eddsa algorithm.
Create challenges using json files exportable to others for verification.
This can be used as an API from FIDO2 backed device to say a server? From local to remote verif: See NZKP
You server can then receive and verify time bound auths directly.