| .github/workflows | ||
| cmd/age-plugin-fido2-hmac | ||
| docs | ||
| e2e | ||
| internal | ||
| pkg/plugin | ||
| .gitignore | ||
| .golangci.yml | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
age-plugin-fido2-hmac
Warning
Please consider this plugin to be experimental until the version v1.0.0 is published!
Note
FIDO2 does not provide an API for asymmetric encryption; instead, this plugin uses the hmac-secret extension to protect an Age identity with your hardware key. For decryption, the identity is transferred to your computer's memory. If this identity is stolen from memory, it can be used without the token to decrypt past and future data meant for this identity. If you need a higher level of security and have the required hardware, please take a look at age-plugin-yubikey or age-plugin-tkey.
For symmetric encryption with FIDO2, please check out the official age-plugin-fido2prf plugin. You will need to present your token for every encryption, but you get the benefit that an attacker needs to intercept a different secret for every file.
🔑 Encrypt files with fido2 keys that support the "hmac-secret" extension.
#️⃣ Unlimited generation of recipients/identities because generated fido2 credentials are stateless.
📝 See the spec for more details.
Requirements
Ubuntu (>= 20.04)
sudo apt install libfido2-1 libfido2-dev libfido2-doc fido2-tools
Fedora (>= 34)
sudo dnf install libfido2 libfido2-devel fido2-tools
Mac OS
brew install libfido2
Installation
Download a the latest binary from the release page. Copy the binary to your $PATH (preferably in $(which age)) and make sure it's executable.
You can also use the following script for installation:
- Installs binary to
~/.local/bin/age-plugin-fido2-hmac(change to your preferred directory) - Make sure to adjust
OSandARCHif needed (OS=darwin ARCH=arm64for Apple Silicon,OS=darwin ARCH=amd64for older Macs)
cd "$(mktemp -d)"
VERSION=v0.4.0 OS=linux ARCH=amd64; curl -L "https://github.com/olastor/age-plugin-fido2-hmac/releases/download/$VERSION/age-plugin-fido2-hmac-$VERSION-$OS-$ARCH.tar.gz" -o age-plugin-fido2-hmac.tar.gz
tar -xzf age-plugin-fido2-hmac.tar.gz
mv age-plugin-fido2-hmac/age-plugin-fido2-hmac ~/.local/bin
Please note that Windows builds are currently not enabled, but if you need them please open a new issue and I'll try to look into it.
Build from source
git clone https://github.com/olastor/age-plugin-fido2-hmac.git
cd age-plugin-fido2-hmac
make build
mv ./age-plugin-fido2-hmac ~/.local/bin/age-plugin-fido2-hmac
(requires Go 1.22)
Usage
Generate a new recipient/identity
Generate new credentials with the following command:
$ age-plugin-fido2-hmac -g
[*] Please insert your token now...
Please enter your PIN:
[*] Please touch your token...
[*] Do you want to require a PIN for decryption? [y/n]: y
[*] Please touch your token...
[*] Are you fine with having a separate identity (better privacy)? [y/n]: y
# created: 2024-04-21T16:54:23+02:00
# public key: age1zdy49ek6z60q9r34vf5mmzkx6u43pr9haqdh5lqdg7fh5tpwlfwqea356l
AGE-PLUGIN-FIDO2-HMAC-1QQPQZRFR7ZZ2WCV...
You can decide between storing your fido2 credential / salt inside the encrypted file header (benefit: no separate identity / downside: ciphertexts can be linked) or in a separate identity (benefit: native age recipient, unlinkabilty / downside: keep identity stored securely somewhere). To decrypt files without an identity, add -j fido2-hmac instead of -i identity.txt to your age command (e.g. age -d -j fido2-hmac -o test.txt test.txt.enc) or use the output of age-plugin-fido2-hmac -m as the identity alternatively.
You are responsible for knowing which token matches your recipient / identity. There is no token identifier stored. If you have multiple tokens and forgot which one you used, there's no other way than trial/error to find out which one it was.
If you require a PIN for decryption, you (obviously) must not forget it. The PIN check is not just an UI guard, but the token changes the secret it uses internal!
Encrypting/Decrypting
Encryption:
age -r age1... -o test.txt.enc test.txt
(where age1... is the public key you created with the previous step.)
Decryption:
age -d -j fido2-hmac -o test-decrypted.txt test.txt.enc
or
age -d -i identity.txt -o test-decrypted.txt test.txt.enc
(where identity.txt is a file you created putting the AGE-PLUGIN-FIDO2-HMAC-1QQP... separated identity you created before.)
Choosing a different algorithm
By default, one of the following algorithms is picked (in that order): ES256, EdDSA, RS256. If you want the credential to use a specific algorithm, use the -a parameter:
age-plugin-fido2-hmac -a eddsa -g
Note that
- your authenticator may not support all algorithms,
- the length of recipient/identity strings can increase dramatically by using a different algorithm.
The default (in most cases) is "es256", which should provide the smallest recipient/identity strings.
Multiple keys
If multiple keys are present, the plugin will start a selection process by making all keys blink until one of them is tapped. Alternatively, you can specify the device you prefer by setting the FIDO2_TOKEN environment variable to the device path you get from fido2-token -L (for example /dev/hidraw7). Please note that this path is ephemeral and not a persistent identifier.
Notes for runnng under Windows
- the command must be run as an administrator
- in Windows 11 you have at least one default
windows://hellodevice available
Testing
Unit Tests
In order to run unit tests, execute:
make test
E2E Tests
End-to-end tests can currently no be run in the CI/CD pipeline because they require a virtual fido2 token to be mounted.
Use the following to setup a virtual test device with pin "1234" that always accepts any assertions:
go install github.com/rogpeppe/go-internal/cmd/testscript@latest # check PATH includes $HOME/go/bin/
sudo dnf install usbip clang clang-devel
git clone https://github.com/Nitrokey/nitrokey-3-firmware.git
cd nitrokey-3-firmware/runners/usbip
cargo build
cargo run -- --ifs ../../../e2e/test_device.bin
make attach # separate shell
Then run the tests using:
make test-e2e