From 8e566591d52030c80aded0e9db6d78d969dc53fb Mon Sep 17 00:00:00 2001 From: Stefan Sterz Date: Wed, 6 Mar 2024 13:35:58 +0100 Subject: [PATCH] auth-api: move signing into the private key this commit moves the current ticket signing code into the private key implementation. the upside is that the caller does not need to deal with openssl's `Signer` directly. it also simplifies and unifies the code by using the same helper for verifying a signature and creating it. also derive `Clone` on `PrivateKey` and `PublicKey`. as they are essentially thin wrappers around `openssl::pkey::PKey` and `openssl::pkey::PKey`, which can be cloned, deriving `Clone` just makes them easier to use. Signed-off-by: Stefan Sterz --- proxmox-auth-api/src/auth_key.rs | 26 ++++++++++++++++---------- proxmox-auth-api/src/ticket.rs | 21 ++------------------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/proxmox-auth-api/src/auth_key.rs b/proxmox-auth-api/src/auth_key.rs index cec73606..32120a30 100644 --- a/proxmox-auth-api/src/auth_key.rs +++ b/proxmox-auth-api/src/auth_key.rs @@ -9,11 +9,13 @@ use openssl::rsa::Rsa; use openssl::sign::{Signer, Verifier}; /// A private auth key used for API ticket signing and verification. +#[derive(Clone)] pub struct PrivateKey { pub(crate) key: PKey, } /// A private auth key used for API ticket verification. +#[derive(Clone)] pub struct PublicKey { pub(crate) key: PKey, } @@ -88,6 +90,13 @@ impl PrivateKey { pub fn public_key(&self) -> Result { PublicKey::from_pem(&self.public_key_to_pem()?) } + + pub(self) fn sign(&self, digest: MessageDigest, data: &[u8]) -> Result, Error> { + Signer::new(digest, &self.key) + .map_err(|e| format_err!("could not create private key signer - {e}"))? + .sign_oneshot_to_vec(data) + .map_err(|e| format_err!("could not sign with private key - {e}")) + } } impl From> for PrivateKey { @@ -204,15 +213,12 @@ impl Keyring { Ok(false) } - pub(crate) fn signer(&self, digest: MessageDigest) -> Result { - Signer::new( - digest, - &self - .signing_key - .as_ref() - .ok_or_else(|| format_err!("no private key available for signing"))? - .key, - ) - .map_err(|err| format_err!("failed to create openssl signer - {err}")) + pub(crate) fn sign(&self, digest: MessageDigest, data: &[u8]) -> Result, Error> { + let key = self + .signing_key + .as_ref() + .ok_or_else(|| format_err!("no private key available for signing"))?; + + key.sign(digest, data) } } diff --git a/proxmox-auth-api/src/ticket.rs b/proxmox-auth-api/src/ticket.rs index 17379125..81054f8b 100644 --- a/proxmox-auth-api/src/ticket.rs +++ b/proxmox-auth-api/src/ticket.rs @@ -116,27 +116,10 @@ where /// Sign the ticket. pub fn sign(&mut self, keyring: &Keyring, aad: Option<&str>) -> Result { let mut output = self.ticket_data(); - let mut signer = keyring.signer(MessageDigest::sha256())?; - - signer - .update(output.as_bytes()) - .map_err(Error::from) - .and_then(|()| { - if let Some(aad) = aad { - signer - .update(b":") - .and_then(|()| signer.update(aad.as_bytes())) - .map_err(Error::from) - } else { - Ok::<_, Error>(()) - } - }) + let signature = keyring + .sign(MessageDigest::sha256(), &self.verification_data(aad)) .map_err(|err| format_err!("error signing ticket: {}", err))?; - let signature = signer - .sign_to_vec() - .map_err(|err| format_err!("error finishing ticket signature: {}", err))?; - use std::fmt::Write; write!( &mut output,