securedrop_protocol_minimal/keys/
newsroom.rs1use rand_core::{CryptoRng, RngCore};
2
3use crate::sign::{DomainTag, Signature, SigningKey, VerifyingKey};
4
5pub const NR_ID: &[u8] = b"MOCK_NEWSROOM_ID";
8
9pub struct NewsroomKeyPair {
11 sk: SigningKey,
12}
13
14#[cfg_attr(hax, hax_lib::exclude)]
17impl core::fmt::Debug for NewsroomKeyPair {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 f.debug_struct("NewsroomKeyPair")
21 .field("vk", &self.sk.vk)
22 .finish_non_exhaustive()
23 }
24}
25
26impl NewsroomKeyPair {
27 pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Self, anyhow::Error> {
28 let sk = SigningKey::new(rng)?;
29 Ok(Self { sk })
30 }
31
32 pub fn verifying_key(&self) -> VerifyingKey {
34 self.sk.vk
35 }
36
37 pub fn sign<D: DomainTag>(&self, msg: &[u8]) -> Signature<D> {
39 self.sk.sign(msg)
40 }
41
42 pub fn as_bytes(&self) -> [u8; SigningKey::SEED_LEN] {
44 self.sk.as_bytes()
45 }
46
47 pub fn from_bytes(seed: [u8; SigningKey::SEED_LEN]) -> Self {
49 Self {
50 sk: SigningKey::from_seed(seed),
51 }
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use proptest::prelude::*;
59
60 proptest! {
61 #[test]
62 fn newsroom_keypair_seed_roundtrip(seed: [u8; SigningKey::SEED_LEN]) {
63 let kp = NewsroomKeyPair::from_bytes(seed);
64 prop_assert_eq!(kp.as_bytes(), seed);
65 let kp2 = NewsroomKeyPair::from_bytes(kp.as_bytes());
66 prop_assert_eq!(
67 kp.verifying_key().into_bytes(),
68 kp2.verifying_key().into_bytes()
69 );
70 }
71 }
72}