securedrop_protocol_minimal/
keys.rs1mod newsroom;
2
3use rand_core::{CryptoRng, RngCore};
4
5use crate::sign::{
6 DomainTag, FpfOnNewsroom, JournalistEphemeralKey, JournalistLongTermKey, Signature, SigningKey,
7 VerifyingKey,
8};
9
10use crate::message::{MessageKeyPair, MessagePublicKey};
11use crate::metadata::{MetadataKeyPair, MetadataPublicKey};
12use crate::primitives::x25519::DHPrivateKey;
13use crate::primitives::x25519::DHPublicKey;
14use alloc::vec::Vec;
15
16use crate::constants::*;
17
18pub struct KeyPair<SK, PK> {
20 pub(crate) sk: SK,
21 pub(crate) pk: PK,
22}
23
24pub type DhFetchKeyPair = KeyPair<DHPrivateKey, DHPublicKey>;
27pub type SigningKeyPair = KeyPair<SigningKey, VerifyingKey>;
28
29pub type SignedKeyBundlePublic = (KeyBundlePublic, Signature<JournalistEphemeralKey>);
32
33#[derive(Debug, Clone)]
35pub struct KeyBundlePublic {
36 pub apke_pk: MessagePublicKey,
38 pub metadata_pk: MetadataPublicKey,
40}
41
42impl KeyBundlePublic {
43 pub fn as_bytes(&self) -> Vec<u8> {
47 let mut out = Vec::new();
48 out.extend(self.apke_pk.as_bytes());
49 out.extend(self.metadata_pk.as_bytes());
50 out
51 }
52}
53
54pub(crate) struct MessageKeyBundle {
55 pub(crate) apke: MessageKeyPair,
56 pub(crate) metadata_kp: MetadataKeyPair,
57}
58
59impl MessageKeyBundle {
60 pub fn new(apke: MessageKeyPair, metadata_kp: MetadataKeyPair) -> Self {
61 Self { apke, metadata_kp }
62 }
63
64 pub(crate) fn public(&self) -> KeyBundlePublic {
65 KeyBundlePublic {
66 apke_pk: self.apke.public_key().clone(),
67 metadata_pk: self.metadata_kp.public_key().clone(),
68 }
69 }
70}
71
72pub(crate) struct SignedMessageKeyBundle {
73 pub(crate) bundle: MessageKeyBundle,
74 pub(crate) selfsig: Signature<JournalistEphemeralKey>,
75}
76
77#[derive(Debug, Clone)]
78pub struct SignedLongtermPubKeyBytes(
79 pub [u8; LEN_DHKEM_ENCAPS_KEY + LEN_MLKEM_ENCAPS_KEY + LEN_DH_ITEM],
80);
81
82impl SignedLongtermPubKeyBytes {
83 pub(crate) fn from_keys(reply_apke: &MessagePublicKey, fetch_pk: &DHPublicKey) -> Self {
88 let apke_bytes = reply_apke.as_bytes();
89 let fetch_bytes = fetch_pk.into_bytes();
90
91 let mut pubkey_bytes = [0u8; LEN_DHKEM_ENCAPS_KEY + LEN_MLKEM_ENCAPS_KEY + LEN_DH_ITEM];
92 pubkey_bytes[..apke_bytes.len()].copy_from_slice(&apke_bytes);
93 pubkey_bytes[apke_bytes.len()..].copy_from_slice(&fetch_bytes);
94
95 Self(pubkey_bytes)
96 }
97
98 pub fn as_bytes(&self) -> &[u8] {
100 &self.0
101 }
102}
103
104#[derive(Clone, Debug)]
105pub struct Enrollment {
106 pub bundle: SignedLongtermPubKeyBytes,
107 pub selfsig: Signature<JournalistLongTermKey>,
108 pub keys: (VerifyingKey, DHPublicKey, MessagePublicKey),
109}
110
111pub struct SessionStorage {
113 pub fpf_key: Option<VerifyingKey>,
114 pub nr_key: Option<VerifyingKey>,
115 pub fpf_signature: Option<Signature<FpfOnNewsroom>>,
116}
117
118pub struct FPFKeyPair {
120 sk: SigningKey,
121 vk: VerifyingKey,
122}
123
124impl core::fmt::Debug for FPFKeyPair {
125 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
126 f.debug_struct("FPFKeyPair")
127 .field("vk", &self.vk)
128 .finish_non_exhaustive()
129 }
130}
131
132impl FPFKeyPair {
133 pub fn new<R: RngCore + CryptoRng>(mut rng: R) -> Result<Self, anyhow::Error> {
139 let sk = SigningKey::new(&mut rng)?;
140 let vk = sk.vk;
141 Ok(Self { sk, vk })
142 }
143
144 pub fn verifying_key(&self) -> VerifyingKey {
146 self.vk
147 }
148
149 pub fn sign<D: DomainTag>(&self, msg: &[u8]) -> Signature<D> {
151 self.sk.sign(msg)
152 }
153}
154
155pub use newsroom::NewsroomKeyPair;