1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! This module defines the interface for share authentication.
use serde::{Deserialize, Serialize};

use crate::{primitives::mac::MAC_LENGTH, Error};

use super::mac::{Mac, MacKey};

/// A bit held by a party with a given ID.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bit {
    pub(crate) id: BitID,
    pub(crate) value: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
/// A bit identifier.
///
/// This is unique per party, not globally, so if referring bits held by another
/// party, their party ID is also required to disambiguate.
pub struct BitID(pub(crate) usize);

#[derive(Debug, Clone, Serialize, Deserialize)]
/// A bit authenticated between two parties.
pub struct AuthBit {
    pub(crate) bit: Bit,
    pub(crate) macs: Vec<(usize, Mac)>,
    pub(crate) mac_keys: Vec<BitKey>,
}

impl AuthBit {
    /// Serialize the bit value and all MACs on the bit.
    pub fn serialize_bit_macs(&self) -> Vec<u8> {
        let mut result = vec![0u8; (self.macs.len() + 1) * MAC_LENGTH + 1];
        result[0] = self.bit.value as u8;
        for (key_holder, mac) in self.macs.iter() {
            result[1 + key_holder * MAC_LENGTH..1 + (key_holder + 1) * MAC_LENGTH]
                .copy_from_slice(mac);
        }

        result
    }

    /// Deserialize a bit and MACs on that bit.
    pub fn deserialize_bit_macs(bytes: &[u8]) -> Result<(bool, Vec<[u8; MAC_LENGTH]>), Error> {
        if bytes[0] > 1 {
            return Err(Error::InvalidSerialization);
        }
        let bit_value = bytes[0] != 0;
        let mac_chunks = bytes[1..].chunks_exact(MAC_LENGTH);
        if !mac_chunks.remainder().is_empty() {
            return Err(Error::InvalidSerialization);
        }

        let mut macs: Vec<[u8; MAC_LENGTH]> = Vec::new();
        for mac in mac_chunks {
            macs.push(
                mac.try_into()
                    .expect("chunks should be of the required length"),
            )
        }

        Ok((bit_value, macs))
    }
}

/// The key to authenticate a two-party authenticated bit.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BitKey {
    pub(crate) holder_bit_id: BitID,
    pub(crate) bit_holder: usize,
    pub(crate) mac_key: MacKey,
}