zoe_client/client/
secret.rs1use crate::ClientError;
2use crate::error::Result;
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use std::net::SocketAddr;
5use std::sync::Arc;
6use zoe_app_primitives::RelayAddress;
7use zoe_wire_protocol::{KeyPair, VerifyingKey};
8
9#[cfg(feature = "frb-api")]
10use flutter_rust_bridge::frb;
11
12#[cfg_attr(feature = "frb-api", frb(opaque))]
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct ClientSecret {
15 #[serde(
16 serialize_with = "serialize_key_pair",
17 deserialize_with = "deserialize_key_pair"
18 )]
19 pub(crate) inner_keypair: Arc<KeyPair>, pub(crate) servers: Vec<RelayAddress>,
21 pub(crate) encryption_key: [u8; 32],
22}
23
24impl PartialEq for ClientSecret {
25 fn eq(&self, other: &Self) -> bool {
26 self.servers == other.servers && self.encryption_key == other.encryption_key
28 }
29}
30
31impl Eq for ClientSecret {}
32
33impl ClientSecret {
34 pub fn servers(&self) -> &[RelayAddress] {
36 &self.servers
37 }
38}
39
40#[cfg_attr(feature = "frb-api", frb(ignore))]
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct LegacyClientSecret {
43 #[serde(
44 serialize_with = "serialize_key_pair",
45 deserialize_with = "deserialize_key_pair"
46 )]
47 inner_keypair: Arc<KeyPair>, server_public_key: VerifyingKey, server_addr: SocketAddr,
50 encryption_key: [u8; 32],
51}
52
53impl PartialEq for LegacyClientSecret {
54 fn eq(&self, other: &Self) -> bool {
55 self.server_public_key == other.server_public_key
57 && self.server_addr == other.server_addr
58 && self.encryption_key == other.encryption_key
59 }
60}
61
62impl Eq for LegacyClientSecret {}
63
64fn serialize_key_pair<S>(
65 key_pair: &Arc<KeyPair>,
66 serializer: S,
67) -> std::result::Result<S::Ok, S::Error>
68where
69 S: Serializer,
70{
71 serializer.serialize_str(&key_pair.to_pem().map_err(serde::ser::Error::custom)?)
72}
73fn deserialize_key_pair<'de, D>(deserializer: D) -> std::result::Result<Arc<KeyPair>, D::Error>
74where
75 D: Deserializer<'de>,
76{
77 let s = String::deserialize(deserializer)?;
78 Ok(Arc::new(
79 KeyPair::from_pem(&s).map_err(serde::de::Error::custom)?,
80 ))
81}
82
83impl ClientSecret {
84 pub fn from_hex(hex: &str) -> Result<Self> {
85 let bytes = hex::decode(hex).map_err(|e| {
86 ClientError::BuildError(format!("Failed to decode hex for client secret: {e}"))
87 })?;
88 let secret = match postcard::from_bytes(&bytes) {
89 Ok(secret) => secret,
90 Err(e) => {
91 tracing::warn!(
92 "Failed to deserialize client secret: {}. Trying with legacy format.",
93 e
94 );
95 let legacy_secret: LegacyClientSecret =
96 postcard::from_bytes(&bytes).map_err(|e| {
97 ClientError::BuildError(format!(
98 "Failed to deserialize legacy client secret: {e}"
99 ))
100 })?;
101 ClientSecret {
102 inner_keypair: legacy_secret.inner_keypair,
103 servers: vec![
104 RelayAddress::new(legacy_secret.server_public_key)
105 .with_address(legacy_secret.server_addr.into()),
106 ],
107 encryption_key: legacy_secret.encryption_key,
108 }
109 }
110 };
111 Ok(secret)
112 }
113
114 pub fn to_hex(&self) -> Result<String> {
115 let bytes = postcard::to_stdvec(&self).map_err(|e| {
116 ClientError::BuildError(format!("Failed to serialize client secret: {e}"))
117 })?;
118 Ok(hex::encode(bytes))
119 }
120}