1use sare_core::{
2 format::signature::{SignatureFormat, SignatureHeaderFormat, SignatureMetadataFormat},
3 hybrid_sign::{ECSignature, PQSignature},
4};
5
6use crate::{SARE_VERSION, SareError, keys::MasterKey};
7
8pub struct Signing(MasterKey);
9
10impl Signing {
11 pub fn new(master_key: MasterKey) -> Self {
13 Self(master_key)
14 }
15
16 fn sign(&self, raw_message: &[u8], attached: bool) -> SignatureHeaderFormat {
18 let fullchain_fingerprint = self.0.get_fullchain_public_fingerprint();
19 let merged_message =
20 Self::merge_message_with_fingerprint(raw_message, &fullchain_fingerprint);
21
22 let (ec_keypair, pq_keypair) = self.0.get_signing_keypair();
23
24 let message_for_attached = if attached {
25 Some(raw_message.to_vec())
26 } else {
27 None
28 };
29
30 let ec_signature = ECSignature::new(&ec_keypair).hash_and_sign(&merged_message);
31 let pq_signature = PQSignature::new(&pq_keypair).hash_and_sign(&merged_message);
32
33 let signature_metadata = SignatureMetadataFormat {
34 ec_algorithm: ec_keypair.algorithm,
35 pq_algorithm: pq_keypair.algorithm,
36 };
37
38 let signature = SignatureFormat {
39 ec_public_key: ec_keypair.public_key,
40 pq_public_key: pq_keypair.public_key,
41 signature_metadata: Some(signature_metadata),
42 message: message_for_attached,
43 ec_signature,
44 pq_signature,
45 fullchain_fingerprint,
46 };
47
48 SignatureHeaderFormat {
49 version: SARE_VERSION,
50 signature,
51 }
52 }
53
54 pub fn sign_attached(&self, raw_message: &[u8]) -> SignatureHeaderFormat {
56 self.sign(raw_message, true)
57 }
58
59 pub fn sign_detached(&self, raw_message: &[u8]) -> SignatureHeaderFormat {
61 self.sign(raw_message, false)
62 }
63
64 fn verify(signature_header: &SignatureHeaderFormat, message: &[u8]) -> Result<bool, SareError> {
66 if signature_header.version > SARE_VERSION {
67 return Err(SareError::Unexpected(format!(
68 "sare version {} or higher is required, your version is {}",
69 signature_header.version, SARE_VERSION
70 )));
71 }
72
73 let signature = &signature_header.signature;
74 let merged_message =
75 Self::merge_message_with_fingerprint(message, &signature.fullchain_fingerprint);
76
77 let signature_metadata = signature.signature_metadata.as_ref().ok_or_else(|| {
78 SareError::CoreError(sare_core::CoreErrorKind::HybridSign(
79 sare_core::hybrid_sign::error::HybridSignError::Unexpected,
80 ))
81 })?;
82
83 let ec_valid = ECSignature::hash_and_verify(
84 &signature_metadata.ec_algorithm,
85 &signature.ec_public_key,
86 &merged_message,
87 &signature.ec_signature,
88 )?;
89
90 let pq_valid = PQSignature::hash_and_verify(
91 &signature_metadata.pq_algorithm,
92 &signature.pq_public_key,
93 &merged_message,
94 &signature.pq_signature,
95 )?;
96
97 Ok(ec_valid && pq_valid)
98 }
99
100 pub fn verify_detached(
102 signature_header: &SignatureHeaderFormat,
103 raw_message: &[u8],
104 ) -> Result<bool, SareError> {
105 Self::verify(signature_header, raw_message)
106 }
107
108 pub fn verify_attached(signature_header: &SignatureHeaderFormat) -> Result<bool, SareError> {
110 let signature = &signature_header.signature;
111 let message = signature.message.as_ref().ok_or_else(|| {
112 SareError::CoreError(sare_core::CoreErrorKind::HybridSign(
113 sare_core::hybrid_sign::error::HybridSignError::Unexpected,
114 ))
115 })?;
116
117 Self::verify(signature_header, message)
118 }
119
120 fn merge_message_with_fingerprint(message: &[u8], fingerprint: &[u8]) -> Vec<u8> {
122 let mut merged = Vec::with_capacity(message.len() + fingerprint.len());
123 merged.extend_from_slice(message);
124 merged.extend_from_slice(fingerprint);
125 merged
126 }
127}