Skip to main content

rsfn_file/header/
mod.rs

1use std::{fmt, io};
2
3pub use self::fields::{
4    AsymmetricKeyAlgo, Buffer, CertSerial, ErrorCode, HashAlgo, HeaderLen, NullableBuffer, PcCert,
5    ProtocolVersion, Reserved, SpecialTreatment, SymmetricKeyAlgo,
6};
7
8mod fields;
9
10/// Cabeçalho de segurança dos arquivos que trafegam na RSFN.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct Header {
13    /// C01 Tamanho total do Cabeçalho.
14    pub len: HeaderLen,
15    /// C02 Versão do Protocolo de Segurança.
16    pub version: ProtocolVersion,
17    /// C03 Código de erro.
18    pub error: ErrorCode,
19    /// C04 Indicação de tratamento especial.
20    pub special_treatment: SpecialTreatment,
21    /// C05 Reservado para uso futuro.
22    pub reserved: Reserved,
23    /// C06 Algoritmo da chave assimétrica do destino.
24    pub dst_key_algo: AsymmetricKeyAlgo,
25    /// C07 Algoritmo da chave simétrica.
26    pub sym_key_algo: SymmetricKeyAlgo,
27    /// C08 Algoritmo da chave assimétrica local.
28    pub src_key_algo: AsymmetricKeyAlgo,
29    /// C09 Algoritmo de "hash".
30    pub hash_algo: HashAlgo,
31    /// C10 PC do certificado digital do destino.
32    pub dst_pc_cert: PcCert,
33    /// C11 Série do certificado digital do destino.
34    pub dst_cert_serial: CertSerial,
35    /// C12 PC do certificado digital da Instituição.
36    pub src_pc_cert: PcCert,
37    /// C13 Série do certificado digital da Instituição.
38    pub src_cert_serial: CertSerial,
39    /// C14 Buffer de criptografia da chave simétrica.
40    pub buffer_sym_key: NullableBuffer,
41    /// C15 Buffer do criptograma de autenticação.
42    pub buffer_hash: Buffer,
43}
44
45impl Header {
46    pub fn read_from_file<R: io::Read>(file: &mut R) -> io::Result<Self> {
47        let mut c01 = [0; 2];
48        file.read_exact(&mut c01)?;
49        let mut c02 = [0; 1];
50        file.read_exact(&mut c02)?;
51        let mut c03 = [0; 1];
52        file.read_exact(&mut c03)?;
53        let mut c04 = [0; 1];
54        file.read_exact(&mut c04)?;
55        let mut c05 = [0; 1];
56        file.read_exact(&mut c05)?;
57        let mut c06 = [0; 1];
58        file.read_exact(&mut c06)?;
59        let mut c07 = [0; 1];
60        file.read_exact(&mut c07)?;
61        let mut c08 = [0; 1];
62        file.read_exact(&mut c08)?;
63        let mut c09 = [0; 1];
64        file.read_exact(&mut c09)?;
65        let mut c10 = [0; 1];
66        file.read_exact(&mut c10)?;
67        let mut c11 = [0; 32];
68        file.read_exact(&mut c11)?;
69        let mut c12 = [0; 1];
70        file.read_exact(&mut c12)?;
71        let mut c13 = [0; 32];
72        file.read_exact(&mut c13)?;
73        let mut c14 = [0; 256];
74        file.read_exact(&mut c14)?;
75        let mut c15 = [0; 256];
76        file.read_exact(&mut c15)?;
77
78        Ok(Self {
79            len: c01.into(),
80            version: c02.into(),
81            error: c03.into(),
82            special_treatment: c04.into(),
83            reserved: c05.into(),
84            dst_key_algo: c06.into(),
85            sym_key_algo: c07.into(),
86            src_key_algo: c08.into(),
87            hash_algo: c09.into(),
88            dst_pc_cert: c10.into(),
89            dst_cert_serial: c11.into(),
90            src_pc_cert: c12.into(),
91            src_cert_serial: c13.into(),
92            buffer_sym_key: c14.into(),
93            buffer_hash: c15.into(),
94        })
95    }
96
97    pub fn is_valid(&self) -> Result<(), String> {
98        let errors: Vec<_> = [
99            (self.len.is_valid(), "C01 inválido"),
100            (self.version.is_valid(), "C02 inválido"),
101            (self.error.is_valid(), "C03 inválido"),
102            (self.special_treatment.is_valid(), "C04 inválido"),
103            (self.reserved.is_valid(), "C05 inválido"),
104            (self.dst_key_algo.is_valid(), "C06 inválido"),
105            (self.sym_key_algo.is_valid(), "C07 inválido"),
106            (self.src_key_algo.is_valid(), "C08 inválido"),
107            (self.hash_algo.is_valid(), "C09 inválido"),
108            (self.dst_pc_cert.is_valid(), "C10 inválido"),
109            (self.dst_cert_serial.is_valid(), "C11 inválido"),
110            (self.src_pc_cert.is_valid(), "C12 inválido"),
111            (self.src_cert_serial.is_valid(), "C13 inválido"),
112            (self.buffer_sym_key.is_valid(), "C14 inválido"),
113            (self.buffer_hash.is_valid(), "C15 inválido"),
114        ]
115        .into_iter()
116        .filter_map(|(valid, error)| if valid { None } else { Some(error) })
117        .collect();
118
119        match errors.is_empty() {
120            true => Ok(()),
121            false => Err(errors.join(", ")),
122        }
123    }
124
125    pub fn is_encrypted_content(&self) -> bool {
126        match self.special_treatment {
127            SpecialTreatment::NotCryptBroadcast
128            | SpecialTreatment::NotCrypt
129            | SpecialTreatment::NotCompressAndNotCrypt
130            | SpecialTreatment::CompressWithoutCrypt => false,
131            _ => matches!(self.buffer_sym_key, NullableBuffer::Some(_)),
132        }
133    }
134
135    pub fn is_compressed_content(&self) -> bool {
136        matches!(
137            self.special_treatment,
138            SpecialTreatment::Compress | SpecialTreatment::CompressWithoutCrypt
139        )
140    }
141
142    pub fn to_bytes(&self) -> Vec<u8> {
143        let mut data = Vec::new();
144        self.len.to_bytes().iter().for_each(|&byte| data.push(byte));
145        self.version
146            .to_bytes()
147            .iter()
148            .for_each(|&byte| data.push(byte));
149        self.error
150            .to_bytes()
151            .iter()
152            .for_each(|&byte| data.push(byte));
153        self.special_treatment
154            .to_bytes()
155            .iter()
156            .for_each(|&byte| data.push(byte));
157        self.reserved
158            .to_bytes()
159            .iter()
160            .for_each(|&byte| data.push(byte));
161        self.dst_key_algo
162            .to_bytes()
163            .iter()
164            .for_each(|&byte| data.push(byte));
165        self.sym_key_algo
166            .to_bytes()
167            .iter()
168            .for_each(|&byte| data.push(byte));
169        self.src_key_algo
170            .to_bytes()
171            .iter()
172            .for_each(|&byte| data.push(byte));
173        self.hash_algo
174            .to_bytes()
175            .iter()
176            .for_each(|&byte| data.push(byte));
177        self.dst_pc_cert
178            .to_bytes()
179            .iter()
180            .for_each(|&byte| data.push(byte));
181        self.dst_cert_serial
182            .to_bytes()
183            .iter()
184            .for_each(|&byte| data.push(byte));
185        self.src_pc_cert
186            .to_bytes()
187            .iter()
188            .for_each(|&byte| data.push(byte));
189        self.src_cert_serial
190            .to_bytes()
191            .iter()
192            .for_each(|&byte| data.push(byte));
193        self.buffer_sym_key
194            .to_bytes()
195            .iter()
196            .for_each(|&byte| data.push(byte));
197        self.buffer_hash
198            .to_bytes()
199            .iter()
200            .for_each(|&byte| data.push(byte));
201        data
202    }
203}
204
205impl fmt::Display for Header {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        writeln!(
208            f,
209            "================================ BEGIN HEADER ================================"
210        )?;
211        writeln!(f, "{:45}: {}", "C01 Tamanho do cabeçalho", self.len)?;
212        writeln!(f, "{:45}: {}", "C02 Versão do protocolo", self.version)?;
213        writeln!(f, "{:45}: {}", "C03 Código de erro", self.error)?;
214        writeln!(
215            f,
216            "{:45}: {}",
217            "C04 Tratamento especial", self.special_treatment
218        )?;
219        writeln!(f, "{:45}: {}", "C05 Reservado", self.reserved)?;
220        writeln!(
221            f,
222            "{:45}: {}",
223            "C06 Algoritmo da chave assimétrica do destino", self.dst_key_algo
224        )?;
225        writeln!(
226            f,
227            "{:45}: {}",
228            "C07 Algoritmo da chave simétrica", self.sym_key_algo
229        )?;
230        writeln!(
231            f,
232            "{:45}: {}",
233            "C08 Algoritmo da chave assimétrica local", self.src_key_algo
234        )?;
235        writeln!(f, "{:45}: {}", "C09 Algoritmo de hash", self.hash_algo)?;
236        writeln!(
237            f,
238            "{:45}: {}",
239            "C10 PC do certificado do destino", self.dst_pc_cert
240        )?;
241        writeln!(
242            f,
243            "{:45}: {}",
244            "C11 Série do certificado do destino", self.dst_cert_serial
245        )?;
246        writeln!(
247            f,
248            "{:45}: {}",
249            "C12 PC do certificado da instituição", self.src_pc_cert
250        )?;
251        writeln!(
252            f,
253            "{:45}: {}",
254            "C13 Série do certificado da instituição", self.src_cert_serial
255        )?;
256        writeln!(
257            f,
258            "{:45}: {}",
259            "C14 Buffer da chave simétrica", self.buffer_sym_key
260        )?;
261        writeln!(
262            f,
263            "{:45}: {}",
264            "C15 Buffer da autenticação da mensagem", self.buffer_hash
265        )?;
266        write!(
267            f,
268            "================================ END HEADER ================================"
269        )
270    }
271}
272
273#[cfg(test)]
274mod tests {
275    use std::io::Cursor;
276
277    use super::*;
278
279    #[test]
280    fn value_plain() {
281        let sut = Header {
282            len: HeaderLen::Default,
283            version: ProtocolVersion::Plain,
284            error: ErrorCode::NoError,
285            special_treatment: SpecialTreatment::Normal,
286            reserved: Reserved::NoValue,
287            dst_key_algo: AsymmetricKeyAlgo::Unknown(0),
288            sym_key_algo: SymmetricKeyAlgo::Unknown(0),
289            src_key_algo: AsymmetricKeyAlgo::Unknown(0),
290            hash_algo: HashAlgo::Unknown(0),
291            dst_pc_cert: PcCert::Unknown(0),
292            dst_cert_serial: [0; 32].into(),
293            src_pc_cert: PcCert::Unknown(0),
294            src_cert_serial: [0; 32].into(),
295            buffer_sym_key: [0; 256].into(),
296            buffer_hash: [0; 256].into(),
297        };
298
299        assert_eq!(sut.to_string(), "================================ BEGIN HEADER ================================
300C01 Tamanho do cabeçalho                     : 0x024c [588]
301C02 Versão do protocolo                      : 0x00 [Em claro]
302C03 Código de erro                           : 0x00 [Sem erros]
303C04 Tratamento especial                      : 0x00 [Uso normal]
304C05 Reservado                                : 0x00 [-]
305C06 Algoritmo da chave assimétrica do destino: 0x00 [DESCONHECIDO]
306C07 Algoritmo da chave simétrica             : 0x00 [DESCONHECIDO]
307C08 Algoritmo da chave assimétrica local     : 0x00 [DESCONHECIDO]
308C09 Algoritmo de hash                        : 0x00 [DESCONHECIDO]
309C10 PC do certificado do destino             : 0x00 [DESCONHECIDO]
310C11 Série do certificado do destino          : 0x0000000000000000000000000000000000000000000000000000000000000000 [INVÁLIDO]
311C12 PC do certificado da instituição         : 0x00 [DESCONHECIDO]
312C13 Série do certificado da instituição      : 0x0000000000000000000000000000000000000000000000000000000000000000 [INVÁLIDO]
313C14 Buffer da chave simétrica                : VAZIO
314C15 Buffer da autenticação da mensagem       : blob [len=0]
315================================ END HEADER ================================");
316    }
317
318    #[test]
319    fn value_version3() {
320        let sut = Header {
321            len: HeaderLen::Default,
322            version: ProtocolVersion::Version3,
323            error: ErrorCode::NoError,
324            special_treatment: SpecialTreatment::Normal,
325            reserved: Reserved::NoValue,
326            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
327            sym_key_algo: SymmetricKeyAlgo::Aes,
328            src_key_algo: AsymmetricKeyAlgo::RSA2048,
329            hash_algo: HashAlgo::SHA256,
330            dst_pc_cert: PcCert::PessoasFisicas,
331            dst_cert_serial: [0; 32].into(),
332            src_pc_cert: PcCert::PessoasFisicas,
333            src_cert_serial: [0; 32].into(),
334            buffer_sym_key: [1; 256].into(),
335            buffer_hash: [1; 256].into(),
336        };
337
338        assert_eq!(sut.to_string(), "================================ BEGIN HEADER ================================
339C01 Tamanho do cabeçalho                     : 0x024c [588]
340C02 Versão do protocolo                      : 0x03 [Terceira versão]
341C03 Código de erro                           : 0x00 [Sem erros]
342C04 Tratamento especial                      : 0x00 [Uso normal]
343C05 Reservado                                : 0x00 [-]
344C06 Algoritmo da chave assimétrica do destino: 0x02 [RSA com 2048 bits]
345C07 Algoritmo da chave simétrica             : 0x02 [AES com 256 bits]
346C08 Algoritmo da chave assimétrica local     : 0x02 [RSA com 2048 bits]
347C09 Algoritmo de hash                        : 0x03 [SHA-256]
348C10 PC do certificado do destino             : 0x03 [Pessoas Físicas]
349C11 Série do certificado do destino          : 0x0000000000000000000000000000000000000000000000000000000000000000 [INVÁLIDO]
350C12 PC do certificado da instituição         : 0x03 [Pessoas Físicas]
351C13 Série do certificado da instituição      : 0x0000000000000000000000000000000000000000000000000000000000000000 [INVÁLIDO]
352C14 Buffer da chave simétrica                : blob [len=256]
353C15 Buffer da autenticação da mensagem       : blob [len=256]
354================================ END HEADER ================================");
355    }
356
357    #[test]
358    fn value_invalid_len() {
359        let sut = Header {
360            len: HeaderLen::Unknown(0),
361            version: ProtocolVersion::Version3,
362            error: ErrorCode::NoError,
363            special_treatment: SpecialTreatment::Normal,
364            reserved: Reserved::NoValue,
365            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
366            sym_key_algo: SymmetricKeyAlgo::Aes,
367            src_key_algo: AsymmetricKeyAlgo::RSA2048,
368            hash_algo: HashAlgo::SHA256,
369            dst_pc_cert: PcCert::PessoasFisicas,
370            dst_cert_serial: [b'1'; 32].into(),
371            src_pc_cert: PcCert::PessoasFisicas,
372            src_cert_serial: [b'1'; 32].into(),
373            buffer_sym_key: [1; 256].into(),
374            buffer_hash: [1; 256].into(),
375        };
376
377        assert_eq!(sut.is_valid().unwrap_err(), "C01 inválido");
378    }
379
380    #[test]
381    fn value_invalid_version() {
382        let sut = Header {
383            len: HeaderLen::Default,
384            version: ProtocolVersion::Unknown(1),
385            error: ErrorCode::NoError,
386            special_treatment: SpecialTreatment::Normal,
387            reserved: Reserved::NoValue,
388            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
389            sym_key_algo: SymmetricKeyAlgo::Aes,
390            src_key_algo: AsymmetricKeyAlgo::RSA2048,
391            hash_algo: HashAlgo::SHA256,
392            dst_pc_cert: PcCert::PessoasFisicas,
393            dst_cert_serial: [b'1'; 32].into(),
394            src_pc_cert: PcCert::PessoasFisicas,
395            src_cert_serial: [b'1'; 32].into(),
396            buffer_sym_key: [1; 256].into(),
397            buffer_hash: [1; 256].into(),
398        };
399
400        assert_eq!(sut.is_valid().unwrap_err(), "C02 inválido");
401    }
402
403    #[test]
404    fn value_invalid_error() {
405        let sut = Header {
406            len: HeaderLen::Default,
407            version: ProtocolVersion::Version3,
408            error: ErrorCode::Unknown(1),
409            special_treatment: SpecialTreatment::Normal,
410            reserved: Reserved::NoValue,
411            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
412            sym_key_algo: SymmetricKeyAlgo::Aes,
413            src_key_algo: AsymmetricKeyAlgo::RSA2048,
414            hash_algo: HashAlgo::SHA256,
415            dst_pc_cert: PcCert::PessoasFisicas,
416            dst_cert_serial: [b'1'; 32].into(),
417            src_pc_cert: PcCert::PessoasFisicas,
418            src_cert_serial: [b'1'; 32].into(),
419            buffer_sym_key: [1; 256].into(),
420            buffer_hash: [1; 256].into(),
421        };
422
423        assert_eq!(sut.is_valid().unwrap_err(), "C03 inválido");
424    }
425
426    #[test]
427    fn value_invalid_special_treatment() {
428        let sut = Header {
429            len: HeaderLen::Default,
430            version: ProtocolVersion::Version3,
431            error: ErrorCode::NoError,
432            special_treatment: SpecialTreatment::Unknown(7),
433            reserved: Reserved::NoValue,
434            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
435            sym_key_algo: SymmetricKeyAlgo::Aes,
436            src_key_algo: AsymmetricKeyAlgo::RSA2048,
437            hash_algo: HashAlgo::SHA256,
438            dst_pc_cert: PcCert::PessoasFisicas,
439            dst_cert_serial: [b'1'; 32].into(),
440            src_pc_cert: PcCert::PessoasFisicas,
441            src_cert_serial: [b'1'; 32].into(),
442            buffer_sym_key: [1; 256].into(),
443            buffer_hash: [1; 256].into(),
444        };
445
446        assert_eq!(sut.is_valid().unwrap_err(), "C04 inválido");
447    }
448
449    #[test]
450    fn value_invalid_reserved() {
451        let sut = Header {
452            len: HeaderLen::Default,
453            version: ProtocolVersion::Version3,
454            error: ErrorCode::NoError,
455            special_treatment: SpecialTreatment::Normal,
456            reserved: Reserved::Unknown(1),
457            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
458            sym_key_algo: SymmetricKeyAlgo::Aes,
459            src_key_algo: AsymmetricKeyAlgo::RSA2048,
460            hash_algo: HashAlgo::SHA256,
461            dst_pc_cert: PcCert::PessoasFisicas,
462            dst_cert_serial: [b'1'; 32].into(),
463            src_pc_cert: PcCert::PessoasFisicas,
464            src_cert_serial: [b'1'; 32].into(),
465            buffer_sym_key: [1; 256].into(),
466            buffer_hash: [1; 256].into(),
467        };
468
469        assert_eq!(sut.is_valid().unwrap_err(), "C05 inválido");
470    }
471
472    #[test]
473    fn value_invalid_dst_key_algo() {
474        let sut = Header {
475            len: HeaderLen::Default,
476            version: ProtocolVersion::Version3,
477            error: ErrorCode::NoError,
478            special_treatment: SpecialTreatment::Normal,
479            reserved: Reserved::NoValue,
480            dst_key_algo: AsymmetricKeyAlgo::Unknown(0),
481            sym_key_algo: SymmetricKeyAlgo::Aes,
482            src_key_algo: AsymmetricKeyAlgo::RSA2048,
483            hash_algo: HashAlgo::SHA256,
484            dst_pc_cert: PcCert::PessoasFisicas,
485            dst_cert_serial: [b'1'; 32].into(),
486            src_pc_cert: PcCert::PessoasFisicas,
487            src_cert_serial: [b'1'; 32].into(),
488            buffer_sym_key: [1; 256].into(),
489            buffer_hash: [1; 256].into(),
490        };
491
492        assert_eq!(sut.is_valid().unwrap_err(), "C06 inválido");
493    }
494
495    #[test]
496    fn value_invalid_sym_key_algo() {
497        let sut = Header {
498            len: HeaderLen::Default,
499            version: ProtocolVersion::Version3,
500            error: ErrorCode::NoError,
501            special_treatment: SpecialTreatment::Normal,
502            reserved: Reserved::NoValue,
503            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
504            sym_key_algo: SymmetricKeyAlgo::Unknown(0),
505            src_key_algo: AsymmetricKeyAlgo::RSA2048,
506            hash_algo: HashAlgo::SHA256,
507            dst_pc_cert: PcCert::PessoasFisicas,
508            dst_cert_serial: [b'1'; 32].into(),
509            src_pc_cert: PcCert::PessoasFisicas,
510            src_cert_serial: [b'1'; 32].into(),
511            buffer_sym_key: [1; 256].into(),
512            buffer_hash: [1; 256].into(),
513        };
514
515        assert_eq!(sut.is_valid().unwrap_err(), "C07 inválido");
516    }
517
518    #[test]
519    fn value_invalid_src_key_algo() {
520        let sut = Header {
521            len: HeaderLen::Default,
522            version: ProtocolVersion::Version3,
523            error: ErrorCode::NoError,
524            special_treatment: SpecialTreatment::Normal,
525            reserved: Reserved::NoValue,
526            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
527            sym_key_algo: SymmetricKeyAlgo::Aes,
528            src_key_algo: AsymmetricKeyAlgo::Unknown(0),
529            hash_algo: HashAlgo::SHA256,
530            dst_pc_cert: PcCert::PessoasFisicas,
531            dst_cert_serial: [b'1'; 32].into(),
532            src_pc_cert: PcCert::PessoasFisicas,
533            src_cert_serial: [b'1'; 32].into(),
534            buffer_sym_key: [1; 256].into(),
535            buffer_hash: [1; 256].into(),
536        };
537
538        assert_eq!(sut.is_valid().unwrap_err(), "C08 inválido");
539    }
540
541    #[test]
542    fn value_invalid_hash_algo() {
543        let sut = Header {
544            len: HeaderLen::Default,
545            version: ProtocolVersion::Version3,
546            error: ErrorCode::NoError,
547            special_treatment: SpecialTreatment::Normal,
548            reserved: Reserved::NoValue,
549            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
550            sym_key_algo: SymmetricKeyAlgo::Aes,
551            src_key_algo: AsymmetricKeyAlgo::RSA2048,
552            hash_algo: HashAlgo::Unknown(0),
553            dst_pc_cert: PcCert::PessoasFisicas,
554            dst_cert_serial: [b'1'; 32].into(),
555            src_pc_cert: PcCert::PessoasFisicas,
556            src_cert_serial: [b'1'; 32].into(),
557            buffer_sym_key: [1; 256].into(),
558            buffer_hash: [1; 256].into(),
559        };
560
561        assert_eq!(sut.is_valid().unwrap_err(), "C09 inválido");
562    }
563
564    #[test]
565    fn value_invalid_dst_pc_cert() {
566        let sut = Header {
567            len: HeaderLen::Default,
568            version: ProtocolVersion::Version3,
569            error: ErrorCode::NoError,
570            special_treatment: SpecialTreatment::Normal,
571            reserved: Reserved::NoValue,
572            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
573            sym_key_algo: SymmetricKeyAlgo::Aes,
574            src_key_algo: AsymmetricKeyAlgo::RSA2048,
575            hash_algo: HashAlgo::SHA256,
576            dst_pc_cert: PcCert::Unknown(0),
577            dst_cert_serial: [b'1'; 32].into(),
578            src_pc_cert: PcCert::PessoasFisicas,
579            src_cert_serial: [b'1'; 32].into(),
580            buffer_sym_key: [1; 256].into(),
581            buffer_hash: [1; 256].into(),
582        };
583
584        assert_eq!(sut.is_valid().unwrap_err(), "C10 inválido");
585    }
586
587    #[test]
588    fn value_invalid_dst_cert_serial() {
589        let sut = Header {
590            len: HeaderLen::Default,
591            version: ProtocolVersion::Version3,
592            error: ErrorCode::NoError,
593            special_treatment: SpecialTreatment::Normal,
594            reserved: Reserved::NoValue,
595            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
596            sym_key_algo: SymmetricKeyAlgo::Aes,
597            src_key_algo: AsymmetricKeyAlgo::RSA2048,
598            hash_algo: HashAlgo::SHA256,
599            dst_pc_cert: PcCert::PessoasFisicas,
600            dst_cert_serial: [0; 32].into(),
601            src_pc_cert: PcCert::PessoasFisicas,
602            src_cert_serial: [b'1'; 32].into(),
603            buffer_sym_key: [1; 256].into(),
604            buffer_hash: [1; 256].into(),
605        };
606
607        assert_eq!(sut.is_valid().unwrap_err(), "C11 inválido");
608    }
609
610    #[test]
611    fn value_invalid_src_pc_cert() {
612        let sut = Header {
613            len: HeaderLen::Default,
614            version: ProtocolVersion::Version3,
615            error: ErrorCode::NoError,
616            special_treatment: SpecialTreatment::Normal,
617            reserved: Reserved::NoValue,
618            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
619            sym_key_algo: SymmetricKeyAlgo::Aes,
620            src_key_algo: AsymmetricKeyAlgo::RSA2048,
621            hash_algo: HashAlgo::SHA256,
622            dst_pc_cert: PcCert::PessoasFisicas,
623            dst_cert_serial: [b'1'; 32].into(),
624            src_pc_cert: PcCert::Unknown(0),
625            src_cert_serial: [b'1'; 32].into(),
626            buffer_sym_key: [1; 256].into(),
627            buffer_hash: [1; 256].into(),
628        };
629
630        assert_eq!(sut.is_valid().unwrap_err(), "C12 inválido");
631    }
632
633    #[test]
634    fn value_invalid_src_cert_serial() {
635        let sut = Header {
636            len: HeaderLen::Default,
637            version: ProtocolVersion::Version3,
638            error: ErrorCode::NoError,
639            special_treatment: SpecialTreatment::Normal,
640            reserved: Reserved::NoValue,
641            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
642            sym_key_algo: SymmetricKeyAlgo::Aes,
643            src_key_algo: AsymmetricKeyAlgo::RSA2048,
644            hash_algo: HashAlgo::SHA256,
645            dst_pc_cert: PcCert::PessoasFisicas,
646            dst_cert_serial: [b'1'; 32].into(),
647            src_pc_cert: PcCert::PessoasFisicas,
648            src_cert_serial: [0; 32].into(),
649            buffer_sym_key: [1; 256].into(),
650            buffer_hash: [1; 256].into(),
651        };
652
653        assert_eq!(sut.is_valid().unwrap_err(), "C13 inválido");
654    }
655
656    #[test]
657    fn value_invalid_buffer_hash() {
658        let sut = Header {
659            len: HeaderLen::Default,
660            version: ProtocolVersion::Version3,
661            error: ErrorCode::NoError,
662            special_treatment: SpecialTreatment::Normal,
663            reserved: Reserved::NoValue,
664            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
665            sym_key_algo: SymmetricKeyAlgo::Aes,
666            src_key_algo: AsymmetricKeyAlgo::RSA2048,
667            hash_algo: HashAlgo::SHA256,
668            dst_pc_cert: PcCert::PessoasFisicas,
669            dst_cert_serial: [b'1'; 32].into(),
670            src_pc_cert: PcCert::PessoasFisicas,
671            src_cert_serial: [b'1'; 32].into(),
672            buffer_sym_key: [1; 256].into(),
673            buffer_hash: [0; 256].into(),
674        };
675
676        assert_eq!(sut.is_valid().unwrap_err(), "C15 inválido");
677    }
678
679    #[test]
680    fn value_invalid_all_possible_fields() {
681        let sut = Header {
682            len: HeaderLen::Unknown(0),
683            version: ProtocolVersion::Unknown(1),
684            error: ErrorCode::Unknown(15),
685            special_treatment: SpecialTreatment::Unknown(7),
686            reserved: Reserved::Unknown(1),
687            dst_key_algo: AsymmetricKeyAlgo::Unknown(0),
688            sym_key_algo: SymmetricKeyAlgo::Unknown(0),
689            src_key_algo: AsymmetricKeyAlgo::Unknown(0),
690            hash_algo: HashAlgo::Unknown(0),
691            dst_pc_cert: PcCert::Unknown(0),
692            dst_cert_serial: [0; 32].into(),
693            src_pc_cert: PcCert::Unknown(0),
694            src_cert_serial: [0; 32].into(),
695            buffer_sym_key: [0; 256].into(),
696            buffer_hash: [0; 256].into(),
697        };
698
699        assert_eq!(
700            sut.is_valid().unwrap_err(),
701            (1..=15)
702                .filter(|&i| i != 14)
703                .map(|i| format!("C{i:02} inválido"))
704                .collect::<Vec<_>>()
705                .join(", ")
706        );
707    }
708
709    #[test]
710    fn is_encrypted_content() {
711        let tests = [
712            (SpecialTreatment::NotCryptBroadcast, [1; 256], false),
713            (SpecialTreatment::NotCrypt, [1; 256], false),
714            (SpecialTreatment::NotCompressAndNotCrypt, [1; 256], false),
715            (SpecialTreatment::CompressWithoutCrypt, [1; 256], false),
716            (SpecialTreatment::Normal, [0; 256], false),
717            (SpecialTreatment::Normal, [1; 256], true),
718        ];
719        for (special_treatment, buffer_sym_key, is_encrypted) in tests {
720            let header = Header {
721                len: HeaderLen::Default,
722                version: ProtocolVersion::Version3,
723                error: ErrorCode::NoError,
724                special_treatment,
725                reserved: Reserved::NoValue,
726                dst_key_algo: AsymmetricKeyAlgo::RSA2048,
727                sym_key_algo: SymmetricKeyAlgo::Aes,
728                src_key_algo: AsymmetricKeyAlgo::RSA2048,
729                hash_algo: HashAlgo::SHA256,
730                dst_pc_cert: PcCert::PessoasFisicas,
731                dst_cert_serial: [0; 32].into(),
732                src_pc_cert: PcCert::PessoasFisicas,
733                src_cert_serial: [0; 32].into(),
734                buffer_sym_key: buffer_sym_key.into(),
735                buffer_hash: [0; 256].into(),
736            };
737
738            assert_eq!(header.is_encrypted_content(), is_encrypted);
739        }
740    }
741
742    #[test]
743    fn is_compessed_content() {
744        let tests = [
745            (SpecialTreatment::Normal, false),
746            (SpecialTreatment::Compress, true),
747            (SpecialTreatment::CompressWithoutCrypt, true),
748        ];
749        for (special_treatment, is_compressed) in tests {
750            let header = Header {
751                len: HeaderLen::Default,
752                version: ProtocolVersion::Version3,
753                error: ErrorCode::NoError,
754                special_treatment,
755                reserved: Reserved::NoValue,
756                dst_key_algo: AsymmetricKeyAlgo::RSA2048,
757                sym_key_algo: SymmetricKeyAlgo::Aes,
758                src_key_algo: AsymmetricKeyAlgo::RSA2048,
759                hash_algo: HashAlgo::SHA256,
760                dst_pc_cert: PcCert::PessoasFisicas,
761                dst_cert_serial: [0; 32].into(),
762                src_pc_cert: PcCert::PessoasFisicas,
763                src_cert_serial: [0; 32].into(),
764                buffer_sym_key: [0; 256].into(),
765                buffer_hash: [0; 256].into(),
766            };
767
768            assert_eq!(header.is_compressed_content(), is_compressed);
769        }
770    }
771
772    #[test]
773    fn convert_to_bytes_and_read() {
774        let a = Header {
775            len: HeaderLen::Default,
776            version: ProtocolVersion::Plain,
777            error: ErrorCode::NoError,
778            special_treatment: SpecialTreatment::Normal,
779            reserved: Reserved::NoValue,
780            dst_key_algo: AsymmetricKeyAlgo::Unknown(0),
781            sym_key_algo: SymmetricKeyAlgo::Unknown(0),
782            src_key_algo: AsymmetricKeyAlgo::Unknown(0),
783            hash_algo: HashAlgo::Unknown(0),
784            dst_pc_cert: PcCert::Unknown(0),
785            dst_cert_serial: [0; 32].into(),
786            src_pc_cert: PcCert::Unknown(0),
787            src_cert_serial: [0; 32].into(),
788            buffer_sym_key: [0; 256].into(),
789            buffer_hash: [0; 256].into(),
790        };
791        let bytes = a.to_bytes();
792
793        assert_eq!(bytes.len(), HeaderLen::Default.value() as usize);
794
795        let mut file = Cursor::new(bytes);
796        let b = Header::read_from_file(&mut file).unwrap();
797
798        assert_eq!(a, b);
799    }
800
801    #[test]
802    fn write_read_header_version3() {
803        let a = Header {
804            len: HeaderLen::Default,
805            version: ProtocolVersion::Version3,
806            error: ErrorCode::NoError,
807            special_treatment: SpecialTreatment::Normal,
808            reserved: Reserved::NoValue,
809            dst_key_algo: AsymmetricKeyAlgo::RSA2048,
810            sym_key_algo: SymmetricKeyAlgo::Aes,
811            src_key_algo: AsymmetricKeyAlgo::RSA2048,
812            hash_algo: HashAlgo::SHA256,
813            dst_pc_cert: PcCert::PessoasFisicas,
814            dst_cert_serial: [0; 32].into(),
815            src_pc_cert: PcCert::PessoasFisicas,
816            src_cert_serial: [0; 32].into(),
817            buffer_sym_key: [0; 256].into(),
818            buffer_hash: [0; 256].into(),
819        };
820        let bytes = a.to_bytes();
821
822        assert_eq!(bytes.len(), HeaderLen::Default.value() as usize);
823
824        let mut file = Cursor::new(bytes);
825        let b = Header::read_from_file(&mut file).unwrap();
826
827        assert_eq!(a, b);
828    }
829}