Skip to main content

securedrop_protocol_minimal/wire/
bundle.rs

1use alloc::string::String;
2use alloc::vec::Vec;
3use serde::de::Error as _;
4use serde::{Deserialize, Serialize};
5
6use crate::keys::bundle::{KeyBundlePublic, LongtermKeyBundle};
7use crate::message::MessagePublicKey;
8use crate::primitives::ristretto255::DHPublicKey;
9use crate::sign::{JournalistEphemeralKey, JournalistLongTermKey, Signature};
10
11/// The public half of an ephemeral key bundle together with the journalist's
12/// self-signature over it.
13pub type SignedKeyBundlePublic = (KeyBundlePublic, Signature<JournalistEphemeralKey>);
14
15#[derive(Debug, Clone)]
16pub struct SignedLongtermKeyBundle {
17    pub bundle: LongtermKeyBundle,
18    pub selfsig: Signature<JournalistLongTermKey>,
19}
20
21impl SignedLongtermKeyBundle {
22    pub fn new(bundle: LongtermKeyBundle, selfsig: Signature<JournalistLongTermKey>) -> Self {
23        Self { bundle, selfsig }
24    }
25
26    pub fn as_bytes(&self) -> Vec<u8> {
27        let bundle_bytes = self.bundle.as_bytes();
28        let sig_bytes = self.selfsig.as_bytes();
29
30        let mut pubkey_bytes = Vec::with_capacity(bundle_bytes.len() + sig_bytes.len());
31        pubkey_bytes.extend_from_slice(&bundle_bytes);
32        pubkey_bytes.extend_from_slice(&sig_bytes);
33
34        pubkey_bytes
35    }
36
37    pub fn bundle_bytes(&self) -> [u8; LongtermKeyBundle::LEN] {
38        self.bundle.as_bytes()
39    }
40
41    pub fn apke(&self) -> &MessagePublicKey {
42        &self.bundle.apke
43    }
44
45    pub fn fetch_pk(&self) -> &DHPublicKey {
46        &self.bundle.fetch_pk
47    }
48}
49
50#[cfg_attr(hax, hax_lib::exclude)]
51impl Serialize for SignedLongtermKeyBundle {
52    fn serialize<S: serde::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
53        ser.serialize_str(&hex::encode(self.as_bytes()))
54    }
55}
56
57#[cfg_attr(hax, hax_lib::exclude)]
58impl<'de> Deserialize<'de> for SignedLongtermKeyBundle {
59    fn deserialize<D: serde::Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
60        type Sig = Signature<JournalistLongTermKey>;
61        let s = String::deserialize(de)?;
62        let mut bytes = [0u8; LongtermKeyBundle::LEN + Sig::LEN];
63        hex::decode_to_slice(s.trim(), &mut bytes).map_err(D::Error::custom)?;
64
65        let offset = MessagePublicKey::LEN;
66        let apke = MessagePublicKey::from_bytes(&bytes[..offset]).map_err(D::Error::custom)?;
67        let mut fetch_key_bytes = [0u8; DHPublicKey::LEN];
68        fetch_key_bytes.copy_from_slice(&bytes[offset..offset + DHPublicKey::LEN]);
69        let fetch = DHPublicKey::decode(fetch_key_bytes).map_err(D::Error::custom)?;
70        let mut sig_bytes = [0u8; Sig::LEN];
71        sig_bytes.copy_from_slice(&bytes[offset + DHPublicKey::LEN..]);
72        Ok(Self {
73            bundle: LongtermKeyBundle::new(apke, fetch),
74            selfsig: Sig::from_bytes(sig_bytes),
75        })
76    }
77}