Skip to main content

rsfn_file/
actions.rs

1use std::{fmt, io};
2
3use crate::{
4    cert::load_cert_and_key,
5    ciphers::{Aes256, load_key},
6    compress::Compressors,
7    encode::Encoders,
8    header,
9};
10
11#[derive(Debug, PartialEq, Eq, Clone)]
12pub enum CertError {
13    MismatchSourceCert,
14    MismatchSourceIssuer,
15    MismatchSourceKeyAlgo,
16    MismatchSourceCertAndKey,
17    MismatchDestinationCert,
18    MismatchDestinationIssuer,
19    MismatchDestinationKeyAlgo,
20    MismatchDestinationCertAndKey,
21}
22
23impl fmt::Display for CertError {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        write!(
26            f,
27            "{}",
28            match self {
29                Self::MismatchSourceCert => "Certificado da origem não coincide",
30                Self::MismatchSourceIssuer => "Emissor do certificado da origem não coincide",
31                Self::MismatchSourceKeyAlgo =>
32                    "Tipo da chave do certificado da origem não coincide",
33                Self::MismatchSourceCertAndKey =>
34                    "Chave privada da origem não coresponde ao seu certificado",
35                Self::MismatchDestinationCert => "Certificado do destino não coincide",
36                Self::MismatchDestinationIssuer => "Emissor do certificado do destino não coincide",
37                Self::MismatchDestinationKeyAlgo =>
38                    "Tipo da chave do certificado do destino não coincide",
39                Self::MismatchDestinationCertAndKey =>
40                    "Chave privada do destino não coresponde ao seu certificado",
41            }
42        )
43    }
44}
45
46#[derive(Debug, PartialEq, Eq, Clone)]
47pub enum CryptError {
48    Plain,
49    DecryptSymmetricKey { error: String },
50    DecryptContent { error: String },
51}
52
53impl CryptError {
54    pub fn is_valid(&self) -> bool {
55        matches!(self, Self::Plain)
56    }
57}
58
59impl fmt::Display for CryptError {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        write!(
62            f,
63            "{}",
64            match self {
65                Self::Plain => "Conteúdo em claro".to_string(),
66                Self::DecryptSymmetricKey { error } =>
67                    format!("Falha ao descriptografar chave simétrica\n{error}"),
68                Self::DecryptContent { error } =>
69                    format!("Falha ao descriptografar os dados\n{error}"),
70            }
71        )
72    }
73}
74
75#[derive(Debug, PartialEq, Eq, Clone)]
76pub enum SignatureError {
77    Blank,
78    Invalid { error: String },
79}
80
81impl fmt::Display for SignatureError {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        write!(
84            f,
85            "{}",
86            match self {
87                Self::Blank => "Assinatura em branco".to_string(),
88                Self::Invalid { error } => format!("Assinatura dos dados inválida\n{error}"),
89            }
90        )
91    }
92}
93
94#[derive(Debug, PartialEq, Eq, Clone)]
95pub enum ProcessContentError {
96    Compress { error: String },
97    Decompress { error: String },
98    Encode { error: String },
99    Decode { error: String },
100}
101
102impl fmt::Display for ProcessContentError {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        write!(
105            f,
106            "{}",
107            match self {
108                Self::Compress { error } => format!("Falha na compactação do arquivo\n{error}"),
109                Self::Decompress { error } => format!("Falha na descompactação\n{error}"),
110                Self::Encode { error } => format!("Falha no encode dos dados UTF-8\n{error}"),
111                Self::Decode { error } => format!("Falha no decode dos dados\n{error}"),
112            }
113        )
114    }
115}
116
117// Header
118
119pub fn load_header<R: io::Read>(file: &mut R) -> Result<header::Header, String> {
120    header::Header::read_from_file(file)
121        .map_err(|error| format!("Falha na leitura do cabeçalho de segurança\n{error}"))
122}
123
124// Encrypt
125
126#[derive(Debug)]
127pub struct EncryptResult {
128    header: header::Header,
129    cert_error: Option<CertError>,
130    data: Vec<u8>,
131}
132
133impl EncryptResult {
134    pub fn new(header: header::Header, cert_error: Option<CertError>, data: Vec<u8>) -> Self {
135        Self {
136            header,
137            cert_error,
138            data,
139        }
140    }
141
142    pub fn header(&self) -> &header::Header {
143        &self.header
144    }
145
146    pub fn is_valid_cert(&self) -> Result<(), CertError> {
147        match &self.cert_error {
148            None => Ok(()),
149            Some(error) => Err(error.clone()),
150        }
151    }
152
153    pub fn data(&self) -> &Vec<u8> {
154        &self.data
155    }
156}
157
158#[derive(Debug, PartialEq, Eq)]
159pub enum EncryptError {
160    SourceCert {
161        error: String,
162    },
163    SourceKey {
164        error: String,
165    },
166    DestinationCert {
167        error: String,
168    },
169    ReadContent {
170        error: String,
171        cert_error: Option<CertError>,
172    },
173    Encode {
174        error: String,
175        cert_error: Option<CertError>,
176    },
177    Compress {
178        error: String,
179        cert_error: Option<CertError>,
180    },
181    EncryptContent {
182        error: String,
183        cert_error: Option<CertError>,
184    },
185    EncryptSymmetricKey {
186        error: String,
187        cert_error: Option<CertError>,
188    },
189    FormatHeader {
190        error: String,
191        cert_error: Option<CertError>,
192    },
193}
194
195impl fmt::Display for EncryptError {
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197        write!(
198            f,
199            "{}",
200            match self {
201                Self::SourceCert { error } => format!("Falha no certificado da origem\n{error}"),
202                Self::SourceKey { error } => format!("Falha na chave privada da origem\n{error}"),
203                Self::DestinationCert { error } =>
204                    format!("Falha no certificado do destino\n{error}"),
205                Self::ReadContent { error, .. } =>
206                    format!("Falha ao ler dados a serem criptografados\n{error}"),
207                Self::Encode { error, .. } => format!("Falha no encode dos dados UTF-8\n{error}"),
208                Self::Compress { error, .. } => format!("Falha na compactação do arquivo\n{error}"),
209                Self::EncryptContent { error, .. } =>
210                    format!("Falha na criptografia do arquivo\n{error}"),
211                Self::EncryptSymmetricKey { error, .. } =>
212                    format!("Falha na criptografia da chave simétrica\n{error}"),
213                Self::FormatHeader { error, .. } =>
214                    format!("Erro ao formatar o cabeçalho de segurança\n{error}"),
215            }
216        )
217    }
218}
219
220#[derive(Debug)]
221pub struct Encrypter {
222    special_treatment: Option<header::SpecialTreatment>,
223    crypt: bool,
224    compressor: Compressors,
225    encoder: Encoders,
226}
227
228impl Default for Encrypter {
229    fn default() -> Self {
230        Self::new()
231    }
232}
233
234impl Encrypter {
235    pub fn new() -> Self {
236        Self {
237            special_treatment: None,
238            crypt: true,
239            compressor: Compressors::default(),
240            encoder: Encoders::default(),
241        }
242    }
243
244    pub fn set_special_treatment(&mut self, value: Option<header::SpecialTreatment>) {
245        self.special_treatment = value;
246    }
247
248    pub fn set_crypt(&mut self, value: bool) {
249        self.crypt = value;
250    }
251
252    pub fn set_compressor(&mut self, value: Compressors) {
253        self.compressor = value;
254    }
255
256    pub fn set_encoder(&mut self, value: Encoders) {
257        self.encoder = value;
258    }
259
260    pub fn encrypt<R: io::Read>(
261        &self,
262        src_cert: &[u8],
263        src_key: &[u8],
264        dst_cert: &[u8],
265        file: &mut R,
266    ) -> Result<EncryptResult, EncryptError> {
267        let (src_cert, src_cert_key_type, src_cert_key) =
268            load_cert_and_key(src_cert).map_err(|error| EncryptError::SourceCert { error })?;
269        let src_key = load_key(src_key).map_err(|error| EncryptError::SourceKey { error })?;
270
271        let (dst_cert, dst_cert_key_type, dst_cert_key) =
272            load_cert_and_key(dst_cert).map_err(|error| EncryptError::DestinationCert { error })?;
273
274        let cert_error = if !src_key.check_public_key(&src_cert_key) {
275            Some(CertError::MismatchSourceCertAndKey)
276        } else {
277            None
278        };
279
280        let mut data = Vec::new();
281        file.read_to_end(&mut data)
282            .map_err(|error| EncryptError::ReadContent {
283                error: error.to_string(),
284                cert_error: cert_error.clone(),
285            })?;
286        let data = self
287            .encoder
288            .init()
289            .encode(&data)
290            .map_err(|error| EncryptError::Encode {
291                error,
292                cert_error: cert_error.clone(),
293            })?;
294        let data =
295            self.compressor
296                .init()
297                .compress(&data)
298                .map_err(|error| EncryptError::Compress {
299                    error,
300                    cert_error: cert_error.clone(),
301                })?;
302
303        let (cipher_sym_key, cipher_data) = if self.crypt {
304            let aes = Aes256::generate_new_key();
305            let cipher_data = aes
306                .encrypt(&data)
307                .map_err(|error| EncryptError::EncryptContent {
308                    error,
309                    cert_error: cert_error.clone(),
310                })?;
311            let cipher_sym_key = dst_cert_key.encrypt(&aes.export_key()).map_err(|error| {
312                EncryptError::EncryptSymmetricKey {
313                    error,
314                    cert_error: cert_error.clone(),
315                }
316            })?;
317            (cipher_sym_key, cipher_data)
318        } else {
319            ([0; 256].into(), data.clone())
320        };
321        let sign = src_key.sign(&data);
322
323        let special_treatment = match &self.special_treatment {
324            Some(value) => value.clone(),
325            None => match self.compressor {
326                Compressors::Plain => header::SpecialTreatment::NotCompress,
327                _ => header::SpecialTreatment::Compress,
328            },
329        };
330
331        let header = header::Header {
332            len: header::HeaderLen::Default,
333            version: header::ProtocolVersion::Version3,
334            error: header::ErrorCode::NoError,
335            special_treatment,
336            reserved: header::Reserved::NoValue,
337            dst_key_algo: dst_cert_key_type,
338            sym_key_algo: header::SymmetricKeyAlgo::Aes,
339            src_key_algo: src_cert_key_type,
340            hash_algo: header::HashAlgo::SHA256,
341            dst_pc_cert: dst_cert.issuer(),
342            dst_cert_serial: dst_cert.serial(),
343            src_pc_cert: src_cert.issuer(),
344            src_cert_serial: src_cert.serial(),
345            buffer_sym_key: cipher_sym_key
346                .try_into()
347                .map_err(|_| EncryptError::FormatHeader {
348                    error: "Tamanho da chave simétrica incorreto".to_string(),
349                    cert_error: cert_error.clone(),
350                })?,
351            buffer_hash: sign.try_into().map_err(|_| EncryptError::FormatHeader {
352                error: "Tamanho da assinatura incorreto".to_string(),
353                cert_error: cert_error.clone(),
354            })?,
355        };
356
357        let mut output = header.to_bytes();
358        output.extend(cipher_data);
359        Ok(EncryptResult {
360            header,
361            cert_error,
362            data: output,
363        })
364    }
365}
366
367// Decrypt
368
369#[derive(Debug)]
370pub struct DecryptResult {
371    header: header::Header,
372    cert_error: Option<CertError>,
373    signature_error: Option<SignatureError>,
374    data: Vec<u8>,
375}
376
377impl DecryptResult {
378    pub fn new(
379        header: header::Header,
380        cert_error: Option<CertError>,
381        signature_error: Option<SignatureError>,
382        data: Vec<u8>,
383    ) -> Self {
384        Self {
385            header,
386            cert_error,
387            signature_error,
388            data,
389        }
390    }
391
392    pub fn header(&self) -> &header::Header {
393        &self.header
394    }
395
396    pub fn is_encrypted_content(&self) -> bool {
397        self.header.is_encrypted_content()
398    }
399
400    pub fn is_compressed_content(&self) -> bool {
401        self.header.is_compressed_content()
402    }
403
404    pub fn is_valid_cert(&self) -> Result<(), CertError> {
405        match &self.cert_error {
406            None => Ok(()),
407            Some(error) => Err(error.clone()),
408        }
409    }
410
411    pub fn is_valid_signature(&self) -> Result<(), SignatureError> {
412        match &self.signature_error {
413            None => Ok(()),
414            Some(error) => Err(error.clone()),
415        }
416    }
417
418    pub fn data(&self) -> &Vec<u8> {
419        &self.data
420    }
421}
422
423#[derive(Debug, PartialEq, Eq)]
424pub enum DecryptError {
425    SourceCert {
426        error: String,
427    },
428    DestinationCert {
429        error: String,
430    },
431    DestinationKey {
432        error: String,
433    },
434    ReadHeader {
435        error: String,
436    },
437    ReadContent {
438        error: String,
439        header: header::Header,
440        cert_error: Option<CertError>,
441    },
442    DecryptSymmetricKey {
443        error: String,
444        header: header::Header,
445        cert_error: Option<CertError>,
446    },
447    DecryptContent {
448        error: String,
449        header: header::Header,
450        cert_error: Option<CertError>,
451    },
452    Decompress {
453        error: String,
454        header: header::Header,
455        cert_error: Option<CertError>,
456        signature_error: Option<SignatureError>,
457        data: Vec<u8>,
458    },
459    Decode {
460        error: String,
461        header: header::Header,
462        cert_error: Option<CertError>,
463        signature_error: Option<SignatureError>,
464        data: Vec<u8>,
465    },
466}
467
468impl fmt::Display for DecryptError {
469    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
470        write!(
471            f,
472            "{}",
473            match self {
474                Self::SourceCert { error } => format!("Falha no certificado da origem\n{error}"),
475                Self::DestinationCert { error } =>
476                    format!("Falha no certificado do destino\n{error}"),
477                Self::DestinationKey { error } =>
478                    format!("Falha na chave privada do destino\n{error}"),
479                Self::ReadHeader { error } =>
480                    format!("Falha na leitura do cabelho de segurança\n{error}"),
481                Self::ReadContent { error, .. } =>
482                    format!("Falha ao ler dados a serem descriptografados\n{error}"),
483                Self::DecryptSymmetricKey { error, .. } =>
484                    format!("Falha ao descriptografar chave simétrica\n{error}"),
485                Self::DecryptContent { error, .. } =>
486                    format!("Falha ao descriptografar os dados\n{error}"),
487                Self::Decompress { error, .. } => format!("Falha na descompactação\n{error}"),
488                Self::Decode { error, .. } => format!("Falha no decode dos dados\n{error}"),
489            }
490        )
491    }
492}
493
494#[derive(Debug)]
495pub struct Decrypter {
496    decompress: bool,
497    decode: bool,
498}
499
500impl Default for Decrypter {
501    fn default() -> Self {
502        Self::new()
503    }
504}
505
506impl Decrypter {
507    pub fn new() -> Self {
508        Self {
509            decompress: true,
510            decode: true,
511        }
512    }
513
514    pub fn set_decompress(&mut self, value: bool) {
515        self.decompress = value;
516    }
517
518    pub fn set_decode(&mut self, value: bool) {
519        self.decode = value;
520    }
521
522    #[allow(clippy::result_large_err)]
523    pub fn decrypt<R: io::Read>(
524        &self,
525        src_cert: &[u8],
526        dst_cert: &[u8],
527        dst_key: &[u8],
528        file: &mut R,
529    ) -> Result<DecryptResult, DecryptError> {
530        let (src_cert, src_cert_key_type, src_cert_key) =
531            load_cert_and_key(src_cert).map_err(|error| DecryptError::SourceCert { error })?;
532
533        let (dst_cert, dst_cert_key_type, dst_cert_key) =
534            load_cert_and_key(dst_cert).map_err(|error| DecryptError::DestinationCert { error })?;
535        let dst_key = load_key(dst_key).map_err(|error| DecryptError::DestinationKey { error })?;
536
537        let header =
538            header::Header::read_from_file(file).map_err(|error| DecryptError::ReadHeader {
539                error: error.to_string(),
540            })?;
541
542        let cert_error = if !dst_key.check_public_key(&dst_cert_key) {
543            Some(CertError::MismatchDestinationCertAndKey)
544        } else if header.src_cert_serial != src_cert.serial() {
545            Some(CertError::MismatchSourceCert)
546        } else if header.src_pc_cert != src_cert.issuer() {
547            Some(CertError::MismatchSourceIssuer)
548        } else if header.src_key_algo != src_cert_key_type {
549            Some(CertError::MismatchSourceKeyAlgo)
550        } else if header.dst_cert_serial != dst_cert.serial() {
551            Some(CertError::MismatchDestinationCert)
552        } else if header.dst_pc_cert != dst_cert.issuer() {
553            Some(CertError::MismatchDestinationIssuer)
554        } else if header.dst_key_algo != dst_cert_key_type {
555            Some(CertError::MismatchDestinationKeyAlgo)
556        } else {
557            None
558        };
559
560        let mut data = Vec::new();
561        file.read_to_end(&mut data)
562            .map_err(|error| DecryptError::ReadContent {
563                error: error.to_string(),
564                header: header.clone(),
565                cert_error: cert_error.clone(),
566            })?;
567
568        let plain_data = if header.is_encrypted_content() {
569            let sym_key = dst_key
570                .decrypt(&header.buffer_sym_key.value())
571                .map_err(|error| DecryptError::DecryptSymmetricKey {
572                    error,
573                    header: header.clone(),
574                    cert_error: cert_error.clone(),
575                })?;
576            let aes = Aes256::new(&sym_key);
577            aes.decrypt(&data)
578                .map_err(|error| DecryptError::DecryptContent {
579                    error,
580                    header: header.clone(),
581                    cert_error: cert_error.clone(),
582                })?
583        } else {
584            data
585        };
586
587        let signature_error = src_cert_key
588            .verify(&plain_data, &header.buffer_hash.value())
589            .map_err(|error| SignatureError::Invalid { error })
590            .err();
591
592        let plain_data = if header.is_compressed_content() && self.decompress {
593            Compressors::try_decompress(&plain_data).map_err(|error| DecryptError::Decompress {
594                error,
595                header: header.clone(),
596                cert_error: cert_error.clone(),
597                signature_error: signature_error.clone(),
598                data: plain_data,
599            })?
600        } else {
601            plain_data
602        };
603        let plain_data = {
604            let decoder = match self.decode {
605                true => Encoders::default(),
606                false => Encoders::Plain,
607            };
608            decoder
609                .init()
610                .decode(&plain_data)
611                .map_err(|error| DecryptError::Decode {
612                    error,
613                    header: header.clone(),
614                    cert_error: cert_error.clone(),
615                    signature_error: signature_error.clone(),
616                    data: plain_data,
617                })?
618        };
619
620        Ok(DecryptResult {
621            header,
622            cert_error,
623            signature_error,
624            data: plain_data,
625        })
626    }
627}