use core::fmt::Debug;
#[cfg(feature = "x509")]
use crate::crypto::x509::error::CertificateValidationError;
use crate::der::oid::ObjectIdentifier;
#[derive(Debug)]
pub enum CryptoPolicyError {
UnsupportedAlgorithm(ObjectIdentifier),
}
crate::impl_error_display!(unconditional CryptoPolicyError {
UnsupportedAlgorithm(oid) => "Unsupported algorithm: {oid}",
});
#[cfg(feature = "x509")]
pub trait VerificationPolicy: Send + Sync + Debug {
fn verify_signature(
&self,
algorithm_oid: &ObjectIdentifier,
public_key_der: &[u8],
message: &[u8],
signature: &[u8],
) -> Result<(), CertificateValidationError>;
}
#[cfg(all(feature = "secp256k1", feature = "signature", feature = "x509"))]
#[derive(Debug, Clone, Copy, Default)]
pub struct Secp256k1Policy;
#[cfg(all(feature = "secp256k1", feature = "signature", feature = "x509"))]
impl VerificationPolicy for Secp256k1Policy {
fn verify_signature(
&self,
algorithm_oid: &ObjectIdentifier,
public_key_der: &[u8],
message: &[u8],
signature: &[u8],
) -> Result<(), CertificateValidationError> {
use crate::crypto::hash::Sha3_256;
use crate::crypto::sign::ecdsa::{Secp256k1Signature, Secp256k1VerifyingKey};
use crate::crypto::sign::verify_canonical;
use crate::oids::SIGNER_ECDSA_WITH_SHA3_256;
use crate::spki::DecodePublicKey;
if algorithm_oid != &SIGNER_ECDSA_WITH_SHA3_256 {
return Err(CertificateValidationError::UnsupportedAlgorithm(*algorithm_oid));
}
let verifying_key = Secp256k1VerifyingKey::from_public_key_der(public_key_der)?;
let sig = Secp256k1Signature::try_from(signature)?;
verify_canonical::<Sha3_256, _>(&verifying_key, message, &sig)?;
Ok(())
}
}
#[cfg(all(
test,
feature = "secp256k1",
feature = "signature",
feature = "x509",
feature = "sha3"
))]
mod tests {
use signature::DigestSigner;
use super::{Secp256k1Policy, VerificationPolicy};
use crate::crypto::hash::Sha3_256;
use crate::crypto::sign::ecdsa::{Secp256k1Signature, Secp256k1SigningKey};
use crate::oids::SIGNER_ECDSA_WITH_SHA3_256;
use crate::spki::EncodePublicKey;
use crate::testing::create_test_signing_key;
#[test]
fn verifies_independent_sha3_ecdsa_signature() -> Result<(), Box<dyn std::error::Error>> {
let signing_key: Secp256k1SigningKey = create_test_signing_key();
let message = b"independent sha3-ecdsa interop";
let mut digest = Sha3_256::default();
digest::Digest::update(&mut digest, message);
let signature: Secp256k1Signature = signing_key.try_sign_digest(digest)?;
let public_key_der = signing_key.verifying_key().to_public_key_der()?;
Secp256k1Policy.verify_signature(
&SIGNER_ECDSA_WITH_SHA3_256,
public_key_der.as_bytes(),
message,
&signature.to_bytes(),
)?;
Ok(())
}
}