1use super::certificate::Certificate;
2pub use sare_core::encryption::{EncryptionAlgorithm, KeyWrap};
3pub use sare_core::format::encryption::*;
4pub use sare_core::format::keys::*;
5pub use sare_core::format::{EncodablePublic, EncodableSecret};
6pub use sare_core::hybrid_kem::{DHAlgorithm, DHKeyPair, KEMAlgorithm, KEMKeyPair};
7pub use sare_core::hybrid_sign::{ECAlgorithm, ECKeyPair, PQAlgorithm, PQKeyPair};
8use sare_core::kdf::{KDF, PKDF, PKDFAlgorithm};
9use sare_core::pem;
10pub use sare_core::seed::Seed;
11use secrecy::{ExposeSecret, SecretString, SecretVec};
12use std::io::{BufReader, Read, Write};
13
14use crate::SareError;
15
16pub const RECOMMENDED_PKDF_PARAMS: PKDFAlgorithm = PKDFAlgorithm::Scrypt(17, 8, 12);
17
18#[derive(Clone, Copy)]
19pub struct HybridSignAlgorithm {
20 ec_algorithm: ECAlgorithm,
21 pq_algorithm: PQAlgorithm,
22}
23
24impl Default for HybridSignAlgorithm {
25 fn default() -> Self {
26 HybridSignAlgorithm {
27 ec_algorithm: ECAlgorithm::Ed25519,
28 pq_algorithm: PQAlgorithm::Dilithium3,
29 }
30 }
31}
32
33impl HybridSignAlgorithm {
34 pub fn from_string(algo: String) -> Self {
35 match algo.to_ascii_uppercase().as_str() {
36 "ED25519_DILITHIUM3" => HybridSignAlgorithm {
37 ec_algorithm: ECAlgorithm::Ed25519,
38 pq_algorithm: PQAlgorithm::Dilithium3,
39 },
40 _ => HybridSignAlgorithm::default(),
41 }
42 }
43}
44
45#[derive(Clone, Copy)]
46pub struct HybridKEMAlgorithm {
47 pub dh_algorithm: DHAlgorithm,
48 pub kem_algorithm: KEMAlgorithm,
49}
50
51impl Default for HybridKEMAlgorithm {
52 fn default() -> Self {
53 HybridKEMAlgorithm {
54 dh_algorithm: DHAlgorithm::X25519,
55 kem_algorithm: KEMAlgorithm::Kyber768,
56 }
57 }
58}
59
60impl HybridKEMAlgorithm {
61 pub fn from_string(algo: String) -> Self {
62 match algo.to_ascii_uppercase().as_str() {
63 "X25519_KYBER768" => HybridKEMAlgorithm {
64 dh_algorithm: DHAlgorithm::X25519,
65 kem_algorithm: KEMAlgorithm::Kyber768,
66 },
67 _ => HybridKEMAlgorithm::default(),
68 }
69 }
70}
71
72pub struct MasterKey {
73 hybrid_kem_algorithm: HybridKEMAlgorithm,
74 hybrid_sign_algorithm: HybridSignAlgorithm,
75 master_seed: Seed,
76}
77
78impl MasterKey {
79 pub fn generate(
80 hybrid_kem_algorithm: HybridKEMAlgorithm,
81 hybrid_sign_algorithm: HybridSignAlgorithm,
82 ) -> Self {
83 let master_seed = Seed::generate();
84
85 MasterKey {
86 hybrid_kem_algorithm,
87 hybrid_sign_algorithm,
88 master_seed,
89 }
90 }
91
92 pub fn clone(&self) -> Self {
93 MasterKey {
94 hybrid_kem_algorithm: self.hybrid_kem_algorithm,
95 hybrid_sign_algorithm: self.hybrid_sign_algorithm,
96 master_seed: Seed::new(self.master_seed.clone_raw_seed()),
97 }
98 }
99
100 pub fn export<W: Write>(
101 &self,
102 passphrase_bytes: Option<SecretVec<u8>>,
103 mut output: W,
104 ) -> Result<(), SareError> {
105 match passphrase_bytes {
106 Some(passphrase) => {
107 let pkdf_salt = PKDF::generate_salt();
108
109 let pkdf = PKDF::new(&passphrase, pkdf_salt.to_owned(), RECOMMENDED_PKDF_PARAMS);
110
111 let pkdf_metadata = PKDFMetadataFormat {
112 pkdf_salt,
113 pkdf_algorithm: RECOMMENDED_PKDF_PARAMS,
114 };
115
116 let derived_key = pkdf.derive_key(32).unwrap();
118 let keywrap = KeyWrap::new(derived_key).unwrap();
119
120 let encrypted_seed = keywrap.wrap(self.master_seed.get_raw_seed()).unwrap();
121
122 let encryption_metadata = EncryptionMetadataFormat {
123 kem_metadata: None,
124 nonce: None,
125 encryption_algorithm: EncryptionAlgorithm::AES256KW,
126 pkdf_metadata: Some(pkdf_metadata),
127 };
128
129 let secret_key_format = SecretKeyFormat {
131 ec_algorithm: self.hybrid_sign_algorithm.ec_algorithm,
132 pq_algorithm: self.hybrid_sign_algorithm.pq_algorithm,
133 dh_algorithm: self.hybrid_kem_algorithm.dh_algorithm,
134 kem_algorithm: self.hybrid_kem_algorithm.kem_algorithm,
135 master_seed: SecretVec::from(encrypted_seed),
136 encryption_metadata: Some(encryption_metadata),
137 };
138
139 output.write_all(secret_key_format.encode_pem().expose_secret().as_bytes())?;
140 }
141 None => {
142 let secret_key_format = SecretKeyFormat {
144 ec_algorithm: self.hybrid_sign_algorithm.ec_algorithm,
145 pq_algorithm: self.hybrid_sign_algorithm.pq_algorithm,
146 dh_algorithm: self.hybrid_kem_algorithm.dh_algorithm,
147 kem_algorithm: self.hybrid_kem_algorithm.kem_algorithm,
148 master_seed: self.master_seed.clone_raw_seed(),
149 encryption_metadata: None,
150 };
151
152 output.write_all(secret_key_format.encode_pem().expose_secret().as_bytes())?;
153 }
154 }
155
156 Ok(())
157 }
158
159 pub fn is_encrypted(secret_key_format: &SecretKeyFormat) -> bool {
160 secret_key_format.encryption_metadata.is_some()
161 }
162
163 pub fn decode_pem<R: Read>(serialized_master_key: R) -> Result<SecretKeyFormat, SareError> {
164 let mut reader = BufReader::new(serialized_master_key);
165
166 let mut string_buf = String::new();
167 reader.read_to_string(&mut string_buf)?;
168 Ok(SecretKeyFormat::decode_pem(SecretString::from(string_buf))?)
169 }
170
171 pub fn import(
172 decoded_master_key_format: SecretKeyFormat,
173 passphrase_bytes: Option<SecretVec<u8>>,
174 ) -> Result<Self, SareError> {
175 let hybrid_sign_algorithm = HybridSignAlgorithm {
176 ec_algorithm: decoded_master_key_format.ec_algorithm,
177 pq_algorithm: decoded_master_key_format.pq_algorithm,
178 };
179
180 let hybrid_kem_algorithm = HybridKEMAlgorithm {
181 dh_algorithm: decoded_master_key_format.dh_algorithm,
182 kem_algorithm: decoded_master_key_format.kem_algorithm,
183 };
184
185 match passphrase_bytes {
186 Some(passphrase) => {
187 let encryption_metadata = decoded_master_key_format.encryption_metadata.unwrap();
190 let pkdf_metadata = encryption_metadata.pkdf_metadata.unwrap();
192
193 let pkdf = PKDF::new(
194 &passphrase,
195 pkdf_metadata.pkdf_salt,
196 pkdf_metadata.pkdf_algorithm,
197 );
198
199 let derived_key = pkdf.derive_key(32)?;
200
201 let keywrap = KeyWrap::new(derived_key)?;
202
203 let decrypted_master_seed =
204 keywrap.dewrap(&decoded_master_key_format.master_seed)?;
205
206 Ok(MasterKey {
207 hybrid_sign_algorithm,
208 hybrid_kem_algorithm,
209 master_seed: Seed::new(decrypted_master_seed),
210 })
211 }
212 None => Ok(MasterKey {
213 hybrid_sign_algorithm,
214 hybrid_kem_algorithm,
215 master_seed: Seed::new(decoded_master_key_format.master_seed),
216 }),
217 }
218 }
219
220 pub fn get_signing_keypair(&self) -> (ECKeyPair, PQKeyPair) {
221 let ec_algorithm = self.hybrid_sign_algorithm.ec_algorithm;
222 let pq_algorithm = self.hybrid_sign_algorithm.pq_algorithm;
223
224 let ec_keypair = ECKeyPair::from_seed(&self.master_seed, ec_algorithm);
225 let pq_keypair = PQKeyPair::from_seed(&self.master_seed, pq_algorithm);
226
227 (ec_keypair, pq_keypair)
228 }
229
230 pub fn get_encryption_keypair(&self) -> (DHKeyPair, KEMKeyPair) {
231 let dh_algorithm = self.hybrid_kem_algorithm.dh_algorithm;
232 let kem_algorithm = self.hybrid_kem_algorithm.kem_algorithm;
233
234 let dh_keypair = DHKeyPair::from_seed(&self.master_seed, dh_algorithm);
235 let kem_keypair = KEMKeyPair::from_seed(&self.master_seed, kem_algorithm);
236
237 (dh_keypair, kem_keypair)
238 }
239
240 pub fn get_signing_public_key(&self) -> SignaturePublicKeyFormat {
241 let (ec_keypair, pq_keypair) = self.get_signing_keypair();
242
243 SignaturePublicKeyFormat::from_keypairs(ec_keypair, pq_keypair)
244 }
245
246 pub fn get_encryption_public_key(&self) -> EncryptionPublicKeyFormat {
247 let (dh_keypair, kem_keypair) = self.get_encryption_keypair();
248
249 EncryptionPublicKeyFormat::from_keypairs(dh_keypair, kem_keypair)
250 }
251
252 pub fn export_signature_public<W: Write>(&self, mut output: W) -> Result<(), SareError> {
253 let signature_public_key = self.get_signing_public_key();
254
255 output.write_all(signature_public_key.encode_pem().as_bytes())?;
256 Ok(())
257 }
258
259 pub fn export_encryption_public<W: Write>(&self, mut output: W) -> Result<(), SareError> {
260 let encryption_public_key = self.get_signing_public_key();
261
262 output.write_all(encryption_public_key.encode_pem().as_bytes())?;
263 Ok(())
264 }
265
266 fn get_fullchain_public_key(&self) -> FullChainPublicKeyFormat {
267 let signature_public_key = self.get_signing_public_key();
268 let encryption_public_key = self.get_encryption_public_key();
269
270 FullChainPublicKeyFormat {
271 signature_public_key,
272 encryption_public_key,
273 }
274 }
275
276 pub fn export_public<W: Write>(&self, mut output: W) -> Result<[u8; 32], SareError> {
277 let fullchain_public_key = self.get_fullchain_public_key();
278
279 output.write_all(fullchain_public_key.encode_pem().as_bytes())?;
280 Ok(fullchain_public_key.calculate_fingerprint())
281 }
282
283 pub fn get_fullchain_public_fingerprint(&self) -> [u8; 32] {
284 self.get_fullchain_public_key().calculate_fingerprint()
285 }
286
287 pub fn get_fullchain_private_fingerprint(&self) -> Vec<u8> {
288 SecretKeyFormat::calculate_fingerprint(self.master_seed.clone_raw_seed())
289 }
290
291 pub fn to_mnemonic(&self) -> SecretString {
292 self.master_seed.to_mnemonic()
293 }
294}
295
296#[derive(Clone)]
297pub struct SharedPublicKey {
298 pub fullchain_public_key: FullChainPublicKeyFormat,
299 pub validation_certificate: Option<Certificate>,
300}
301
302impl SharedPublicKey {
303 pub fn new(fullchain: FullChainPublicKeyFormat, validation: Option<Certificate>) -> Self {
304 SharedPublicKey {
305 fullchain_public_key: fullchain,
306 validation_certificate: validation,
307 }
308 }
309
310 pub fn from_pem(pem_data: String) -> Result<Self, SareError> {
311 let all_pems =
313 pem::parse_many(&pem_data).map_err(|e| SareError::Unexpected(e.to_string()))?;
314
315 let mut fullchain_public_key: Option<FullChainPublicKeyFormat> = None;
316 let mut validation_certificate: Option<Certificate> = None;
317
318 for block in all_pems {
319 match block.tag() {
320 sare_core::format::keys::FULLCHAIN_PUBLIC_KEY_PEM_TAG => {
321 fullchain_public_key =
322 Some(FullChainPublicKeyFormat::decode_bson(block.contents())?);
323 }
324 sare_core::format::certificate::VALIDATION_PEM_TAG => {
325 validation_certificate = Some(Certificate::decode_bson(block.contents())?)
326 }
327 _ => {}
328 }
329 }
330
331 let fullchain_public_key = fullchain_public_key.ok_or(SareError::Unexpected(
332 "Recipient's PublicKey is Missing".to_string(),
333 ))?;
334
335 Ok(SharedPublicKey {
336 fullchain_public_key,
337 validation_certificate,
338 })
339 }
340
341 pub fn export<W: Write>(&self, mut output: W) -> Result<[u8; 32], SareError> {
342 let fullchain_public_key = &self.fullchain_public_key;
343
344 output.write_all(fullchain_public_key.encode_pem().as_bytes())?;
345
346 if let Some(validation_certificate) = &self.validation_certificate {
347 validation_certificate.export(output)?;
348 }
349
350 Ok(fullchain_public_key.calculate_fingerprint())
351 }
352}