copernica_packets/
hbfi.rs

1use {
2    crate::{ PublicIdentity, PublicIdentityInterface },
3    copernica_common::{constants::*, u8_to_u64, u16_to_u8, u64_to_u8 },
4    anyhow::{Result, anyhow},
5    std::fmt,
6    core::hash::{Hash}
7};
8pub fn bloom_filter_index(
9    s: &str,
10) -> Result<BFI> {
11    use std::str;
12    use cryptoxide::digest::Digest as _;
13    let mut hash_orig = [0; 32];
14    let mut b = cryptoxide::blake2b::Blake2b::new(32);
15    b.input(&s.as_bytes());
16    b.result(&mut hash_orig);
17    let mut bloom_filter_index_array: BFI = BFI::new();
18    let mut count = 0;
19    for n in 0..BLOOM_FILTER_INDEX_ELEMENT_LENGTH {
20        let mut hash_derived = [0; 32];
21        let mut b = cryptoxide::blake2b::Blake2b::new(32);
22        let mut s: String = "".into();
23        for byte in hash_orig.iter() {
24            s.push_str(format!("{:x}", byte).as_str());
25        }
26        s.push_str(format!("{}", n).as_str());
27        b.input(&s.as_bytes());
28        b.result(&mut hash_derived);
29        s = "".into();
30        for byte in hash_derived.iter() {
31            s.push_str(format!("{:x}", byte).as_str());
32        }
33        let subs = s
34            .as_bytes()
35            .chunks(16)
36            .map(str::from_utf8)
37            .collect::<Result<Vec<&str>, _>>()?;
38        let mut index: u64 = 0;
39        for sub in subs {
40            let o = u64::from_str_radix(&sub, 16)?;
41            index = (index + o) % BLOOM_FILTER_LENGTH as u64;
42        }
43        bloom_filter_index_array.0[count] = index as u16;
44        count += 1;
45    }
46    Ok(bloom_filter_index_array)
47}
48#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
49pub struct BFI(pub [u16; BLOOM_FILTER_INDEX_ELEMENT_LENGTH]);
50impl BFI {
51    pub fn new() -> Self {
52        Self([0; BLOOM_FILTER_INDEX_ELEMENT_LENGTH as usize])
53    }
54    pub fn to_bytes(&self) -> [u8; BFI_BYTE_SIZE] {
55        let mut bbfi: [u8; BFI_BYTE_SIZE] = [0; BFI_BYTE_SIZE];
56        let mut count = 0;
57        for i in self.0.iter() {
58            let two_u8 = u16_to_u8(*i);
59            bbfi[count]   = two_u8[0];
60            bbfi[count+1] = two_u8[1];
61            count+=2;
62        }
63        bbfi
64    }
65    pub fn from_bytes(bbfi: [u8; BFI_BYTE_SIZE]) -> Self {
66        Self([((bbfi[0] as u16) << 8) | bbfi[1] as u16,
67        ((bbfi[2]  as u16) << 8) | bbfi[3] as u16,
68        ((bbfi[4]  as u16) << 8) | bbfi[5] as u16,
69        ((bbfi[6]  as u16) << 8) | bbfi[7] as u16])
70    }
71}
72#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
73pub struct BFIS(pub [BFI; BFI_COUNT]);
74impl BFIS {
75    pub fn new(bfis: [BFI; BFI_COUNT]) -> Self {
76        Self(bfis)
77    }
78}
79#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
80pub struct HBFI {
81    // Hierarchical Bloom Filter Index
82    pub request_pid: PublicIdentityInterface,
83    pub response_pid: PublicIdentity,
84    pub req: BFI, // request PublicIdentity, when set indicates Response will be encrypted.
85    pub res: BFI, // response PublicIdentity
86    pub app: BFI, // Application
87    pub m0d: BFI, // Module
88    pub fun: BFI, // Function
89    pub arg: BFI, // Argument
90    pub frm: u64, // Frame Count: current 1024 byte chunk of data in a range.
91}
92impl HBFI {
93    pub fn new(request_pid: PublicIdentityInterface
94        ,response_pid: PublicIdentity
95        , app: &str
96        , m0d: &str
97        , fun: &str
98        , arg: &str
99    ) -> Result<HBFI> {
100        Ok(HBFI {
101            request_pid: request_pid.clone(),
102            response_pid: response_pid.clone(),
103            req: request_pid.bloom_filter_index()?,
104            res: bloom_filter_index(&format!("{}", response_pid))?,
105            app: bloom_filter_index(app)?,
106            m0d: bloom_filter_index(m0d)?,
107            fun: bloom_filter_index(fun)?,
108            arg: bloom_filter_index(arg)?,
109            frm: 0,
110        })
111    }
112    pub fn to_bfis(&self) -> BFIS {
113        BFIS::new([ self.req.clone()
114        , self.res.clone()
115        , self.app.clone()
116        , self.m0d.clone()
117        , self.fun.clone()
118        , self.arg.clone()
119        ])
120    }
121    pub fn offset(mut self, frm: u64) -> Self {
122        self.frm = frm;
123        self
124    }
125    pub fn encrypt_for(&self, request_pid: PublicIdentityInterface) -> Result<Self> {
126        Ok(HBFI { request_pid: request_pid.clone()
127            , response_pid: self.response_pid.clone()
128            , req: request_pid.bloom_filter_index()?
129            , res: self.res.clone()
130            , app: self.app.clone()
131            , m0d: self.m0d.clone()
132            , fun: self.fun.clone()
133            , arg: self.arg.clone()
134            , frm: self.frm.clone()
135        })
136    }
137    pub fn cleartext_repr(&self) -> Result<Self> {
138        let absent_request_pid = PublicIdentityInterface::Absent;
139        Ok(HBFI { request_pid: absent_request_pid.clone()
140            , response_pid: self.response_pid.clone()
141            , req: absent_request_pid.bloom_filter_index()?
142            , res: self.res.clone()
143            , app: self.app.clone()
144            , m0d: self.m0d.clone()
145            , fun: self.fun.clone()
146            , arg: self.arg.clone()
147            , frm: self.frm.clone()
148        })
149    }
150    pub fn from_bytes(data: &[u8]) -> Result<Self> {
151        match data.len() {
152          CYPHERTEXT_HBFI_SIZE => {
153              let mut bfis: Vec<BFI> = Vec::with_capacity(BFI_COUNT);
154              let mut count = 0;
155              for _ in 0..BFI_COUNT {
156                  let mut bbfi = [0u8; BFI_BYTE_SIZE];
157                  bbfi.clone_from_slice(&data[count..count+BFI_BYTE_SIZE]);
158                  bfis.push(BFI::from_bytes(bbfi));
159                  count += BFI_BYTE_SIZE;
160              }
161              let mut frm = [0u8; FRAME_SIZE];
162              frm.clone_from_slice(&data[HBFI_FRAME_START..HBFI_FRAME_END]);
163              let frm: u64 = u8_to_u64(frm);
164              let mut res_key = [0u8; ID_SIZE + CC_SIZE];
165              res_key.clone_from_slice(&data[HBFI_RESPONSE_KEY_START..HBFI_RESPONSE_KEY_END]);
166              let mut req_key = [0u8; ID_SIZE + CC_SIZE];
167              req_key.clone_from_slice(&data[HBFI_REQUEST_KEY_START..HBFI_REQUEST_KEY_END]);
168              Ok(HBFI { response_pid: PublicIdentity::from(res_key)
169                      , request_pid: PublicIdentityInterface::new(PublicIdentity::from(req_key))
170                      , res: bfis[0].clone()
171                      , req: bfis[1].clone()
172                      , app: bfis[2].clone()
173                      , m0d: bfis[3].clone()
174                      , fun: bfis[4].clone()
175                      , arg: bfis[5].clone()
176                      , frm})
177          },
178          CLEARTEXT_HBFI_SIZE => {
179              let mut bfis: Vec<BFI> = Vec::with_capacity(BFI_COUNT);
180              let mut count = 0;
181              for _ in 0..BFI_COUNT {
182                  let mut bbfi = [0u8; BFI_BYTE_SIZE];
183                  bbfi.clone_from_slice(&data[count..count+BFI_BYTE_SIZE]);
184                  bfis.push(BFI::from_bytes(bbfi));
185                  count += BFI_BYTE_SIZE;
186              }
187              let mut frm = [0u8; FRAME_SIZE];
188              frm.clone_from_slice(&data[HBFI_FRAME_START..HBFI_FRAME_END]);
189              let frm: u64 = u8_to_u64(frm);
190              let mut res_key = [0u8; ID_SIZE + CC_SIZE];
191              res_key.clone_from_slice(&data[HBFI_RESPONSE_KEY_START..HBFI_RESPONSE_KEY_END]);
192              Ok(HBFI { response_pid: PublicIdentity::from(res_key)
193                      , request_pid: PublicIdentityInterface::Absent
194                      , res: bfis[0].clone()
195                      , req: bfis[1].clone()
196                      , app: bfis[2].clone()
197                      , m0d: bfis[3].clone()
198                      , fun: bfis[4].clone()
199                      , arg: bfis[5].clone()
200                      , frm})
201          }
202            _ => Err(anyhow!("Length of data used to reconstruct a HBFI is unrecognised")),
203        }
204
205    }
206    pub fn as_bytes(&self) -> Vec<u8> {
207        let mut buf: Vec<u8> = vec![];
208        let res = self.res.to_bytes();
209        let req = self.req.to_bytes();
210        let app = self.app.to_bytes();
211        let m0d = self.m0d.to_bytes();
212        let fun = self.fun.to_bytes();
213        let arg = self.arg.to_bytes();
214        let frm = &u64_to_u8(self.frm);
215        let mut ids_buf: Vec<u8> = vec![];
216        match &self.request_pid {
217            PublicIdentityInterface::Present { public_identity } => {
218                ids_buf.extend_from_slice(self.response_pid.key().as_ref());
219                ids_buf.extend_from_slice(self.response_pid.chain_code().as_ref());
220                ids_buf.extend_from_slice(public_identity.key().as_ref());
221                ids_buf.extend_from_slice(public_identity.chain_code().as_ref());
222            },
223            PublicIdentityInterface::Absent => {
224                ids_buf.extend_from_slice(self.response_pid.key().as_ref());
225                ids_buf.extend_from_slice(self.response_pid.chain_code().as_ref());
226            },
227        }
228        buf.extend_from_slice(&res);
229        buf.extend_from_slice(&req);
230        buf.extend_from_slice(&app);
231        buf.extend_from_slice(&m0d);
232        buf.extend_from_slice(&fun);
233        buf.extend_from_slice(&arg);
234        buf.extend_from_slice(frm);
235        buf.extend_from_slice(&ids_buf);
236        buf
237    }
238}
239impl fmt::Debug for HBFI {
240    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
241        match &*self {
242            HBFI { request_pid, response_pid, res, req, app, m0d, fun, arg, frm } =>
243            write!(f, "req_pid:{:?},res_pid:{:?},req:{:?},res:{:?},app:{:?},m0d:{:?},fun:{:?},arg:{:?},frm:{:?}", request_pid, response_pid, req, res, app, m0d, fun, arg, frm),
244        }
245    }
246}
247impl fmt::Display for HBFI {
248    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249        match &*self {
250            HBFI { request_pid, response_pid, res, req, app, m0d, fun, arg, frm } =>
251            write!(f, "req_pid:{:?},res_pid:{:?},req:{:?},res:{:?},app:{:?},m0d:{:?},fun:{:?},arg:{:?},frm:{:?}", request_pid, response_pid, req, res, app, m0d, fun, arg, frm),
252        }
253    }
254}
255#[cfg(test)]
256mod tests {
257    use super::*;
258
259    #[test]
260    fn test_bloom_filter_index() {
261        let actual = bloom_filter_index("9".into()).unwrap();
262        let expected: [u16; BLOOM_FILTER_INDEX_ELEMENT_LENGTH as usize] =
263            [19283, 50425, 20212, 47266];
264        assert_eq!(actual, expected);
265    }
266}