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
117pub 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#[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#[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}