mithril_common/crypto_helper/cardano/kes/
verifier_standard.rs

1use kes_summed_ed25519::{kes::Sum6KesSig, traits::KesSig};
2
3use crate::{
4    StdResult,
5    crypto_helper::{
6        KesPeriod, OpCert,
7        cardano::{KesVerifier, KesVerifyError},
8    },
9};
10
11/// A standard KES signature verifier.
12#[derive(Debug)]
13pub struct KesVerifierStandard;
14
15impl KesVerifier for KesVerifierStandard {
16    /// Verify the signed message and return the original message.
17    fn verify(
18        &self,
19        message: &[u8],
20        signature: &Sum6KesSig,
21        operational_certificate: &OpCert,
22        kes_period: KesPeriod,
23    ) -> StdResult<()> {
24        operational_certificate
25            .validate()
26            .map_err(|_| KesVerifyError::OpCertInvalid)?;
27
28        // Check if the KES period in the operational certificate matches the provided KES period +/- 1
29        let kes_period_try_min = std::cmp::max(0, kes_period.saturating_sub(1));
30        let kes_period_try_max = std::cmp::min(64, kes_period.saturating_add(1));
31        for kes_period_try in kes_period_try_min..kes_period_try_max {
32            if signature
33                .verify(kes_period_try, &operational_certificate.kes_vk, message)
34                .is_ok()
35            {
36                return Ok(());
37            }
38        }
39
40        Err(KesVerifyError::SignatureInvalid(
41            kes_period,
42            operational_certificate.start_kes_period as u32,
43        )
44        .into())
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use crate::crypto_helper::cardano::kes::{KesSigner, KesSignerStandard};
51    use crate::test::crypto_helper::{
52        KesCryptographicMaterialForTest, KesPartyIndexForTest, create_kes_cryptographic_material,
53    };
54
55    use super::*;
56
57    #[test]
58    fn verify_valid_signature_succeeds() {
59        let KesCryptographicMaterialForTest {
60            party_id: _,
61            operational_certificate_file,
62            kes_secret_key_file,
63        } = create_kes_cryptographic_material(
64            1 as KesPartyIndexForTest,
65            0 as KesPeriod,
66            "verify_valid_signature_succeeds",
67        );
68        let message = b"Test message for KES signing";
69        let kes_signer = KesSignerStandard::new(kes_secret_key_file, operational_certificate_file);
70        let kes_signing_period = 1;
71        let (signature, op_cert) = kes_signer
72            .sign(message, kes_signing_period)
73            .expect("Signing should not fail");
74
75        KesVerifierStandard
76            .verify(message, &signature, &op_cert, kes_signing_period)
77            .expect("Signature verification should not fail");
78    }
79
80    #[test]
81    fn verify_invalid_signature_fails() {
82        let KesCryptographicMaterialForTest {
83            party_id: _,
84            operational_certificate_file,
85            kes_secret_key_file,
86        } = create_kes_cryptographic_material(
87            1 as KesPartyIndexForTest,
88            0 as KesPeriod,
89            "verify_invalid_signature_fails",
90        );
91        let message = b"Test message for KES signing";
92        let kes_signer = KesSignerStandard::new(kes_secret_key_file, operational_certificate_file);
93        let kes_signing_period = 1;
94        let (signature, op_cert) = kes_signer
95            .sign(message, kes_signing_period)
96            .expect("Signing should not fail");
97
98        KesVerifierStandard
99            .verify(
100                b"Different message",
101                &signature,
102                &op_cert,
103                kes_signing_period,
104            )
105            .expect_err("Signature verification should fail");
106    }
107}