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(
34                    kes_period_try,
35                    &operational_certificate.get_kes_verification_key(),
36                    message,
37                )
38                .is_ok()
39            {
40                return Ok(());
41            }
42        }
43
44        Err(KesVerifyError::SignatureInvalid(
45            kes_period,
46            operational_certificate.get_start_kes_period() as u32,
47        )
48        .into())
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use crate::crypto_helper::cardano::kes::{KesSigner, KesSignerStandard};
55    use crate::test::crypto_helper::{
56        KesCryptographicMaterialForTest, KesPartyIndexForTest, create_kes_cryptographic_material,
57    };
58
59    use super::*;
60
61    #[test]
62    fn verify_valid_signature_succeeds() {
63        let KesCryptographicMaterialForTest {
64            party_id: _,
65            operational_certificate_file,
66            kes_secret_key_file,
67        } = create_kes_cryptographic_material(
68            1 as KesPartyIndexForTest,
69            0 as KesPeriod,
70            "verify_valid_signature_succeeds",
71        );
72        let message = b"Test message for KES signing";
73        let kes_signer = KesSignerStandard::new(kes_secret_key_file, operational_certificate_file);
74        let kes_signing_period = 1;
75        let (signature, op_cert) = kes_signer
76            .sign(message, kes_signing_period)
77            .expect("Signing should not fail");
78
79        KesVerifierStandard
80            .verify(message, &signature, &op_cert, kes_signing_period)
81            .expect("Signature verification should not fail");
82    }
83
84    #[test]
85    fn verify_invalid_signature_fails() {
86        let KesCryptographicMaterialForTest {
87            party_id: _,
88            operational_certificate_file,
89            kes_secret_key_file,
90        } = create_kes_cryptographic_material(
91            1 as KesPartyIndexForTest,
92            0 as KesPeriod,
93            "verify_invalid_signature_fails",
94        );
95        let message = b"Test message for KES signing";
96        let kes_signer = KesSignerStandard::new(kes_secret_key_file, operational_certificate_file);
97        let kes_signing_period = 1;
98        let (signature, op_cert) = kes_signer
99            .sign(message, kes_signing_period)
100            .expect("Signing should not fail");
101
102        KesVerifierStandard
103            .verify(
104                b"Different message",
105                &signature,
106                &op_cert,
107                kes_signing_period,
108            )
109            .expect_err("Signature verification should fail");
110    }
111}