opgpcard: Extract pubkey command into module
This commit is contained in:
parent
660ba2d3bb
commit
3ff4127fff
4 changed files with 107 additions and 97 deletions
|
@ -51,17 +51,7 @@ pub enum Command {
|
||||||
Ssh(commands::ssh::SshCommand),
|
Ssh(commands::ssh::SshCommand),
|
||||||
|
|
||||||
/// Export the key data on a card as an OpenPGP public key
|
/// Export the key data on a card as an OpenPGP public key
|
||||||
Pubkey {
|
Pubkey(commands::pubkey::PubkeyCommand),
|
||||||
#[clap(name = "card ident", short = 'c', long = "card")]
|
|
||||||
ident: Option<String>,
|
|
||||||
|
|
||||||
#[clap(name = "User PIN file", short = 'p', long = "user-pin")]
|
|
||||||
user_pin: Option<PathBuf>,
|
|
||||||
|
|
||||||
/// User ID to add to the exported certificate representation
|
|
||||||
#[clap(name = "User ID", short = 'u', long = "userid")]
|
|
||||||
user_id: Vec<String>,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Administer data on a card (including keys and metadata)
|
/// Administer data on a card (including keys and metadata)
|
||||||
Admin {
|
Admin {
|
||||||
|
|
|
@ -3,5 +3,6 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
pub mod info;
|
pub mod info;
|
||||||
|
pub mod pubkey;
|
||||||
pub mod ssh;
|
pub mod ssh;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
|
|
102
tools/src/bin/opgpcard/commands/pubkey.rs
Normal file
102
tools/src/bin/opgpcard/commands/pubkey.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name>
|
||||||
|
// SPDX-FileCopyrightText: 2022 Lars Wirzenius <liw@liw.fi>
|
||||||
|
// SPDX-FileCopyrightText: 2022 Nora Widdecke <mail@nora.pink>
|
||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use sequoia_openpgp::serialize::SerializeInto;
|
||||||
|
|
||||||
|
use openpgp_card_sequoia::card::Card;
|
||||||
|
use openpgp_card_sequoia::types::KeyType;
|
||||||
|
use openpgp_card_sequoia::util::public_key_material_and_fp_to_key;
|
||||||
|
|
||||||
|
use crate::output;
|
||||||
|
use crate::pick_card_for_reading;
|
||||||
|
use crate::util;
|
||||||
|
use crate::versioned_output::{OutputBuilder, OutputFormat, OutputVersion};
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
pub struct PubkeyCommand {
|
||||||
|
#[clap(name = "card ident", short = 'c', long = "card")]
|
||||||
|
ident: Option<String>,
|
||||||
|
|
||||||
|
#[clap(name = "User PIN file", short = 'p', long = "user-pin")]
|
||||||
|
user_pin: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// User ID to add to the exported certificate representation
|
||||||
|
#[clap(name = "User ID", short = 'u', long = "userid")]
|
||||||
|
user_ids: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_pubkey(
|
||||||
|
format: OutputFormat,
|
||||||
|
output_version: OutputVersion,
|
||||||
|
command: PubkeyCommand,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut output = output::PublicKey::default();
|
||||||
|
|
||||||
|
let backend = pick_card_for_reading(command.ident)?;
|
||||||
|
let mut card = Card::new(backend);
|
||||||
|
let mut open = card.transaction()?;
|
||||||
|
|
||||||
|
let ident = open.application_identifier()?.ident();
|
||||||
|
output.ident(ident);
|
||||||
|
|
||||||
|
let user_pin = util::get_pin(&mut open, command.user_pin, crate::ENTER_USER_PIN);
|
||||||
|
|
||||||
|
let pkm = open.public_key(KeyType::Signing)?;
|
||||||
|
let times = open.key_generation_times()?;
|
||||||
|
let fps = open.fingerprints()?;
|
||||||
|
|
||||||
|
let key_sig = public_key_material_and_fp_to_key(
|
||||||
|
&pkm,
|
||||||
|
KeyType::Signing,
|
||||||
|
times.signature().expect("Signature time is unset"),
|
||||||
|
fps.signature().expect("Signature fingerprint is unset"),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut key_dec = None;
|
||||||
|
if let Ok(pkm) = open.public_key(KeyType::Decryption) {
|
||||||
|
if let Some(ts) = times.decryption() {
|
||||||
|
key_dec = Some(public_key_material_and_fp_to_key(
|
||||||
|
&pkm,
|
||||||
|
KeyType::Decryption,
|
||||||
|
ts,
|
||||||
|
fps.decryption().expect("Decryption fingerprint is unset"),
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut key_aut = None;
|
||||||
|
if let Ok(pkm) = open.public_key(KeyType::Authentication) {
|
||||||
|
if let Some(ts) = times.authentication() {
|
||||||
|
key_aut = Some(public_key_material_and_fp_to_key(
|
||||||
|
&pkm,
|
||||||
|
KeyType::Authentication,
|
||||||
|
ts,
|
||||||
|
fps.authentication()
|
||||||
|
.expect("Authentication fingerprint is unset"),
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cert = crate::get_cert(
|
||||||
|
&mut open,
|
||||||
|
key_sig,
|
||||||
|
key_dec,
|
||||||
|
key_aut,
|
||||||
|
user_pin.as_deref(),
|
||||||
|
&command.user_ids,
|
||||||
|
&|| println!("Enter User PIN on card reader pinpad."),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let armored = String::from_utf8(cert.armored().to_vec()?)?;
|
||||||
|
output.public_key(armored);
|
||||||
|
|
||||||
|
println!("{}", output.print(format, output_version)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -19,9 +19,7 @@ use sequoia_openpgp::Cert;
|
||||||
|
|
||||||
use openpgp_card_sequoia::card::{Admin, Card, Open};
|
use openpgp_card_sequoia::card::{Admin, Card, Open};
|
||||||
use openpgp_card_sequoia::types::{AlgoSimple, CardBackend, KeyType, TouchPolicy};
|
use openpgp_card_sequoia::types::{AlgoSimple, CardBackend, KeyType, TouchPolicy};
|
||||||
use openpgp_card_sequoia::util::{
|
use openpgp_card_sequoia::util::{make_cert, public_key_material_to_key};
|
||||||
make_cert, public_key_material_and_fp_to_key, public_key_material_to_key,
|
|
||||||
};
|
|
||||||
use openpgp_card_sequoia::{sq_util, PublicKey};
|
use openpgp_card_sequoia::{sq_util, PublicKey};
|
||||||
|
|
||||||
use crate::util::{load_pin, print_gnuk_note};
|
use crate::util::{load_pin, print_gnuk_note};
|
||||||
|
@ -60,18 +58,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
cli::Command::Ssh(cmd) => {
|
cli::Command::Ssh(cmd) => {
|
||||||
commands::ssh::print_ssh(cli.output_format, cli.output_version, cmd)?;
|
commands::ssh::print_ssh(cli.output_format, cli.output_version, cmd)?;
|
||||||
}
|
}
|
||||||
cli::Command::Pubkey {
|
cli::Command::Pubkey(cmd) => {
|
||||||
ident,
|
commands::pubkey::print_pubkey(cli.output_format, cli.output_version, cmd)?;
|
||||||
user_pin,
|
|
||||||
user_id,
|
|
||||||
} => {
|
|
||||||
print_pubkey(
|
|
||||||
cli.output_format,
|
|
||||||
cli.output_version,
|
|
||||||
ident,
|
|
||||||
user_pin,
|
|
||||||
user_id,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
cli::Command::SetIdentity { ident, id } => {
|
cli::Command::SetIdentity { ident, id } => {
|
||||||
set_identity(&ident, id)?;
|
set_identity(&ident, id)?;
|
||||||
|
@ -607,77 +595,6 @@ fn pick_card_for_reading(ident: Option<String>) -> Result<Box<dyn CardBackend +
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_pubkey(
|
|
||||||
format: OutputFormat,
|
|
||||||
output_version: OutputVersion,
|
|
||||||
ident: Option<String>,
|
|
||||||
user_pin: Option<PathBuf>,
|
|
||||||
user_ids: Vec<String>,
|
|
||||||
) -> Result<()> {
|
|
||||||
let mut output = output::PublicKey::default();
|
|
||||||
|
|
||||||
let backend = pick_card_for_reading(ident)?;
|
|
||||||
let mut card = Card::new(backend);
|
|
||||||
let mut open = card.transaction()?;
|
|
||||||
|
|
||||||
let ident = open.application_identifier()?.ident();
|
|
||||||
output.ident(ident);
|
|
||||||
|
|
||||||
let user_pin = util::get_pin(&mut open, user_pin, ENTER_USER_PIN);
|
|
||||||
|
|
||||||
let pkm = open.public_key(KeyType::Signing)?;
|
|
||||||
let times = open.key_generation_times()?;
|
|
||||||
let fps = open.fingerprints()?;
|
|
||||||
|
|
||||||
let key_sig = public_key_material_and_fp_to_key(
|
|
||||||
&pkm,
|
|
||||||
KeyType::Signing,
|
|
||||||
times.signature().expect("Signature time is unset"),
|
|
||||||
fps.signature().expect("Signature fingerprint is unset"),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut key_dec = None;
|
|
||||||
if let Ok(pkm) = open.public_key(KeyType::Decryption) {
|
|
||||||
if let Some(ts) = times.decryption() {
|
|
||||||
key_dec = Some(public_key_material_and_fp_to_key(
|
|
||||||
&pkm,
|
|
||||||
KeyType::Decryption,
|
|
||||||
ts,
|
|
||||||
fps.decryption().expect("Decryption fingerprint is unset"),
|
|
||||||
)?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut key_aut = None;
|
|
||||||
if let Ok(pkm) = open.public_key(KeyType::Authentication) {
|
|
||||||
if let Some(ts) = times.authentication() {
|
|
||||||
key_aut = Some(public_key_material_and_fp_to_key(
|
|
||||||
&pkm,
|
|
||||||
KeyType::Authentication,
|
|
||||||
ts,
|
|
||||||
fps.authentication()
|
|
||||||
.expect("Authentication fingerprint is unset"),
|
|
||||||
)?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let cert = get_cert(
|
|
||||||
&mut open,
|
|
||||||
key_sig,
|
|
||||||
key_dec,
|
|
||||||
key_aut,
|
|
||||||
user_pin.as_deref(),
|
|
||||||
&user_ids,
|
|
||||||
&|| println!("Enter User PIN on card reader pinpad."),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let armored = String::from_utf8(cert.armored().to_vec()?)?;
|
|
||||||
output.public_key(armored);
|
|
||||||
|
|
||||||
println!("{}", output.print(format, output_version)?);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrypt(
|
fn decrypt(
|
||||||
ident: &str,
|
ident: &str,
|
||||||
pin_file: Option<PathBuf>,
|
pin_file: Option<PathBuf>,
|
||||||
|
|
Loading…
Reference in a new issue