libsignal_protocol/state/
kyber_prekey.rs

1//
2// Copyright 2023 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6use std::fmt;
7
8use crate::proto::storage::SignedPreKeyRecordStructure;
9use crate::state::GenericSignedPreKey;
10use crate::{kem, PrivateKey, Result, Timestamp};
11
12/// A unique identifier selecting among this client's known signed pre-keys.
13#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
14pub struct KyberPreKeyId(u32);
15
16impl From<u32> for KyberPreKeyId {
17    fn from(value: u32) -> Self {
18        Self(value)
19    }
20}
21
22impl From<KyberPreKeyId> for u32 {
23    fn from(value: KyberPreKeyId) -> Self {
24        value.0
25    }
26}
27
28impl fmt::Display for KyberPreKeyId {
29    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30        write!(f, "{}", self.0)
31    }
32}
33
34#[derive(Debug, Clone)]
35pub struct KyberPreKeyRecord {
36    signed_pre_key: SignedPreKeyRecordStructure,
37}
38
39impl GenericSignedPreKey for KyberPreKeyRecord {
40    type KeyPair = kem::KeyPair;
41    type Id = KyberPreKeyId;
42
43    fn get_storage(&self) -> &SignedPreKeyRecordStructure {
44        &self.signed_pre_key
45    }
46
47    fn from_storage(storage: SignedPreKeyRecordStructure) -> Self {
48        Self {
49            signed_pre_key: storage,
50        }
51    }
52}
53
54impl KyberPreKeyRecord {
55    pub fn secret_key(&self) -> Result<kem::SecretKey> {
56        kem::SecretKey::deserialize(&self.signed_pre_key.private_key)
57    }
58}
59
60impl KyberPreKeyRecord {
61    pub fn generate(
62        kyber_key_type: kem::KeyType,
63        id: KyberPreKeyId,
64        signing_key: &PrivateKey,
65    ) -> Result<KyberPreKeyRecord> {
66        let key_pair = kem::KeyPair::generate(kyber_key_type);
67        let mut rng = rand::rngs::OsRng;
68        let signature = signing_key
69            .calculate_signature(&key_pair.public_key.serialize(), &mut rng)?
70            .into_vec();
71        let timestamp = std::time::SystemTime::now()
72            .duration_since(std::time::SystemTime::UNIX_EPOCH)
73            .expect("Time should move forward")
74            .as_millis();
75        Ok(KyberPreKeyRecord::new(
76            id,
77            Timestamp::from_epoch_millis(timestamp.try_into().expect("Timestamp too large")),
78            &key_pair,
79            &signature,
80        ))
81    }
82}