opgpcard: Extract decrypt command into module

This commit is contained in:
Nora Widdecke 2022-10-26 12:01:39 +02:00
parent 3ff4127fff
commit 9e5e30cea4
No known key found for this signature in database
GPG key ID: 2D4111B31DBB99B6
4 changed files with 61 additions and 48 deletions

View file

@ -75,17 +75,7 @@ pub enum Command {
}, },
/// Decrypt data using a card /// Decrypt data using a card
Decrypt { Decrypt(commands::decrypt::DecryptCommand),
#[clap(name = "card ident", short = 'c', long = "card")]
ident: String,
#[clap(name = "User PIN file", short = 'p', long = "user-pin")]
user_pin: Option<PathBuf>,
/// Input file (stdin if unset)
#[clap(name = "input")]
input: Option<PathBuf>,
},
/// Sign data using a card /// Sign data using a card
Sign { Sign {

View file

@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name>
// SPDX-FileCopyrightText: 2022 Nora Widdecke <mail@nora.pink>
// SPDX-License-Identifier: MIT OR Apache-2.0
use anyhow::{anyhow, Result};
use clap::Parser;
use std::path::PathBuf;
use sequoia_openpgp::{
parse::{stream::DecryptorBuilder, Parse},
policy::StandardPolicy,
};
use openpgp_card_sequoia::card::Card;
use crate::util;
#[derive(Parser, Debug)]
pub struct DecryptCommand {
#[clap(name = "card ident", short = 'c', long = "card")]
ident: String,
#[clap(name = "User PIN file", short = 'p', long = "user-pin")]
pin_file: Option<PathBuf>,
/// Input file (stdin if unset)
#[clap(name = "input")]
input: Option<PathBuf>,
}
pub fn decrypt(command: DecryptCommand) -> Result<(), Box<dyn std::error::Error>> {
let p = StandardPolicy::new();
let input = util::open_or_stdin(command.input.as_deref())?;
let backend = util::open_card(&command.ident)?;
let mut card = Card::new(backend);
let mut open = card.transaction()?;
if open.fingerprints()?.decryption().is_none() {
return Err(anyhow!("Can't decrypt: this card has no key in the decryption slot.").into());
}
let user_pin = util::get_pin(&mut open, command.pin_file, crate::ENTER_USER_PIN);
let mut user = util::verify_to_user(&mut open, user_pin.as_deref())?;
let d = user.decryptor(&|| println!("Touch confirmation needed for decryption"))?;
let db = DecryptorBuilder::from_reader(input)?;
let mut decryptor = db.with_policy(&p, None, d)?;
std::io::copy(&mut decryptor, &mut std::io::stdout())?;
Ok(())
}

View file

@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: 2022 Nora Widdecke <mail@nora.pink> // SPDX-FileCopyrightText: 2022 Nora Widdecke <mail@nora.pink>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
pub mod decrypt;
pub mod info; pub mod info;
pub mod pubkey; pub mod pubkey;
pub mod ssh; pub mod ssh;

View file

@ -10,7 +10,7 @@ use std::path::{Path, PathBuf};
use sequoia_openpgp::cert::prelude::ValidErasedKeyAmalgamation; use sequoia_openpgp::cert::prelude::ValidErasedKeyAmalgamation;
use sequoia_openpgp::packet::key::{SecretParts, UnspecifiedRole}; use sequoia_openpgp::packet::key::{SecretParts, UnspecifiedRole};
use sequoia_openpgp::packet::Key; use sequoia_openpgp::packet::Key;
use sequoia_openpgp::parse::{stream::DecryptorBuilder, Parse}; use sequoia_openpgp::parse::Parse;
use sequoia_openpgp::policy::{Policy, StandardPolicy}; use sequoia_openpgp::policy::{Policy, StandardPolicy};
use sequoia_openpgp::serialize::stream::{Armorer, Message, Signer}; use sequoia_openpgp::serialize::stream::{Armorer, Message, Signer};
use sequoia_openpgp::serialize::SerializeInto; use sequoia_openpgp::serialize::SerializeInto;
@ -64,12 +64,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
cli::Command::SetIdentity { ident, id } => { cli::Command::SetIdentity { ident, id } => {
set_identity(&ident, id)?; set_identity(&ident, id)?;
} }
cli::Command::Decrypt { cli::Command::Decrypt(cmd) => {
ident, commands::decrypt::decrypt(cmd)?;
user_pin,
input,
} => {
decrypt(&ident, user_pin, input.as_deref())?;
} }
cli::Command::Sign { cli::Command::Sign {
ident, ident,
@ -595,36 +591,6 @@ fn pick_card_for_reading(ident: Option<String>) -> Result<Box<dyn CardBackend +
} }
} }
fn decrypt(
ident: &str,
pin_file: Option<PathBuf>,
input: Option<&Path>,
) -> Result<(), Box<dyn std::error::Error>> {
let p = StandardPolicy::new();
let input = util::open_or_stdin(input)?;
let backend = util::open_card(ident)?;
let mut card = Card::new(backend);
let mut open = card.transaction()?;
if open.fingerprints()?.decryption().is_none() {
return Err(anyhow!("Can't decrypt: this card has no key in the decryption slot.").into());
}
let user_pin = util::get_pin(&mut open, pin_file, ENTER_USER_PIN);
let mut user = util::verify_to_user(&mut open, user_pin.as_deref())?;
let d = user.decryptor(&|| println!("Touch confirmation needed for decryption"))?;
let db = DecryptorBuilder::from_reader(input)?;
let mut decryptor = db.with_policy(&p, None, d)?;
std::io::copy(&mut decryptor, &mut std::io::stdout())?;
Ok(())
}
fn sign_detached( fn sign_detached(
ident: &str, ident: &str,
pin_file: Option<PathBuf>, pin_file: Option<PathBuf>,