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