4 Commits

Author SHA1 Message Date
Jack Grigg 23a1f61e5a v0.4.1
CI checks / Test on linux (push) Has been cancelled
CI checks / Test on macos (push) Has been cancelled
CI checks / Test on windows (push) Has been cancelled
CI checks / Code coverage (push) Has been cancelled
CI checks / Intra-doc links (push) Has been cancelled
CI checks / Rustfmt (push) Has been cancelled
Publish release binaries / Publish for macos-arm64 (push) Has been cancelled
Publish release binaries / Publish for macos-x86_64 (push) Has been cancelled
Publish release binaries / Publish for linux (push) Has been cancelled
Publish release binaries / Publish for windows (push) Has been cancelled
Publish release binaries / Debian linux (push) Has been cancelled
2026-04-08 04:20:54 +01:00
Jack Grigg eb945b2849 Merge tag 'v0.4.0' into detect-critical-extensions 2026-04-08 04:16:00 +01:00
Jack Grigg bf081835c4 Release 0.3.4
CI checks / Test on linux (push) Has been cancelled
CI checks / Test on macos (push) Has been cancelled
CI checks / Test on windows (push) Has been cancelled
CI checks / Clippy (1.56.0) (push) Has been cancelled
CI checks / Clippy (nightly) (push) Has been cancelled
CI checks / Code coverage (push) Has been cancelled
CI checks / Intra-doc links (push) Has been cancelled
CI checks / Rustfmt (push) Has been cancelled
Publish release binaries / Publish for macos-arm64 (push) Has been cancelled
Publish release binaries / Publish for macos-x86_64 (push) Has been cancelled
Publish release binaries / Publish for linux (push) Has been cancelled
Publish release binaries / Publish for windows (push) Has been cancelled
Publish release binaries / Debian linux (push) Has been cancelled
2026-04-08 04:14:54 +01:00
Jack Grigg 9503f406ae Reject identities with unrecognised critical extensions
We don't know how to correctly use these identities. In particular, some
identities store parts of their private key material in certificate
extensions to work around hardware limitations. Not understanding these
extensions could lead to encrypting with the wrong protocol and
violating security assumptions.
2026-04-08 04:12:35 +01:00
15 changed files with 773 additions and 904 deletions
+17 -65
View File
@@ -1,13 +1,10 @@
name: CI checks name: CI checks
on: on: [push, pull_request]
pull_request:
push:
branches: main
jobs: jobs:
test-msrv: test:
name: Test MSRV on ${{ matrix.name }} name: Test on ${{ matrix.name }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
@@ -25,83 +22,37 @@ jobs:
os: macos-latest os: macos-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install build dependencies - name: Install build dependencies
run: sudo apt install ${{ matrix.build_deps }} run: sudo apt install ${{ matrix.build_deps }}
if: matrix.build_deps != '' if: matrix.build_deps != ''
- uses: dtolnay/rust-toolchain@stable
id: stable-toolchain
- name: Install test dependencies using latest stable Rust
run: cargo +${{steps.stable-toolchain.outputs.name}} install rage
- name: Run tests
run: cargo test
- name: Verify working directory is clean
run: git diff --exit-code
test-latest:
name: Test latest stable on ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
name: [linux, windows, macos]
include:
- name: linux
os: ubuntu-latest
build_deps: >
libpcsclite-dev
- name: windows
os: windows-latest
- name: macos
os: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install build dependencies
run: sudo apt install ${{ matrix.build_deps }}
if: matrix.build_deps != ''
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/rust-toolchain@stable
id: toolchain
- run: rustup override set ${{steps.toolchain.outputs.name}}
- name: Install test dependencies - name: Install test dependencies
run: cargo install rage run: cargo install rage
- name: Remove lockfile to build with latest dependencies - run: cargo fetch
run: rm Cargo.lock - name: Build tests
run: cargo build --verbose --tests
- name: Run tests - name: Run tests
run: cargo test run: cargo test --verbose
- name: Verify working directory is clean (excluding lockfile)
run: git diff --exit-code ':!Cargo.lock'
codecov: codecov:
name: Code coverage name: Code coverage
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: xd009642/tarpaulin:develop-nightly
options: --security-opt seccomp=unconfined
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install build dependencies - name: Install build dependencies
run: apt update && apt install -y libpcsclite-dev run: sudo apt install libpcsclite-dev
- name: Install coverage dependencies
run: cargo install cargo-tarpaulin
- name: Generate coverage report - name: Generate coverage report
run: > run: cargo tarpaulin --engine llvm --all-features --release --timeout 600 --out Xml
cargo tarpaulin
--engine llvm
--timeout 180
--out xml
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
uses: codecov/codecov-action@v4.5.0 uses: codecov/codecov-action@v3.1.1
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
doc-links: doc-links:
name: Intra-doc links name: Intra-doc links
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install build dependencies - name: Install build dependencies
run: sudo apt install libpcsclite-dev run: sudo apt install libpcsclite-dev
- run: cargo fetch - run: cargo fetch
@@ -111,8 +62,9 @@ jobs:
fmt: fmt:
name: Rustfmt name: Rustfmt
timeout-minutes: 30
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Check formatting - name: Check formatting
run: cargo fmt -- --check run: cargo fmt -- --check
+2 -1
View File
@@ -6,9 +6,10 @@ on: pull_request
jobs: jobs:
clippy-beta: clippy-beta:
name: Clippy (beta) name: Clippy (beta)
timeout-minutes: 30
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@beta - uses: dtolnay/rust-toolchain@beta
id: toolchain id: toolchain
- run: rustup override set ${{steps.toolchain.outputs.name}} - run: rustup override set ${{steps.toolchain.outputs.name}}
+2 -1
View File
@@ -6,9 +6,10 @@ on: pull_request
jobs: jobs:
clippy: clippy:
name: Clippy (MSRV) name: Clippy (MSRV)
timeout-minutes: 30
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install build dependencies - name: Install build dependencies
run: sudo apt install libpcsclite-dev run: sudo apt install libpcsclite-dev
- name: Run clippy - name: Run clippy
+14 -12
View File
@@ -24,7 +24,7 @@ jobs:
- windows - windows
include: include:
- name: linux - name: linux
os: ubuntu-20.04 os: ubuntu-18.04
build_deps: > build_deps: >
libpcsclite-dev libpcsclite-dev
archive_name: age-plugin-yubikey.tar.gz archive_name: age-plugin-yubikey.tar.gz
@@ -48,10 +48,11 @@ jobs:
asset_suffix: x86_64-darwin.tar.gz asset_suffix: x86_64-darwin.tar.gz
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable - uses: actions-rs/toolchain@v1
id: toolchain with:
- run: rustup override set ${{steps.toolchain.outputs.name}} toolchain: stable
override: true
- name: Add target - name: Add target
run: rustup target add ${{ matrix.target }} run: rustup target add ${{ matrix.target }}
if: matrix.target != '' if: matrix.target != ''
@@ -86,7 +87,7 @@ jobs:
if: matrix.name == 'windows' if: matrix.name == 'windows'
- name: Upload archive to release - name: Upload archive to release
uses: svenstaro/upload-release-action@2.6.1 uses: svenstaro/upload-release-action@2.5.0
with: with:
file: ${{ matrix.archive_name }} file: ${{ matrix.archive_name }}
asset_name: age-plugin-yubikey-$tag-${{ matrix.asset_suffix }} asset_name: age-plugin-yubikey-$tag-${{ matrix.asset_suffix }}
@@ -95,7 +96,7 @@ jobs:
deb: deb:
name: Debian ${{ matrix.name }} name: Debian ${{ matrix.name }}
runs-on: ubuntu-20.04 runs-on: ubuntu-18.04
strategy: strategy:
matrix: matrix:
name: [linux] name: [linux]
@@ -106,10 +107,11 @@ jobs:
libpcsclite-dev libpcsclite-dev
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable - uses: actions-rs/toolchain@v1
id: toolchain with:
- run: rustup override set ${{steps.toolchain.outputs.name}} toolchain: stable
override: true
- name: Add target - name: Add target
run: rustup target add ${{ matrix.target }} run: rustup target add ${{ matrix.target }}
- name: cargo install cargo-deb - name: cargo install cargo-deb
@@ -144,7 +146,7 @@ jobs:
args: --package age-plugin-yubikey --no-build --target ${{ matrix.target }} args: --package age-plugin-yubikey --no-build --target ${{ matrix.target }}
- name: Upload Debian package to release - name: Upload Debian package to release
uses: svenstaro/upload-release-action@2.6.1 uses: svenstaro/upload-release-action@2.5.0
with: with:
file: target/${{ matrix.target }}/debian/*.deb file: target/${{ matrix.target }}/debian/*.deb
file_glob: true file_glob: true
+4 -5
View File
@@ -8,12 +8,11 @@ to 0.3.0 are beta releases.
## [Unreleased] ## [Unreleased]
## [0.5.0] - 2024-08-04 ## [0.3.4], [0.4.1] - 2026-04-08
### Fixed ### Fixed
- `age-plugin-yubikey` can now be compiled with Rust 1.80 and above. - `age-plugin-yubikey` now completely ignores any identity that has unrecognised
critical extensions in its certificate, to ensure it doesn't misuse a newer
### Changed identity type.
- MSRV is now 1.67.0.
## [0.4.0] - 2023-04-09 ## [0.4.0] - 2023-04-09
### Changed ### Changed
Generated
+667 -769
View File
File diff suppressed because it is too large Load Diff
+12 -12
View File
@@ -1,7 +1,7 @@
[package] [package]
name = "age-plugin-yubikey" name = "age-plugin-yubikey"
description = "YubiKey plugin for age clients" description = "YubiKey plugin for age clients"
version = "0.5.0" version = "0.4.1"
authors = ["Jack Grigg <thestr4d@gmail.com>"] authors = ["Jack Grigg <thestr4d@gmail.com>"]
repository = "https://github.com/str4d/age-plugin-yubikey" repository = "https://github.com/str4d/age-plugin-yubikey"
readme = "README.md" readme = "README.md"
@@ -9,7 +9,7 @@ keywords = ["age", "cli", "encryption", "yubikey"]
categories = ["command-line-utilities", "cryptography"] categories = ["command-line-utilities", "cryptography"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
edition = "2021" edition = "2021"
rust-version = "1.67" # MSRV rust-version = "1.65" # MSRV
[package.metadata.deb] [package.metadata.deb]
extended-description = """\ extended-description = """\
@@ -22,12 +22,12 @@ assets = [
] ]
[dependencies] [dependencies]
age-core = "0.10" age-core = "0.9"
age-plugin = "0.5" age-plugin = "0.4"
base64 = "0.21" base64 = "0.21"
bech32 = "0.9" bech32 = "0.9"
console = { version = "0.15", default-features = false } console = { version = "0.15", default-features = false }
dialoguer = { version = "0.11", default-features = false, features = ["password"] } dialoguer = { version = "0.10", default-features = false, features = ["password"] }
env_logger = "0.10" env_logger = "0.10"
gumdrop = "0.8" gumdrop = "0.8"
hex = "0.4" hex = "0.4"
@@ -36,23 +36,23 @@ p256 = { version = "0.13", features = ["ecdh"] }
pcsc = "2.4" pcsc = "2.4"
rand = "0.8" rand = "0.8"
sha2 = "0.10" sha2 = "0.10"
which = "5" which = "4.1"
x509 = "0.2" x509 = "0.2"
x509-parser = "0.14" x509-parser = "0.14"
yubikey = { version = "=0.8.0-pre.0", features = ["untested"] } yubikey = { version = "=0.8.0-pre.0", features = ["untested"] }
# Translations # Translations
i18n-embed = { version = "0.14", features = ["desktop-requester", "fluent-system"] } i18n-embed = { version = "0.13", features = ["desktop-requester", "fluent-system"] }
i18n-embed-fl = "0.8" i18n-embed-fl = "0.6"
lazy_static = "1" lazy_static = "1"
rust-embed = "8" rust-embed = "6"
# GnuPG coexistence # GnuPG coexistence
sysinfo = "0.29" sysinfo = "0.28"
[dev-dependencies] [dev-dependencies]
flate2 = "1" flate2 = "1"
man = "0.3" man = "0.3"
tempfile = "3" tempfile = "3"
test-with = "0.11" test-with = "0.9"
which = "5" which = "4"
+1 -9
View File
@@ -8,13 +8,8 @@ which enables files to be encrypted to age identities stored on YubiKeys.
| Environment | CLI command | | Environment | CLI command |
|-------------|-------------| |-------------|-------------|
| Cargo (Rust 1.67+) | `cargo install age-plugin-yubikey` | | Cargo (Rust 1.65+) | `cargo install age-plugin-yubikey` |
| Homebrew (macOS or Linux) | `brew install age-plugin-yubikey` | | Homebrew (macOS or Linux) | `brew install age-plugin-yubikey` |
| Arch Linux | `pacman -S age-plugin-yubikey` |
| Debian | [Debian package](https://github.com/str4d/age-plugin-yubikey/releases) |
| NixOS | Add to config:<br>`environment.systemPackages = [`<br>` pkgs.age-plugin-yubikey`<br>`];`<br>Or run `nix-env -i age-plugin-yubikey` |
| Ubuntu 20.04+ | [Debian package](https://github.com/str4d/age-plugin-yubikey/releases) |
| OpenBSD | `pkg_add age-plugin-yubikey` (security/age-plugin-yubikey) |
On Windows, Linux, and macOS, you can use the On Windows, Linux, and macOS, you can use the
[pre-built binaries](https://github.com/str4d/age-plugin-yubikey/releases). [pre-built binaries](https://github.com/str4d/age-plugin-yubikey/releases).
@@ -29,10 +24,8 @@ is installed and running.
| Environment | CLI command | | Environment | CLI command |
|-------------|-------------| |-------------|-------------|
| Debian or Ubuntu | `sudo apt-get install pcscd` | | Debian or Ubuntu | `sudo apt-get install pcscd` |
| Fedora | `sudo dnf install pcsc-lite` |
| OpenBSD | As ```root``` do:<br>`pkg_add pcsc-lite ccid`<br>`rcctl enable pcscd`<br>`rcctl start pcscd` | | OpenBSD | As ```root``` do:<br>`pkg_add pcsc-lite ccid`<br>`rcctl enable pcscd`<br>`rcctl start pcscd` |
| FreeBSD | As ```root``` do:<br>`pkg install pcsc-lite libccid`<br>`service pcscd enable`<br>`service pcscd start` | | FreeBSD | As ```root``` do:<br>`pkg install pcsc-lite libccid`<br>`service pcscd enable`<br>`service pcscd start` |
| Arch | `sudo pacman -S pcsclite pcsc-tools yubikey-manager`<br>`sudo systemctl enable pcscd`<br>`sudo systemctl start pcscd`|
When installing via Cargo, you also need to ensure that the development headers When installing via Cargo, you also need to ensure that the development headers
for the `pcsc-lite` library are available, so that the `pcsc-sys` crate can be for the `pcsc-lite` library are available, so that the `pcsc-sys` crate can be
@@ -41,7 +34,6 @@ compiled.
| Environment | CLI command | | Environment | CLI command |
|-------------|-------------| |-------------|-------------|
| Debian or Ubuntu | `sudo apt-get install libpcsclite-dev` | | Debian or Ubuntu | `sudo apt-get install libpcsclite-dev` |
| Fedora | `sudo dnf install pcsc-lite-devel` |
### Windows Subsystem for Linux (WSL) ### Windows Subsystem for Linux (WSL)
+1 -1
View File
@@ -6,7 +6,7 @@ use std::io::prelude::*;
const MANPAGES_DIR: &str = "./target/manpages"; const MANPAGES_DIR: &str = "./target/manpages";
fn generate_manpage(page: String, name: &str) { fn generate_manpage(page: String, name: &str) {
let file = File::create(format!("{MANPAGES_DIR}/{name}.1.gz")) let file = File::create(format!("{}/{}.1.gz", MANPAGES_DIR, name))
.expect("Should be able to open file in target directory"); .expect("Should be able to open file in target directory");
let mut encoder = GzEncoder::new(file, Compression::best()); let mut encoder = GzEncoder::new(file, Compression::best());
encoder encoder
-1
View File
@@ -204,7 +204,6 @@ err-invalid-flag-tui = Flag '{$flag}' cannot be used with the interactive in
err-invalid-pin-policy = Invalid PIN policy '{$policy}' (expected [{$expected}]). err-invalid-pin-policy = Invalid PIN policy '{$policy}' (expected [{$expected}]).
err-invalid-slot = Invalid slot '{$slot}' (expected number between 1 and 20). err-invalid-slot = Invalid slot '{$slot}' (expected number between 1 and 20).
err-invalid-touch-policy = Invalid touch policy '{$policy}' (expected [{$expected}]). err-invalid-touch-policy = Invalid touch policy '{$policy}' (expected [{$expected}]).
err-io-user = Failed to get input from user: {$err}
err-io = Failed to set up {-yubikey}: {$err} err-io = Failed to set up {-yubikey}: {$err}
err-multiple-commands = Only one of {-cmd-generate}, {-cmd-identity}, {-cmd-list}, {-cmd-list-all} can be specified. err-multiple-commands = Only one of {-cmd-generate}, {-cmd-identity}, {-cmd-list}, {-cmd-list-all} can be specified.
err-multiple-yubikeys = Multiple {-yubikeys} are plugged in. Use {-flag-serial} to select a single {-yubikey}. err-multiple-yubikeys = Multiple {-yubikeys} are plugged in. Use {-flag-serial} to select a single {-yubikey}.
+1 -1
View File
@@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "1.67.0" channel = "1.65.0"
components = ["clippy", "rustfmt"] components = ["clippy", "rustfmt"]
-8
View File
@@ -15,7 +15,6 @@ macro_rules! wlnfl {
pub enum Error { pub enum Error {
CustomManagementKey, CustomManagementKey,
Dialog(dialoguer::Error),
InvalidFlagCommand(String, String), InvalidFlagCommand(String, String),
InvalidFlagTui(String), InvalidFlagTui(String),
InvalidPinPolicy(String), InvalidPinPolicy(String),
@@ -36,12 +35,6 @@ pub enum Error {
YubiKey(yubikey::Error), YubiKey(yubikey::Error),
} }
impl From<dialoguer::Error> for Error {
fn from(e: dialoguer::Error) -> Self {
Error::Dialog(e)
}
}
impl From<io::Error> for Error { impl From<io::Error> for Error {
fn from(e: io::Error) -> Self { fn from(e: io::Error) -> Self {
Error::Io(e) Error::Io(e)
@@ -72,7 +65,6 @@ impl fmt::Debug for Error {
url = CHANGE_MGMT_KEY_URL url = CHANGE_MGMT_KEY_URL
)?; )?;
} }
Error::Dialog(e) => wlnfl!(f, "err-io-user", err = e.to_string())?,
Error::InvalidFlagCommand(flag, command) => wlnfl!( Error::InvalidFlagCommand(flag, command) => wlnfl!(
f, f,
"err-invalid-flag-command", "err-invalid-flag-command",
+37 -10
View File
@@ -15,6 +15,7 @@ use std::io;
use std::iter; use std::iter;
use std::thread::sleep; use std::thread::sleep;
use std::time::{Duration, Instant, SystemTime}; use std::time::{Duration, Instant, SystemTime};
use x509_parser::der_parser::oid::Oid;
use yubikey::{ use yubikey::{
certificate::Certificate, certificate::Certificate,
piv::{decrypt_data, AlgorithmId, RetiredSlotId, SlotId}, piv::{decrypt_data, AlgorithmId, RetiredSlotId, SlotId},
@@ -27,13 +28,16 @@ use crate::{
fl, fl,
format::{RecipientLine, STANZA_KEY_LABEL}, format::{RecipientLine, STANZA_KEY_LABEL},
p256::{Recipient, TAG_BYTES}, p256::{Recipient, TAG_BYTES},
util::{otp_serial_prefix, Metadata}, util::{otp_serial_prefix, Metadata, POLICY_EXTENSION_OID},
IDENTITY_PREFIX, IDENTITY_PREFIX,
}; };
const ONE_SECOND: Duration = Duration::from_secs(1); const ONE_SECOND: Duration = Duration::from_secs(1);
const FIFTEEN_SECONDS: Duration = Duration::from_secs(15); const FIFTEEN_SECONDS: Duration = Duration::from_secs(15);
/// The set of OIDs that we understand and use when parsing YubiKey slot certificates.
const KNOWN_OIDS: &[&[u64]] = &[POLICY_EXTENSION_OID];
pub(crate) fn is_connected(reader: Reader) -> bool { pub(crate) fn is_connected(reader: Reader) -> bool {
filter_connected(&reader) filter_connected(&reader)
} }
@@ -274,10 +278,10 @@ pub(crate) fn disconnect_without_reset(yubikey: YubiKey) {
let _ = yubikey.disconnect(pcsc::Disposition::LeaveCard); let _ = yubikey.disconnect(pcsc::Disposition::LeaveCard);
} }
fn request_pin<E, E2>( fn request_pin<E>(
mut prompt: impl FnMut(Option<String>) -> Result<Result<SecretString, E>, E2>, mut prompt: impl FnMut(Option<String>) -> io::Result<Result<SecretString, E>>,
serial: Serial, serial: Serial,
) -> Result<Result<SecretString, E>, E2> { ) -> io::Result<Result<SecretString, E>> {
let mut prev_error = None; let mut prev_error = None;
loop { loop {
prev_error = Some(match prompt(prev_error)? { prev_error = Some(match prompt(prev_error)? {
@@ -326,7 +330,7 @@ pub(crate) fn manage(yubikey: &mut YubiKey) -> Result<(), Error> {
let pin = request_pin( let pin = request_pin(
|prev_error| { |prev_error| {
if let Some(err) = prev_error { if let Some(err) = prev_error {
eprintln!("{err}"); eprintln!("{}", err);
} }
Password::new() Password::new()
.with_prompt(fl!("mgr-choose-new-pin")) .with_prompt(fl!("mgr-choose-new-pin"))
@@ -388,6 +392,30 @@ pub(crate) fn manage(yubikey: &mut YubiKey) -> Result<(), Error> {
Ok(()) Ok(())
} }
/// Parses the certificate to identify the preferred recipient type it corresponds to.
pub(crate) fn identify_recipient(cert: &Certificate) -> Option<Recipient> {
let known_oids = KNOWN_OIDS
.iter()
.map(|oid| Oid::from(oid).unwrap())
.collect::<Vec<_>>();
// If the certificate contains any unrecognised critical extensions, reject it: we
// don't know how to correctly use the identity. In particular, some identities store
// parts of their private key material in certificate extensions to work around
// hardware limitations. Not understanding these extensions could lead to encrypting
// with the wrong protocol and violating security assumptions.
let (_, c) = x509_parser::parse_x509_certificate(cert.as_ref()).ok()?;
if c.tbs_certificate
.extensions()
.iter()
.any(|ext| ext.critical && !known_oids.contains(&ext.oid))
{
return None;
}
Recipient::from_certificate(cert)
}
/// Returns an iterator of keys that are occupying plugin-compatible slots, along with the /// Returns an iterator of keys that are occupying plugin-compatible slots, along with the
/// corresponding recipient if the key is compatible with this plugin. /// corresponding recipient if the key is compatible with this plugin.
pub(crate) fn list_slots( pub(crate) fn list_slots(
@@ -397,8 +425,7 @@ pub(crate) fn list_slots(
// We only use the retired slots. // We only use the retired slots.
match key.slot() { match key.slot() {
SlotId::Retired(slot) => { SlotId::Retired(slot) => {
// Only P-256 keys are compatible with us. let recipient = identify_recipient(key.certificate());
let recipient = Recipient::from_certificate(key.certificate());
Some((key, slot, recipient)) Some((key, slot, recipient))
} }
_ => None, _ => None,
@@ -605,9 +632,9 @@ impl Stub {
let (cert, pk) = match Certificate::read(&mut yubikey, SlotId::Retired(self.slot)) let (cert, pk) = match Certificate::read(&mut yubikey, SlotId::Retired(self.slot))
.ok() .ok()
.and_then(|cert| { .and_then(|cert| {
Recipient::from_certificate(&cert) identify_recipient(&cert)
.filter(|pk| pk.tag() == self.tag) .filter(|recipient| recipient.tag() == self.tag)
.map(|pk| (cert, pk)) .map(|r| (cert, r))
}) { }) {
Some(pk) => pk, Some(pk) => pk,
None => { None => {
+14 -8
View File
@@ -296,8 +296,8 @@ fn list(flags: PluginFlags, all: bool) -> Result<(), Error> {
flags, flags,
all, all,
|_, recipient, metadata| { |_, recipient, metadata| {
println!("{metadata}"); println!("{}", metadata);
println!("{recipient}"); println!("{}", recipient);
}, },
) )
} }
@@ -329,8 +329,8 @@ fn main() -> Result<(), Error> {
if let Some(state_machine) = opts.age_plugin { if let Some(state_machine) = opts.age_plugin {
run_state_machine( run_state_machine(
&state_machine, &state_machine,
Some(plugin::RecipientPlugin::default), plugin::RecipientPlugin::default,
Some(plugin::IdentityPlugin::default), plugin::IdentityPlugin::default,
)?; )?;
Ok(()) Ok(())
} else if opts.version { } else if opts.version {
@@ -411,9 +411,9 @@ fn main() -> Result<(), Error> {
.validity() .validity()
.not_before .not_before
.to_rfc2822() .to_rfc2822()
.unwrap_or_else(|e| format!("Invalid date: {e}")); .unwrap_or_else(|e| format!("Invalid date: {}", e));
format!("{name}, created: {created}") format!("{}, created: {}", name, created)
}) })
}) })
}) })
@@ -631,8 +631,14 @@ fn main() -> Result<(), Error> {
// If `rage` binary is installed, use it in examples. Otherwise default to `age`. // If `rage` binary is installed, use it in examples. Otherwise default to `age`.
let age_binary = which::which("rage").map(|_| "rage").unwrap_or("age"); let age_binary = which::which("rage").map(|_| "rage").unwrap_or("age");
let encrypt_usage = format!("$ cat foo.txt | {age_binary} -r {recipient} -o foo.txt.age"); let encrypt_usage = format!(
let decrypt_usage = format!("$ cat foo.txt.age | {age_binary} -d -i {file_name} > foo.txt"); "$ cat foo.txt | {} -r {} -o foo.txt.age",
age_binary, recipient
);
let decrypt_usage = format!(
"$ cat foo.txt.age | {} -d -i {} > foo.txt",
age_binary, file_name
);
let identity_usage = format!( let identity_usage = format!(
"$ age-plugin-yubikey -i --serial {} --slot {} > {}", "$ age-plugin-yubikey -i --serial {} --slot {} > {}",
stub.serial, stub.serial,
+1 -1
View File
@@ -177,7 +177,7 @@ impl Metadata {
.validity() .validity()
.not_before .not_before
.to_rfc2822() .to_rfc2822()
.unwrap_or_else(|e| format!("Invalid date: {e}")), .unwrap_or_else(|e| format!("Invalid date: {}", e)),
pin_policy, pin_policy,
touch_policy, touch_policy,
}) })