From 8775c786f6e487f42ea5323f0c2b186b3ff4f092 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Wed, 6 Nov 2024 23:18:00 -0800 Subject: [PATCH] Adds support for ECDSA signatures --- CHANGELOG.md | 4 ++++ src/rpm/headers/signature_builder.rs | 16 ++++++++++++++ src/rpm/package.rs | 3 +++ src/rpm/signature/pgp.rs | 10 +++++++++ src/rpm/signature/traits.rs | 1 + .../signing_keys/public_nistp256.asc | 10 +++++++++ .../signing_keys/secret_nistp256.asc | 11 ++++++++++ tests/common.rs | 16 ++++++++++++++ tests/signatures.rs | 22 +++++++++++++++++++ 9 files changed, 93 insertions(+) create mode 100644 test_assets/fixture_packages/signing_keys/public_nistp256.asc create mode 100644 test_assets/fixture_packages/signing_keys/secret_nistp256.asc diff --git a/CHANGELOG.md b/CHANGELOG.md index 429be925..7ba82027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added support for ecdsa signatures + ## 0.16.0 ### Added diff --git a/src/rpm/headers/signature_builder.rs b/src/rpm/headers/signature_builder.rs index 0ce6d32b..fc7fd7d9 100644 --- a/src/rpm/headers/signature_builder.rs +++ b/src/rpm/headers/signature_builder.rs @@ -113,6 +113,22 @@ impl SignatureHeaderBuilder { phantom: Default::default(), } } + + pub fn add_ecdsa_signature( + mut self, + sig_header_only: &[u8], + ) -> SignatureHeaderBuilder { + let offset = 0i32; // filled externally later on + self.entries.push(IndexEntry::new( + IndexSignatureTag::RPMSIGTAG_DSA, + offset, + IndexData::Bin(sig_header_only.to_vec()), + )); + SignatureHeaderBuilder:: { + entries: self.entries, + phantom: Default::default(), + } + } } #[cfg(test)] diff --git a/src/rpm/package.rs b/src/rpm/package.rs index 837dc74c..78424e73 100644 --- a/src/rpm/package.rs +++ b/src/rpm/package.rs @@ -115,6 +115,9 @@ impl Package { crate::signature::AlgorithmType::EdDSA => { sig_header_builder.add_eddsa_signature(&header_signature) } + crate::signature::AlgorithmType::ECDSA => { + sig_header_builder.add_ecdsa_signature(&header_signature) + } }; self.metadata.signature = sig_header_builder.build(); diff --git a/src/rpm/signature/pgp.rs b/src/rpm/signature/pgp.rs index e97bc04a..aeee4276 100644 --- a/src/rpm/signature/pgp.rs +++ b/src/rpm/signature/pgp.rs @@ -31,6 +31,7 @@ impl From for ::pgp::crypto::public_key::PublicKeyAlgorit match value { traits::AlgorithmType::RSA => PublicKeyAlgorithm::RSA, traits::AlgorithmType::EdDSA => PublicKeyAlgorithm::EdDSALegacy, + traits::AlgorithmType::ECDSA => PublicKeyAlgorithm::ECDSA, } } } @@ -100,6 +101,11 @@ where algorithm: AlgorithmType::EdDSA, key_passphrase: None, }), + PublicKeyAlgorithm::ECDSA => Ok(Self { + secret_key: inner, + algorithm: AlgorithmType::ECDSA, + key_passphrase: None, + }), algorithm => Err(Error::UnsupportedPGPKeyType(algorithm)), } } @@ -263,6 +269,10 @@ impl Verifier { public_key, algorithm: AlgorithmType::EdDSA, }), + PublicKeyAlgorithm::ECDSA => Ok(Self { + public_key, + algorithm: AlgorithmType::ECDSA, + }), a => Err(Error::UnsupportedPGPKeyType(a)), } } diff --git a/src/rpm/signature/traits.rs b/src/rpm/signature/traits.rs index 68780ee8..19178c0d 100644 --- a/src/rpm/signature/traits.rs +++ b/src/rpm/signature/traits.rs @@ -11,6 +11,7 @@ use std::io; #[derive(Clone, Copy, Debug)] pub enum AlgorithmType { RSA, + ECDSA, EdDSA, } diff --git a/test_assets/fixture_packages/signing_keys/public_nistp256.asc b/test_assets/fixture_packages/signing_keys/public_nistp256.asc new file mode 100644 index 00000000..136cab4a --- /dev/null +++ b/test_assets/fixture_packages/signing_keys/public_nistp256.asc @@ -0,0 +1,10 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mFIEZy0/HRMIKoZIzj0DAQcCAwTV3+oPJaeeZrD7lMsdwnV2xD3ZpVuM7QRqERgz +cCOy/mkwdWySiWLe746qxGE015wJ/F/tP5nsDgZJg9A4ofwYtBlBbGljZSA8YWxp +Y2VAZXhhbXBsZS5jb20+iJAEExMIADgWIQSv7E04DLxEn5XutuCNvq52nKsG6gUC +Zy0/HQIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRCNvq52nKsG6nwsAP91 +H80ltwaC07b+T1vpU+WNN1gKIAKTCXEgbYmHJmmAogEAprfD7g4va0CVkgNxNJlM +GrBALsDsXGFrcQi45tDKRUI= +=GgQq +-----END PGP PUBLIC KEY BLOCK----- diff --git a/test_assets/fixture_packages/signing_keys/secret_nistp256.asc b/test_assets/fixture_packages/signing_keys/secret_nistp256.asc new file mode 100644 index 00000000..c6e305a5 --- /dev/null +++ b/test_assets/fixture_packages/signing_keys/secret_nistp256.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lHcEZy0/HRMIKoZIzj0DAQcCAwTV3+oPJaeeZrD7lMsdwnV2xD3ZpVuM7QRqERgz +cCOy/mkwdWySiWLe746qxGE015wJ/F/tP5nsDgZJg9A4ofwYAAD7B9vjV/l8xtDV +tJsRCL51KjMg7TH3hzfI8j7MQZYu+m4SE7QZQWxpY2UgPGFsaWNlQGV4YW1wbGUu +Y29tPoiQBBMTCAA4FiEEr+xNOAy8RJ+V7rbgjb6udpyrBuoFAmctPx0CGwMFCwkI +BwIGFQoJCAsCBBYCAwECHgECF4AACgkQjb6udpyrBup8LAD/dR/NJbcGgtO2/k9b +6VPljTdYCiACkwlxIG2JhyZpgKIBAKa3w+4OL2tAlZIDcTSZTBqwQC7A7Fxha3EI +uObQykVC +=mSPj +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/common.rs b/tests/common.rs index 379ccb60..0a256dba 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -91,3 +91,19 @@ pub fn eddsa_public_key() -> Vec { pub fn load_eddsa_keys() -> (Vec, Vec) { (eddsa_private_key(), eddsa_public_key()) } + +pub fn ecdsa_private_key() -> Vec { + let private_key = + cargo_manifest_dir().join("test_assets/fixture_packages/signing_keys/secret_nistp256.asc"); + std::fs::read(private_key).unwrap() +} + +pub fn ecdsa_public_key() -> Vec { + let public_key = + cargo_manifest_dir().join("test_assets/fixture_packages/signing_keys/public_nistp256.asc"); + std::fs::read(public_key).unwrap() +} + +pub fn load_ecdsa_keys() -> (Vec, Vec) { + (ecdsa_private_key(), ecdsa_public_key()) +} diff --git a/tests/signatures.rs b/tests/signatures.rs index 88d46565..7338730a 100644 --- a/tests/signatures.rs +++ b/tests/signatures.rs @@ -42,6 +42,16 @@ fn test_rpm_file_signatures_resign() -> Result<(), Box> { None, &verification_key, "eddsa_resigned_pkg.rpm", + )?; + + // test ECDSA + let (signing_key, verification_key) = common::load_ecdsa_keys(); + resign_and_verify_with_keys( + pkg_path.as_ref(), + &signing_key, + None, + &verification_key, + "ecdsa_resigned_pkg.rpm", ) } @@ -59,6 +69,10 @@ fn parse_externally_signed_rpm_and_verify() -> Result<(), Box Result<(), Box> { Err(rpm::Error::NoSignatureFound) )); + // test ECDSA + let verification_key = common::ecdsa_public_key(); + let verifier = Verifier::load_from_asc_bytes(verification_key.as_ref())?; + assert!(matches!( + pkg.verify_signature(verifier), + Err(rpm::Error::NoSignatureFound) + )); + Ok(()) }