use crate::cms::signed_data::SignedData;
use crate::crypto::sign::SignatureVerifier;
use crate::der::asn1::{ObjectIdentifier, OctetString};
use crate::der::{Decode, Encode};
use crate::transport::handshake::error::HandshakeError;
#[cfg(feature = "signature")]
pub struct TightBeamSignedDataProcessor {
verifier: Box<dyn SignatureVerifier>,
}
#[cfg(feature = "signature")]
impl TightBeamSignedDataProcessor {
pub fn new<V>(verifier: V) -> Self
where
V: SignatureVerifier + 'static,
{
Self { verifier: Box::new(verifier) }
}
pub fn process(&self, signed_data: &SignedData, digest_oid: &ObjectIdentifier) -> Result<Vec<u8>, HandshakeError> {
if signed_data.signer_infos.0.len() != 1 {
return Err(HandshakeError::SignatureVerificationFailed);
}
let signer_info = &signed_data.signer_infos.0.as_ref()[0];
if signer_info.digest_alg.oid != *digest_oid {
return Err(HandshakeError::SignatureVerificationFailed);
}
let content = signed_data
.encap_content_info
.econtent
.as_ref()
.ok_or(HandshakeError::SignatureVerificationFailed)?;
let content_der = content.to_der()?;
let content_bytes = OctetString::from_der(&content_der)?;
let signature_bytes = signer_info.signature.as_bytes();
self.verifier
.verify_signature(content_bytes.as_bytes(), signature_bytes, &signer_info.sid)
.map_err(|_| HandshakeError::SignatureVerificationFailed)?;
Ok(content_bytes.as_bytes().to_vec())
}
pub fn process_der(
&self,
signed_data_der: &[u8],
digest_oid: &ObjectIdentifier,
) -> Result<Vec<u8>, HandshakeError> {
let signed_data = SignedData::from_der(signed_data_der)?;
self.process(&signed_data, digest_oid)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(all(feature = "signature", feature = "secp256k1", feature = "sha3"))]
mod signed_data {
use super::*;
use crate::crypto::hash::Sha3_256;
use crate::crypto::profiles::DefaultCryptoProvider;
use crate::crypto::sign::ecdsa::{Secp256k1Signature, Secp256k1SigningKey, Secp256k1VerifyingKey};
use crate::crypto::sign::EcdsaSignatureVerifier;
use crate::oids::HASH_SHA3_256;
use crate::transport::handshake::builders::TightBeamSignedDataBuilder;
use crate::transport::handshake::tests::{
create_ecdsa_sha3_256_signature_alg, create_sha3_256_digest_alg, create_test_signing_key,
};
fn create_test_signed_data_builder<'a>(
signing_key: &'a Secp256k1SigningKey,
) -> Result<TightBeamSignedDataBuilder<'a, DefaultCryptoProvider, Secp256k1SigningKey>, HandshakeError> {
let digest_alg = create_sha3_256_digest_alg();
let signature_alg = create_ecdsa_sha3_256_signature_alg();
TightBeamSignedDataBuilder::<DefaultCryptoProvider, _>::new(signing_key, digest_alg, signature_alg)
}
fn create_test_verifier(
signing_key: &Secp256k1SigningKey,
) -> Result<
EcdsaSignatureVerifier<Secp256k1VerifyingKey, Secp256k1Signature, Sha3_256>,
crate::error::TightBeamError,
> {
EcdsaSignatureVerifier::<Secp256k1VerifyingKey, Secp256k1Signature, Sha3_256>::from_signing_key(signing_key)
}
fn create_test_processor(
signing_key: &Secp256k1SigningKey,
) -> Result<TightBeamSignedDataProcessor, crate::error::TightBeamError> {
let verifier = create_test_verifier(signing_key)?;
Ok(TightBeamSignedDataProcessor::new(verifier))
}
#[test]
fn test_verify_signed_data() -> Result<(), Box<dyn std::error::Error>> {
let signing_key = create_test_signing_key();
let content = b"test_content_to_verify";
let builder = create_test_signed_data_builder(&signing_key)?;
let signed_data = builder.build(content)?;
let processor = create_test_processor(&signing_key)?;
let verified_content = processor.process(&signed_data, &HASH_SHA3_256)?;
assert_eq!(verified_content, content);
Ok(())
}
#[test]
fn test_verify_der_encoded() -> Result<(), Box<dyn std::error::Error>> {
let signing_key = create_test_signing_key();
let content = b"der_encoded_test";
let builder = create_test_signed_data_builder(&signing_key)?;
let signed_data = builder.build(content)?;
let der_bytes = signed_data.to_der()?;
let processor = create_test_processor(&signing_key)?;
let verified_content = processor.process_der(&der_bytes, &HASH_SHA3_256)?;
assert_eq!(verified_content, content);
Ok(())
}
#[test]
fn test_wrong_key_fails() -> Result<(), Box<dyn std::error::Error>> {
let signing_key = create_test_signing_key();
let wrong_key = create_test_signing_key();
let content = b"test_content";
let builder = create_test_signed_data_builder(&signing_key)?;
let signed_data = builder.build(content)?;
let processor = create_test_processor(&wrong_key)?;
let result = processor.process(&signed_data, &HASH_SHA3_256);
assert!(result.is_err());
Ok(())
}
#[test]
fn test_wrong_digest_algorithm_fails() -> Result<(), Box<dyn std::error::Error>> {
let signing_key = create_test_signing_key();
let content = b"test_content";
let builder = create_test_signed_data_builder(&signing_key)?;
let signed_data = builder.build(content)?;
let wrong_digest_oid = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.1"); let processor = create_test_processor(&signing_key)?;
let result = processor.process(&signed_data, &wrong_digest_oid);
assert!(result.is_err());
Ok(())
}
}
}