iota_signing/
hmac.rs

1use iota_conversion::Trinary;
2use iota_crypto::{Curl, HashMode, Sponge};
3use iota_model::Bundle;
4
5use crate::Result;
6
7/// HMAC uses curl to provide an extra layer of verification
8/// to bundles
9///```rust
10/// use iota_signing::{self, HMAC};
11/// use iota_model::Bundle;
12///
13/// let mut bundle = Bundle::default();
14/// let hmac = HMAC::new("apples");
15/// hmac.add_hmac(&mut bundle);
16///```
17#[derive(Clone, Debug)]
18pub struct HMAC {
19    key: Vec<i8>,
20}
21
22impl HMAC {
23    /// Creates a new HMAC instance using the provided key
24    pub fn new(key: &str) -> HMAC {
25        HMAC { key: key.trits() }
26    }
27
28    /// Using the key provided earlier, add an HMAC to provided
29    /// Bundle
30    pub fn add_hmac(&self, bundle: &mut Bundle) -> Result<()> {
31        let mut curl = Curl::new(HashMode::CURLP27)?;
32        for b in bundle.iter_mut() {
33            if b.value > 0 {
34                let bundle_hash_trits = b.bundle.trits();
35                let mut hmac = [0; 243];
36                curl.reset();
37                curl.absorb(&self.key)?;
38                curl.absorb(&bundle_hash_trits)?;
39                curl.squeeze(&mut hmac)?;
40                let hmac_trytes = hmac.trytes()?;
41                b.signature_fragments = hmac_trytes
42                    + &b.signature_fragments
43                        .chars()
44                        .skip(81)
45                        .take(2106)
46                        .collect::<String>();
47            }
48        }
49        Ok(())
50    }
51}