Skip to content

Commit

Permalink
pgp: adds support for signing RPM with an HSM held key
Browse files Browse the repository at this point in the history
  • Loading branch information
baloo committed Nov 8, 2024
1 parent 1cef8bb commit a380e6f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 21 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
56 changes: 36 additions & 20 deletions src/rpm/signature/pgp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T = SignedSecretKey> {
secret_key: T,
algorithm: traits::AlgorithmType,
key_passphrase: Option<String>,
}
Expand All @@ -31,7 +35,10 @@ impl From<traits::AlgorithmType> for ::pgp::crypto::public_key::PublicKeyAlgorit
}
}

impl traits::Signing for Signer {
impl<T> traits::Signing for Signer<T>
where
T: SecretKeyTrait,
{
type Signature = Vec<u8>;

/// Despite the fact the API suggest zero copy pattern,
Expand Down Expand Up @@ -77,6 +84,27 @@ impl traits::Signing for Signer {
}
}

impl<T> Signer<T>
where
T: PublicKeyTrait,
{
pub fn new(inner: T) -> Result<Self, Error> {
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<Self, Error> {
Expand All @@ -88,19 +116,7 @@ impl Signer {
pub fn load_from_asc(input: &str) -> Result<Self, Error> {
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.
Expand Down

0 comments on commit a380e6f

Please sign in to comment.