1use std::convert::TryFrom;
7use std::convert::TryInto;
8use std::fmt;
9
10use nom::{bytes::complete as bytes, combinator, sequence};
11
12use crate::ocard::data::{Fingerprint, KeySet};
13use crate::Error;
14
15impl From<[u8; 20]> for Fingerprint {
16 fn from(data: [u8; 20]) -> Self {
17 Self(data)
18 }
19}
20
21impl TryFrom<&[u8]> for Fingerprint {
22 type Error = Error;
23
24 fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
25 log::trace!("Fingerprint from input: {:x?}, len {}", input, input.len());
26
27 if input.len() == 20 {
28 #[allow(clippy::expect_used)]
29 let array: [u8; 20] = input.try_into().expect("checked");
30 Ok(array.into())
31 } else {
32 Err(Error::ParseError(format!(
33 "Unexpected fingerprint length {}",
34 input.len()
35 )))
36 }
37 }
38}
39
40impl Fingerprint {
41 pub fn as_bytes(&self) -> &[u8] {
42 &self.0
43 }
44}
45
46impl fmt::Display for Fingerprint {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 write!(f, "{self:X}")
49 }
50}
51
52impl fmt::UpperHex for Fingerprint {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 for b in &self.0 {
55 write!(f, "{b:02X}")?;
56 }
57 Ok(())
58 }
59}
60
61impl fmt::Debug for Fingerprint {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 f.debug_tuple("Fingerprint")
64 .field(&self.to_string())
65 .finish()
66 }
67}
68
69fn fingerprint(input: &[u8]) -> nom::IResult<&[u8], Option<Fingerprint>> {
70 combinator::map(bytes::take(20u8), |i: &[u8]| {
71 if i.iter().any(|&c| c > 0) {
72 #[allow(clippy::expect_used)]
74 let i: [u8; 20] = i.try_into().expect("20 taken");
75 Some(i.into())
76 } else {
77 None
78 }
79 })(input)
80}
81
82fn fingerprints(input: &[u8]) -> nom::IResult<&[u8], KeySet<Fingerprint>> {
83 combinator::into(sequence::tuple((fingerprint, fingerprint, fingerprint)))(input)
84}
85
86impl TryFrom<&[u8]> for KeySet<Fingerprint> {
87 type Error = Error;
88
89 fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
90 log::trace!("Fingerprint from input: {:x?}, len {}", input, input.len());
91
92 self::fingerprints(input)
95 .map(|res| res.1)
96 .map_err(|_err| Error::ParseError("Parsing failed".into()))
97 }
98}
99
100#[cfg(test)]
101mod test {
102 use super::*;
103
104 #[test]
105 fn test() {
106 let data3 = [
107 0xb7, 0xcd, 0x9f, 0x76, 0x37, 0x1e, 0x7, 0x7f, 0x76, 0x1c, 0x82, 0x65, 0x55, 0x54,
108 0x3e, 0x6d, 0x65, 0x6d, 0x1d, 0x80, 0x62, 0xd7, 0x34, 0x22, 0x65, 0xd2, 0xef, 0x33,
109 0x64, 0xe3, 0x79, 0x52, 0xd9, 0x5e, 0x94, 0x20, 0x5f, 0x4c, 0xce, 0x8b, 0x3f, 0x9,
110 0x7a, 0xf2, 0xfd, 0x76, 0xa5, 0xa7, 0x57, 0x9b, 0x51, 0x1f, 0xf, 0x44, 0x9a, 0x25,
111 0x80, 0x2d, 0xb2, 0xb8,
112 ];
113
114 let fp_set: KeySet<Fingerprint> = (&data3[..])
115 .try_into()
116 .expect("failed to parse fingerprint set");
117
118 assert_eq!(
119 format!("{}", fp_set.signature().unwrap()),
120 "B7CD9F76371E077F761C826555543E6D656D1D80"
121 );
122 assert_eq!(
123 format!("{}", fp_set.decryption().unwrap()),
124 "62D7342265D2EF3364E37952D95E94205F4CCE8B"
125 );
126 assert_eq!(
127 format!("{}", fp_set.authentication().unwrap()),
128 "3F097AF2FD76A5A7579B511F0F449A25802DB2B8"
129 );
130
131 let data1 = [
132 0xb7, 0xcd, 0x9f, 0x76, 0x37, 0x1e, 0x7, 0x7f, 0x76, 0x1c, 0x82, 0x65, 0x55, 0x54,
133 0x3e, 0x6d, 0x65, 0x6d, 0x1d, 0x80,
134 ];
135
136 let fp = Fingerprint::try_from(&data1[..]).expect("failed to parse fingerprint");
137
138 assert_eq!(format!("{fp}"), "B7CD9F76371E077F761C826555543E6D656D1D80");
139 }
140}