Files
age-plugin-openpgp-card/README.md

84 lines
4.1 KiB
Markdown

# Age Plugin: OpenPGP Card
[![CI](https://github.com/wiktor-k/age-plugin-openpgp-card/actions/workflows/rust.yml/badge.svg)](https://github.com/wiktor-k/age-plugin-openpgp-card/actions/workflows/rust.yml)
[![Crates.io](https://img.shields.io/crates/v/age-plugin-openpgp-card)](https://crates.io/crates/age-plugin-openpgp-card)
This age plugin lets you reuse your OpenPGP Card devices (such as [Yubikeys](https://www.yubico.com/products/yubikey-5-overview/) or [Nitrokeys](https://www.nitrokey.com/products/nitrokeys)) for [age decryption](https://age-encryption.org/).
Why? [OpenPGP Card](https://en.wikipedia.org/wiki/OpenPGP_card), contrary to its name, is just a generic cryptographic device standard.
Most importantly the specification and the real-world devices (e.g. [Yubikeys](https://docs.yubico.com/hardware/yubikey/yk-tech-manual/yk5-apps.html#elliptic-curve-cryptographic-ecc-algorithms) and [Nitrokeys](https://docs.nitrokey.com/nitrokey3/faq#which-algorithms-and-maximum-key-length-are-supported)) support [curve25519](https://en.wikipedia.org/wiki/Curve25519).
This application is a no-moving-parts solution which requires only [`pcsc-lite`](https://github.com/LudovicRousseau/PCSC) on Linux and reuses built-in smartcard services on Windows and macOS. No GnuPG needed, no other OpenPGP software is used or accessed.
If you don't need curve25519 and are using Yubikeys then the [`age-plugin-yubikey`](https://github.com/str4d/age-plugin-yubikey) provides a more polished experience.
This plugin assumes that you have already provisioned the card.
[`oct admin generate`](https://codeberg.org/openpgp-card/openpgp-card-tools/#generate-keys-on-the-card) may be used to provision the card with a new curve25519 key.
(This is actually how end-to-end tests are implemented. See `scripts/encrypt-and-decrypt.sh`).
## Installation
At this moment the installation from `crates.io` is the only supported method:
```sh
cargo install --locked age-plugin-openpgp-card
```
## Usage
Running the tool directly outputs the public keys and the identity stubs for all connected cards:
```sh
$ age-plugin-openpgp-card | tee identity.txt
# Card ident 0006:15422467
# age1dkfzfyk58yvkf07n32nygkyuqxtnq2am427sy79gjkh6krf96frsucn0me
AGE-PLUGIN-OPENPGP-CARD-1XQCRQD36XY6NGV3JXSMRWAN88PC
```
Note that the public key looks like a regular age ed25519 key.
The stub encodes the card identifier and is mostly irrelevant.
If the stub is lost it may be regenerated - if the key on the card is the same the decryption will succeed.
Any age-compatible tool can be used for encryption:
```sh
$ echo I like strawberries | age -r age1dkfzfyk58yvkf07n32nygkyuqxtnq2am427sy79gjkh6krf96frsucn0me -a > encrypted.age
```
And the identity stubs are required for decryption:
```sh
$ age -d -i identity.txt < encrypted.age
I like strawberries
```
The plugin will ask you for the PIN using built-in plugin protocol (e.g. [`rage`](https://github.com/str4d/rage) would show a pin-entry prompt).
## Tests
This repository contains end-to-end integration tests which run a [virtual Nitrokey card](https://github.com/Nitrokey/opcard-rs), provision it with a new key and then encrypt and decrypt data using `rage`.
## Thanks
The plugin is basically glue code for already existing, awesome libraries and tools:
- [`openpgp-card`](https://crates.io/crates/openpgp-card) which interacts with the smartcards,
- [`age-plugin`](https://crates.io/crates/age-plugin) which provides easy to use framework for writing age plugins,
And, last but not least, [`opcard`](https://github.com/Nitrokey/opcard-rs) which provides us with a virtual card to test that all of this really works!
Thank you very much for all contributors to these projects 🙇‍♂️
## License
This project is licensed under either of:
- [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0),
- [MIT license](https://opensource.org/licenses/MIT).
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.