wireguard_conf/keys/
preshared.rs1use core::fmt;
2
3use base64::prelude::*;
4use rand::Rng;
5use zeroize::{Zeroize, ZeroizeOnDrop};
6
7use crate::WireguardError;
8
9#[derive(Clone, PartialEq, Zeroize, ZeroizeOnDrop)]
39pub struct PresharedKey([u8; 32]);
40
41impl PresharedKey {
42 #[must_use]
44 pub fn random() -> Self {
45 let mut key = [0u8; 32];
46 rand::rng().fill_bytes(&mut key);
47 Self(key)
48 }
49}
50
51impl PresharedKey {
52 #[inline]
54 #[must_use]
55 pub fn to_bytes(&self) -> [u8; 32] {
56 self.0
57 }
58
59 #[inline]
61 #[must_use]
62 pub fn as_bytes(&self) -> &[u8; 32] {
63 &self.0
64 }
65}
66
67impl fmt::Debug for PresharedKey {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 f.debug_tuple("PresharedKey")
70 .field(&self.to_string())
71 .finish()
72 }
73}
74
75impl fmt::Display for PresharedKey {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 write!(f, "{}", BASE64_STANDARD.encode(self.as_bytes()))
79 }
80}
81
82impl From<[u8; 32]> for PresharedKey {
83 fn from(value: [u8; 32]) -> Self {
84 Self(value)
85 }
86}
87
88impl TryFrom<&str> for PresharedKey {
89 type Error = WireguardError;
90
91 fn try_from(value: &str) -> Result<Self, Self::Error> {
92 let bytes: [u8; 32] = BASE64_STANDARD
93 .decode(value)
94 .map_err(|_| WireguardError::InvalidPresharedKey)?
95 .try_into()
96 .map_err(|_| WireguardError::InvalidPresharedKey)?;
97
98 Ok(Self(bytes))
99 }
100}
101
102impl TryFrom<String> for PresharedKey {
103 type Error = WireguardError;
104
105 fn try_from(value: String) -> Result<Self, Self::Error> {
106 Self::try_from(value.as_str())
107 }
108}
109
110#[cfg(feature = "serde")]
111mod serde_impl {
112 use super::PresharedKey;
113 use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
114
115 impl Serialize for PresharedKey {
116 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
117 where
118 S: Serializer,
119 {
120 if serializer.is_human_readable() {
121 serializer.serialize_str(&self.to_string())
122 } else {
123 serializer.serialize_bytes(self.as_bytes())
124 }
125 }
126 }
127
128 impl<'de> Deserialize<'de> for PresharedKey {
129 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
130 where
131 D: Deserializer<'de>,
132 {
133 if deserializer.is_human_readable() {
134 let data = String::deserialize(deserializer)?;
135
136 PresharedKey::try_from(data.as_str()).map_err(|_| {
137 de::Error::invalid_value(de::Unexpected::Str(&data), &"a preshared key")
138 })
139 } else {
140 let bytes = <[u8; 32]>::deserialize(deserializer)?;
141
142 Ok(PresharedKey::from(bytes))
143 }
144 }
145 }
146}