zkgroup/api/call_links/
params.rs1use partial_default::PartialDefault;
7use serde::{Deserialize, Serialize};
8
9use crate::common::errors::*;
10use crate::common::serialization::ReservedByte;
11use crate::common::sho::*;
12use crate::crypto::uid_encryption;
13use crate::{api, crypto};
14
15#[derive(Copy, Clone, Serialize, Deserialize, PartialDefault)]
16pub struct CallLinkSecretParams {
17 reserved: ReservedByte,
18 pub(crate) uid_enc_key_pair:
19 zkcredential::attributes::KeyPair<crypto::uid_encryption::UidEncryptionDomain>,
20}
21
22impl AsRef<uid_encryption::KeyPair> for CallLinkSecretParams {
23 fn as_ref(&self) -> &uid_encryption::KeyPair {
24 &self.uid_enc_key_pair
25 }
26}
27
28#[derive(Copy, Clone, Serialize, Deserialize, PartialDefault)]
29pub struct CallLinkPublicParams {
30 reserved: ReservedByte,
31 pub(crate) uid_enc_public_key:
32 zkcredential::attributes::PublicKey<crypto::uid_encryption::UidEncryptionDomain>,
33}
34
35impl CallLinkSecretParams {
36 const ROOT_KEY_MAX_BYTES_FOR_SHO: usize = 16;
37
38 pub fn derive_from_root_key(root_key: &[u8]) -> Self {
39 let byte_count = Self::ROOT_KEY_MAX_BYTES_FOR_SHO.min(root_key.len());
40 let mut sho = Sho::new(
41 b"Signal_ZKGroup_20230419_CallLinkSecretParams_DeriveFromRootKey",
42 &root_key[..byte_count],
43 );
44 let uid_enc_key_pair = zkcredential::attributes::KeyPair::derive_from(sho.as_mut());
45
46 Self {
47 reserved: Default::default(),
48 uid_enc_key_pair,
49 }
50 }
51
52 pub fn get_public_params(&self) -> CallLinkPublicParams {
53 CallLinkPublicParams {
54 reserved: Default::default(),
55 uid_enc_public_key: self.uid_enc_key_pair.public_key,
56 }
57 }
58
59 pub fn encrypt_uid(&self, user_id: libsignal_core::Aci) -> api::groups::UuidCiphertext {
60 let uid = crypto::uid_struct::UidStruct::from_service_id(user_id.into());
61 self.encrypt_uid_struct(uid)
62 }
63
64 fn encrypt_uid_struct(
65 &self,
66 uid: crypto::uid_struct::UidStruct,
67 ) -> api::groups::UuidCiphertext {
68 let ciphertext = self.uid_enc_key_pair.encrypt(&uid);
69 api::groups::UuidCiphertext {
70 reserved: Default::default(),
71 ciphertext,
72 }
73 }
74
75 pub fn decrypt_uid(
76 &self,
77 ciphertext: api::groups::UuidCiphertext,
78 ) -> Result<libsignal_core::Aci, ZkGroupVerificationFailure> {
79 let uid = crypto::uid_encryption::UidEncryptionDomain::decrypt(
80 &self.uid_enc_key_pair,
81 &ciphertext.ciphertext,
82 )?;
83 uid.try_into().map_err(|_| ZkGroupVerificationFailure)
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use crate::call_links::CallLinkSecretParams;
90
91 #[test]
92 fn test_call_link_secret_params_ignores_extra_bytes() {
93 let bytes_0 = b"0123456789012345";
94 let bytes_1 = b"012345678901234512345";
95
96 assert_eq!(
97 bytes_0.len(),
98 CallLinkSecretParams::ROOT_KEY_MAX_BYTES_FOR_SHO
99 );
100
101 assert!(bytes_1.len() > CallLinkSecretParams::ROOT_KEY_MAX_BYTES_FOR_SHO);
102
103 let secret_params_0 = CallLinkSecretParams::derive_from_root_key(bytes_0);
104 let secret_params_1 = CallLinkSecretParams::derive_from_root_key(bytes_1);
105
106 assert_eq!(
107 secret_params_0.uid_enc_key_pair.a1,
108 secret_params_1.uid_enc_key_pair.a1
109 );
110 assert_eq!(
111 secret_params_0.uid_enc_key_pair.a2,
112 secret_params_1.uid_enc_key_pair.a2
113 );
114 assert!(
115 secret_params_0.uid_enc_key_pair.public_key
116 == secret_params_1.uid_enc_key_pair.public_key
117 );
118 }
119}