Don't use Cert
to build signer and decryptor.
Rename decryptor/signer/authenticator getters. Add alternatives that don't require PublicKey parameter.
This commit is contained in:
parent
f3ac66cef5
commit
6e630254fa
6 changed files with 63 additions and 125 deletions
|
@ -163,15 +163,13 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
.user_card()
|
||||
.expect("We just validated, this should not fail");
|
||||
|
||||
let cert = Cert::from_file(TEST_KEY_PATH)?;
|
||||
let _cert = Cert::from_file(TEST_KEY_PATH)?;
|
||||
let msg = std::fs::read_to_string(TEST_ENC_MSG).expect("Unable to read file");
|
||||
|
||||
println!("Encrypted message:\n{}", msg);
|
||||
|
||||
let sp = StandardPolicy::new();
|
||||
let d = user.decryptor(&cert, &|| {
|
||||
println!("Touch confirmation needed for decryption")
|
||||
})?;
|
||||
let d = user.decryptor(&|| println!("Touch confirmation needed for decryption"))?;
|
||||
let res = sq_util::decryption_helper(d, msg.into_bytes(), &sp)?;
|
||||
|
||||
let plain = String::from_utf8_lossy(&res);
|
||||
|
@ -194,11 +192,11 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
// Use Sign access to card
|
||||
let mut sign = open.signing_card().expect("just verified");
|
||||
|
||||
let cert = Cert::from_file(TEST_KEY_PATH)?;
|
||||
let _cert = Cert::from_file(TEST_KEY_PATH)?;
|
||||
|
||||
let text = "Hello world, I am signed.";
|
||||
|
||||
let signer = sign.signer(&cert, &|| {})?;
|
||||
let signer = sign.signer(&|| {})?;
|
||||
let sig = sq_util::sign_helper(signer, &mut text.as_bytes())?;
|
||||
|
||||
println!("Signature from card:\n{}", sig)
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
use sequoia_openpgp::cert::amalgamation::key::ValidErasedKeyAmalgamation;
|
||||
use sequoia_openpgp::packet::key::SecretParts;
|
||||
use sequoia_openpgp::types::{HashAlgorithm, SymmetricAlgorithm};
|
||||
use sequoia_openpgp::Cert;
|
||||
|
||||
use openpgp_card::algorithm::{Algo, AlgoInfo, AlgoSimple};
|
||||
use openpgp_card::card_do::{
|
||||
|
@ -15,13 +14,13 @@ use openpgp_card::card_do::{
|
|||
ExtendedLengthInfo, Fingerprint, HistoricalBytes, KeyGenerationTime, Lang, PWStatusBytes,
|
||||
SecuritySupportTemplate, Sex, TouchPolicy,
|
||||
};
|
||||
use openpgp_card::crypto_data::PublicKeyMaterial;
|
||||
use openpgp_card::{Error, KeySet, KeyType, OpenPgpTransaction};
|
||||
|
||||
use crate::decryptor::CardDecryptor;
|
||||
use crate::signer::CardSigner;
|
||||
use crate::util::{public_to_fingerprint, vka_as_uploadable_key};
|
||||
use crate::PublicKey;
|
||||
use openpgp_card::crypto_data::PublicKeyMaterial;
|
||||
|
||||
/// Representation of an opened OpenPGP card in its base state (i.e. no
|
||||
/// passwords have been verified, default authorization applies).
|
||||
|
@ -340,13 +339,40 @@ pub struct User<'app, 'open> {
|
|||
impl<'app, 'open> User<'app, 'open> {
|
||||
pub fn decryptor(
|
||||
&mut self,
|
||||
cert: &Cert,
|
||||
touch_prompt: &'open (dyn Fn() + Send + Sync),
|
||||
) -> Result<CardDecryptor<'_, 'app>, Error> {
|
||||
CardDecryptor::new(&mut self.oc.opt, cert, touch_prompt)
|
||||
let pk = crate::util::key_slot(self.oc, KeyType::Decryption)?
|
||||
.expect("Couldn't get decryption pubkey from card");
|
||||
|
||||
Ok(CardDecryptor::with_pubkey(
|
||||
&mut self.oc.opt,
|
||||
pk,
|
||||
touch_prompt,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn decryptor_from_public(
|
||||
&mut self,
|
||||
pubkey: PublicKey,
|
||||
touch_prompt: &'open (dyn Fn() + Send + Sync),
|
||||
) -> CardDecryptor<'_, 'app> {
|
||||
CardDecryptor::with_pubkey(&mut self.oc.opt, pubkey, touch_prompt)
|
||||
}
|
||||
|
||||
pub fn authenticator(
|
||||
&mut self,
|
||||
touch_prompt: &'open (dyn Fn() + Send + Sync),
|
||||
) -> Result<CardSigner<'_, 'app>, Error> {
|
||||
let pk = crate::util::key_slot(self.oc, KeyType::Authentication)?
|
||||
.expect("Couldn't get authentication pubkey from card");
|
||||
|
||||
Ok(CardSigner::with_pubkey_for_auth(
|
||||
&mut self.oc.opt,
|
||||
pk,
|
||||
touch_prompt,
|
||||
))
|
||||
}
|
||||
pub fn authenticator_from_public(
|
||||
&mut self,
|
||||
pubkey: PublicKey,
|
||||
touch_prompt: &'open (dyn Fn() + Send + Sync),
|
||||
|
@ -364,16 +390,18 @@ pub struct Sign<'app, 'open> {
|
|||
impl<'app, 'open> Sign<'app, 'open> {
|
||||
pub fn signer(
|
||||
&mut self,
|
||||
cert: &Cert,
|
||||
touch_prompt: &'open (dyn Fn() + Send + Sync),
|
||||
) -> std::result::Result<CardSigner<'_, 'app>, Error> {
|
||||
) -> Result<CardSigner<'_, 'app>, Error> {
|
||||
// FIXME: depending on the setting in "PW1 Status byte", only one
|
||||
// signature can be made after verification for signing
|
||||
|
||||
CardSigner::with_cert(&mut self.oc.opt, cert, touch_prompt)
|
||||
let pk = crate::util::key_slot(self.oc, KeyType::Signing)?
|
||||
.expect("Couldn't get signing pubkey from card");
|
||||
|
||||
Ok(CardSigner::with_pubkey(&mut self.oc.opt, pk, touch_prompt))
|
||||
}
|
||||
|
||||
pub fn signer_from_pubkey(
|
||||
pub fn signer_from_public(
|
||||
&mut self,
|
||||
pubkey: PublicKey,
|
||||
touch_prompt: &'open (dyn Fn() + Send + Sync),
|
||||
|
|
|
@ -9,13 +9,11 @@ use openpgp::crypto::SessionKey;
|
|||
use openpgp::packet;
|
||||
use openpgp::parse::stream::{DecryptionHelper, MessageStructure, VerificationHelper};
|
||||
use openpgp::types::{Curve, SymmetricAlgorithm};
|
||||
use openpgp::Cert;
|
||||
use sequoia_openpgp as openpgp;
|
||||
|
||||
use openpgp_card::crypto_data::Cryptogram;
|
||||
use openpgp_card::{Error, OpenPgpTransaction};
|
||||
use openpgp_card::OpenPgpTransaction;
|
||||
|
||||
use crate::sq_util;
|
||||
use crate::PublicKey;
|
||||
|
||||
pub struct CardDecryptor<'a, 'app> {
|
||||
|
@ -30,41 +28,15 @@ pub struct CardDecryptor<'a, 'app> {
|
|||
}
|
||||
|
||||
impl<'a, 'app> CardDecryptor<'a, 'app> {
|
||||
/// Try to create a CardDecryptor.
|
||||
///
|
||||
/// An Error is returned if no match between the card's decryption
|
||||
/// key and a (sub)key of `cert` can be made.
|
||||
pub fn new(
|
||||
pub(crate) fn with_pubkey(
|
||||
ca: &'a mut OpenPgpTransaction<'app>,
|
||||
cert: &Cert,
|
||||
public: PublicKey,
|
||||
touch_prompt: &'a (dyn Fn() + Send + Sync),
|
||||
) -> Result<CardDecryptor<'a, 'app>, Error> {
|
||||
// Get the fingerprint for the decryption key from the card.
|
||||
let ard = ca.application_related_data()?;
|
||||
let fps = ard.fingerprints()?;
|
||||
let fp = fps.decryption();
|
||||
|
||||
if let Some(fp) = fp {
|
||||
// Transform into Sequoia Fingerprint
|
||||
let fp = openpgp::Fingerprint::from_bytes(fp.as_bytes());
|
||||
|
||||
if let Some(eka) = sq_util::get_subkey_by_fingerprint(cert, &fp)? {
|
||||
let public = eka.key().clone();
|
||||
Ok(Self {
|
||||
ca,
|
||||
public,
|
||||
touch_prompt,
|
||||
})
|
||||
} else {
|
||||
Err(Error::InternalError(format!(
|
||||
"Failed to find (sub)key {} in cert",
|
||||
fp
|
||||
)))
|
||||
}
|
||||
} else {
|
||||
Err(Error::InternalError(
|
||||
"Failed to get the decryption key's Fingerprint from the card".to_string(),
|
||||
))
|
||||
) -> CardDecryptor<'a, 'app> {
|
||||
Self {
|
||||
ca,
|
||||
public,
|
||||
touch_prompt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,13 +67,8 @@
|
|||
//! open.verify_user(b"123456")?;
|
||||
//! let mut user = open.user_card().expect("This should not fail");
|
||||
//!
|
||||
//! // Get decryptor (`cert` must contain a public key that corresponds
|
||||
//! // to the key material on the card)
|
||||
//! # use sequoia_openpgp::cert::CertBuilder;
|
||||
//! # let (cert, _) =
|
||||
//! # CertBuilder::general_purpose(None, Some("alice@example.org"))
|
||||
//! # .generate()?;
|
||||
//! let decryptor = user.decryptor(&cert, &|| { println!("Touch confirmation needed for decryption") });
|
||||
//! // Get decryptor
|
||||
//! let decryptor = user.decryptor(&|| { println!("Touch confirmation needed for decryption") });
|
||||
//!
|
||||
//! // Perform decryption operation(s)
|
||||
//! // ..
|
||||
|
@ -110,13 +105,8 @@
|
|||
//! open.verify_user_for_signing(b"123456")?;
|
||||
//! let mut user = open.signing_card().expect("This should not fail");
|
||||
//!
|
||||
//! // Get signer (`cert` must contain a public key that corresponds
|
||||
//! // to the key material on the card)
|
||||
//! # use sequoia_openpgp::cert::CertBuilder;
|
||||
//! # let (cert, _) =
|
||||
//! # CertBuilder::general_purpose(None, Some("alice@example.org"))
|
||||
//! # .generate()?;
|
||||
//! let signer = user.signer(&cert, &|| println!("Touch confirmation needed for signing"));
|
||||
//! // Get signer
|
||||
//! let signer = user.signer(&|| println!("Touch confirmation needed for signing"));
|
||||
//!
|
||||
//! // Perform signing operation(s)
|
||||
//! // ..
|
||||
|
|
|
@ -11,9 +11,8 @@ use openpgp::types::{Curve, PublicKeyAlgorithm};
|
|||
use sequoia_openpgp as openpgp;
|
||||
|
||||
use openpgp_card::crypto_data::Hash;
|
||||
use openpgp_card::{Error, OpenPgpTransaction};
|
||||
use openpgp_card::OpenPgpTransaction;
|
||||
|
||||
use crate::sq_util;
|
||||
use crate::PublicKey;
|
||||
|
||||
pub struct CardSigner<'a, 'app> {
|
||||
|
@ -31,40 +30,6 @@ pub struct CardSigner<'a, 'app> {
|
|||
}
|
||||
|
||||
impl<'a, 'app> CardSigner<'a, 'app> {
|
||||
/// Try to create a CardSigner.
|
||||
///
|
||||
/// An Error is returned if no match between the card's signing
|
||||
/// key and a (sub)key of `cert` can be made.
|
||||
pub(crate) fn with_cert(
|
||||
ca: &'a mut OpenPgpTransaction<'app>,
|
||||
cert: &openpgp::Cert,
|
||||
touch_prompt: &'a (dyn Fn() + Send + Sync),
|
||||
) -> Result<CardSigner<'a, 'app>, Error> {
|
||||
// Get the fingerprint for the signing key from the card.
|
||||
let ard = ca.application_related_data()?;
|
||||
let fps = ard.fingerprints()?;
|
||||
let fp = fps.signature();
|
||||
|
||||
if let Some(fp) = fp {
|
||||
// Transform into Sequoia Fingerprint
|
||||
let fp = openpgp::Fingerprint::from_bytes(fp.as_bytes());
|
||||
|
||||
if let Some(eka) = sq_util::get_subkey_by_fingerprint(cert, &fp)? {
|
||||
let key = eka.key().clone();
|
||||
Ok(Self::with_pubkey(ca, key, touch_prompt))
|
||||
} else {
|
||||
Err(Error::InternalError(format!(
|
||||
"Failed to find (sub)key {} in cert",
|
||||
fp
|
||||
)))
|
||||
}
|
||||
} else {
|
||||
Err(Error::InternalError(
|
||||
"Failed to get the signing key's Fingerprint from the card".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn with_pubkey(
|
||||
ca: &'a mut OpenPgpTransaction<'app>,
|
||||
public: PublicKey,
|
||||
|
|
|
@ -29,11 +29,13 @@ use sequoia_openpgp::types::{HashAlgorithm, SymmetricAlgorithm};
|
|||
use openpgp_card::algorithm::{Algo, Curve};
|
||||
use openpgp_card::card_do::{Fingerprint, KeyGenerationTime};
|
||||
use openpgp_card::crypto_data::{CardUploadableKey, PublicKeyMaterial};
|
||||
use openpgp_card::{Error, KeyType, OpenPgpTransaction};
|
||||
use openpgp_card::{Error, KeyType};
|
||||
|
||||
use crate::card::Open;
|
||||
use crate::decryptor::CardDecryptor;
|
||||
use crate::privkey::SequoiaKey;
|
||||
use crate::{decryptor, signer, PublicKey};
|
||||
use crate::signer::CardSigner;
|
||||
use crate::PublicKey;
|
||||
|
||||
/// Create a Cert from the three subkeys on a card.
|
||||
/// (Calling this multiple times will result in different Certs!)
|
||||
|
@ -85,7 +87,7 @@ pub fn make_cert<'app>(
|
|||
}
|
||||
if let Some(mut sign) = open.signing_card() {
|
||||
// Card-backed signer for bindings
|
||||
let mut card_signer = sign.signer_from_pubkey(key_sig.clone(), touch_prompt);
|
||||
let mut card_signer = sign.signer_from_public(key_sig.clone(), touch_prompt);
|
||||
|
||||
let signing_bsig: Packet = sub_dec
|
||||
.bind(&mut card_signer, &cert, signing_builder)?
|
||||
|
@ -116,7 +118,7 @@ pub fn make_cert<'app>(
|
|||
}
|
||||
if let Some(mut sign) = open.signing_card() {
|
||||
// Card-backed signer for bindings
|
||||
let mut card_signer = sign.signer_from_pubkey(key_sig.clone(), touch_prompt);
|
||||
let mut card_signer = sign.signer_from_public(key_sig.clone(), touch_prompt);
|
||||
|
||||
// Temporary version of the cert
|
||||
let cert = Cert::try_from(pp.clone())?;
|
||||
|
@ -159,7 +161,7 @@ pub fn make_cert<'app>(
|
|||
|
||||
if let Some(mut sign) = open.signing_card() {
|
||||
// Card-backed signer for bindings
|
||||
let mut card_signer = sign.signer_from_pubkey(key_sig, touch_prompt);
|
||||
let mut card_signer = sign.signer_from_public(key_sig, touch_prompt);
|
||||
|
||||
// Temporary version of the cert
|
||||
let cert = Cert::try_from(pp.clone())?;
|
||||
|
@ -238,7 +240,7 @@ pub fn public_key_material_and_fp_to_key(
|
|||
}
|
||||
|
||||
/// Get a PublicKey representation for a key slot on the card
|
||||
pub fn key_slot(open: &mut Open, kt: KeyType) -> Result<Option<PublicKey>> {
|
||||
pub fn key_slot(open: &mut Open, kt: KeyType) -> Result<Option<PublicKey>, Error> {
|
||||
// FIXME: only read these once, if multiple subkeys are retrieved from the card
|
||||
let times = open.key_generation_times()?;
|
||||
let fps = open.fingerprints()?;
|
||||
|
@ -425,17 +427,9 @@ pub fn vka_as_uploadable_key(
|
|||
Box::new(sqk)
|
||||
}
|
||||
|
||||
/// FIXME: this fn is used in card_functionality, but should be removed
|
||||
pub fn sign(
|
||||
card_tx: &'_ mut OpenPgpTransaction<'_>,
|
||||
cert: &Cert,
|
||||
input: &mut dyn io::Read,
|
||||
touch_prompt: &(dyn Fn() + Send + Sync),
|
||||
) -> Result<String> {
|
||||
pub fn sign(s: CardSigner, input: &mut dyn io::Read) -> Result<String> {
|
||||
let mut armorer = armor::Writer::new(vec![], armor::Kind::Signature)?;
|
||||
{
|
||||
let s = signer::CardSigner::with_cert(card_tx, cert, touch_prompt)?;
|
||||
|
||||
let message = Message::new(&mut armorer);
|
||||
let mut message = Signer::new(message, s).detached().build()?;
|
||||
|
||||
|
@ -450,20 +444,11 @@ pub fn sign(
|
|||
String::from_utf8(buffer).context("Failed to convert signature to utf8")
|
||||
}
|
||||
|
||||
/// FIXME: this fn is used in card_functionality, but should be removed
|
||||
pub fn decrypt(
|
||||
card_tx: &'_ mut OpenPgpTransaction<'_>,
|
||||
cert: &Cert,
|
||||
msg: Vec<u8>,
|
||||
touch_prompt: &(dyn Fn() + Send + Sync),
|
||||
p: &dyn Policy,
|
||||
) -> Result<Vec<u8>> {
|
||||
pub fn decrypt(d: CardDecryptor, msg: Vec<u8>, p: &dyn Policy) -> Result<Vec<u8>> {
|
||||
let mut decrypted = Vec::new();
|
||||
{
|
||||
let reader = io::BufReader::new(&msg[..]);
|
||||
|
||||
let d = decryptor::CardDecryptor::new(card_tx, cert, touch_prompt)?;
|
||||
|
||||
let db = DecryptorBuilder::from_reader(reader)?;
|
||||
let mut decryptor = db.with_policy(p, None, d)?;
|
||||
|
||||
|
|
Loading…
Reference in a new issue