From 65fad6ed0c93fbe4eb6a13e2fa2de00c9e38f992 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Wed, 6 Nov 2024 21:54:45 -0800 Subject: [PATCH] pgp: adds support for signing RPM with an HSM held key --- CHANGELOG.md | 6 ++++- src/rpm/signature/pgp.rs | 56 ++++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf03d8c..4392762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -### Changed +### Added - Added `zstdmt` feature which sets zstd compression to use all available cores. - Added feature flags for every compression algorithm to support disabling unused ones. +- Added support for signing with a key held in an HSM + +### Changed + - Bump `pgp` to 0.14.0 ### Breaking Changes diff --git a/src/rpm/signature/pgp.rs b/src/rpm/signature/pgp.rs index 93fdbb5..e97bc04 100644 --- a/src/rpm/signature/pgp.rs +++ b/src/rpm/signature/pgp.rs @@ -7,17 +7,21 @@ use std::io; use pgp::crypto::hash::HashAlgorithm; use pgp::crypto::public_key::PublicKeyAlgorithm; use pgp::packet::{SignatureConfig, SignatureType, Subpacket, SubpacketData}; -use pgp::{self, composed::Deserializable, types::PublicKeyTrait}; +use pgp::{ + self, + composed::Deserializable, + types::{PublicKeyTrait, SecretKeyTrait}, +}; use pgp::{SignedPublicKey, SignedSecretKey}; /// Signer implementation using the `pgp` crate. /// -/// Note that this only supports ascii armored key files -/// commonly with the file extension `.asc` as generated -/// by i.e. `gpg`. +/// This supports either ascii armored key files (commonly with +/// the file extension `.asc` as generated by i.e. `gpg`.), or +/// any object implementing [`SecretKeyTrait`]. #[derive(Clone, Debug)] -pub struct Signer { - secret_key: SignedSecretKey, +pub struct Signer { + secret_key: T, algorithm: traits::AlgorithmType, key_passphrase: Option, } @@ -31,7 +35,10 @@ impl From for ::pgp::crypto::public_key::PublicKeyAlgorit } } -impl traits::Signing for Signer { +impl traits::Signing for Signer +where + T: SecretKeyTrait, +{ type Signature = Vec; /// Despite the fact the API suggest zero copy pattern, @@ -77,6 +84,27 @@ impl traits::Signing for Signer { } } +impl Signer +where + T: PublicKeyTrait, +{ + pub fn new(inner: T) -> Result { + match inner.algorithm() { + PublicKeyAlgorithm::RSA => Ok(Self { + secret_key: inner, + algorithm: AlgorithmType::RSA, + key_passphrase: None, + }), + PublicKeyAlgorithm::EdDSALegacy => Ok(Self { + secret_key: inner, + algorithm: AlgorithmType::EdDSA, + key_passphrase: None, + }), + algorithm => Err(Error::UnsupportedPGPKeyType(algorithm)), + } + } +} + impl Signer { /// load the private key for signing pub fn load_from_asc_bytes(input: &[u8]) -> Result { @@ -88,19 +116,7 @@ impl Signer { pub fn load_from_asc(input: &str) -> Result { let (secret_key, _) = SignedSecretKey::from_string(input).map_err(Error::KeyLoadSecretKeyError)?; - match secret_key.algorithm() { - PublicKeyAlgorithm::RSA => Ok(Self { - secret_key, - algorithm: AlgorithmType::RSA, - key_passphrase: None, - }), - PublicKeyAlgorithm::EdDSALegacy => Ok(Self { - secret_key, - algorithm: AlgorithmType::EdDSA, - key_passphrase: None, - }), - algorithm => Err(Error::UnsupportedPGPKeyType(algorithm)), - } + Self::new(secret_key) } /// Configues the [Signer] with the provided PGP key passphrase.