mithril_common/crypto_helper/cardano/kes/
signer_with_key.rs1use std::path::PathBuf;
2
3use anyhow::{anyhow, Context};
4use kes_summed_ed25519::{
5 kes::{Sum6Kes, Sum6KesSig},
6 traits::KesSk,
7};
8
9use crate::{
10 crypto_helper::{
11 cardano::{KesSignError, KesSigner},
12 KesPeriod, OpCert, SerDeShelleyFileFormat, Sum6KesBytes,
13 },
14 StdResult,
15};
16
17pub struct KesSignerStandard {
19 kes_sk_path: PathBuf,
20 operational_certificate_path: PathBuf,
21}
22
23impl KesSignerStandard {
24 pub fn new(kes_sk_path: PathBuf, operational_certificate_path: PathBuf) -> Self {
26 Self {
27 kes_sk_path,
28 operational_certificate_path,
29 }
30 }
31}
32
33impl KesSigner for KesSignerStandard {
34 fn sign(&self, message: &[u8], kes_period: KesPeriod) -> StdResult<(Sum6KesSig, OpCert)> {
35 let mut kes_sk_bytes = Sum6KesBytes::from_file(&self.kes_sk_path)
36 .map_err(|e| anyhow!(e))
37 .with_context(|| "StandardKesSigner can not read KES secret key from file")?;
38 let mut kes_sk = Sum6Kes::try_from(&mut kes_sk_bytes)
39 .map_err(|e| anyhow!(e))
40 .with_context(|| "StandardKesSigner can not use KES secret key")?;
41 let kes_sk_period = kes_sk.get_period();
42 if kes_sk_period > kes_period {
43 return Err(anyhow!(KesSignError::PeriodMismatch(
44 kes_sk_period,
45 kes_period
46 )));
47 }
48
49 for period in kes_sk_period..kes_period {
51 kes_sk
52 .update()
53 .map_err(|_| KesSignError::UpdateKey(period))?;
54 }
55
56 let operational_certificate = OpCert::from_file(&self.operational_certificate_path)
57 .map_err(|e| anyhow!(e))
58 .with_context(|| "StandardKesSigner can not read operational certificate from file")?;
59
60 Ok((kes_sk.sign(message), operational_certificate))
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 use crate::crypto_helper::cardano::{
69 kes::tests_setup::create_kes_cryptographic_material,
70 tests_setup::KesCryptographicMaterialForTest, KesVerifier, KesVerifierStandard,
71 };
72
73 type PartyIndex = u64;
74
75 #[test]
76 fn create_valid_signature_for_message() {
77 let KesCryptographicMaterialForTest {
78 party_id: _,
79 operational_certificate_file,
80 kes_secret_key_file,
81 } = create_kes_cryptographic_material(
82 1 as PartyIndex,
83 0 as KesPeriod,
84 "create_valid_signature_for_message",
85 );
86 let message = b"Test message for KES signing";
87 let kes_signer = KesSignerStandard::new(kes_secret_key_file, operational_certificate_file);
88 let kes_signing_period = 1;
89
90 let (signature, op_cert) = kes_signer
91 .sign(message, kes_signing_period)
92 .expect("Signing should not fail");
93
94 KesVerifierStandard
95 .verify(message, &signature, &op_cert, kes_signing_period)
96 .expect("Signature verification should not fail");
97 }
98
99 #[test]
100 fn create_invalid_signature_for_different_message() {
101 let KesCryptographicMaterialForTest {
102 party_id: _,
103 operational_certificate_file,
104 kes_secret_key_file,
105 } = create_kes_cryptographic_material(
106 1 as PartyIndex,
107 0 as KesPeriod,
108 "create_invalid_signature_for_different_message",
109 );
110 let message = b"Test message for KES signing";
111 let kes_signer = KesSignerStandard::new(kes_secret_key_file, operational_certificate_file);
112 let kes_signing_period = 1;
113
114 let (signature, op_cert) = kes_signer
115 .sign(message, kes_signing_period)
116 .expect("Signing should not fail");
117
118 KesVerifierStandard
119 .verify(
120 b"Different message",
121 &signature,
122 &op_cert,
123 kes_signing_period,
124 )
125 .expect_err("Signature verification should fail");
126 }
127
128 #[test]
129 fn create_invalid_signature_for_invalid_kes_period() {
130 let kes_period_start = 5 as KesPeriod;
131 let KesCryptographicMaterialForTest {
132 party_id: _,
133 operational_certificate_file,
134 kes_secret_key_file,
135 } = create_kes_cryptographic_material(
136 1 as PartyIndex,
137 kes_period_start,
138 "create_invalid_signature_for_invalid_kes_period",
139 );
140 let message = b"Test message for KES signing";
141 let kes_signer = KesSignerStandard::new(kes_secret_key_file, operational_certificate_file);
142 let kes_signing_period = 2;
143 assert!(
144 kes_signing_period < kes_period_start,
145 "KES signing period should be less than the KES period of the key"
146 );
147
148 kes_signer
149 .sign(message, kes_signing_period)
150 .expect_err("Signing should fail");
151 }
152}