1#[macro_use]
28mod macros;
29
30use paste::paste;
31use rand_core::{OsRng, RngCore};
32#[cfg(feature = "rocket")]
33use rocket::request::FromParam;
34#[cfg(feature = "schema")]
35use schemars::JsonSchema;
36#[cfg(feature = "serde")]
37use serde::{
38 de::{Error, Visitor},
39 Deserialize, Deserializer, Serialize, Serializer,
40};
41use std::fmt;
42use std::str::FromStr;
43use thiserror::Error;
44use x25519_dalek_fiat::{PublicKey, StaticSecret};
45use zeroize::Zeroize;
46
47#[derive(Error, Debug)]
49pub enum ParseError {
50 #[cfg(feature = "base64")]
52 #[error("base64 decoding error")]
53 Base64(#[from] base64::DecodeError),
54 #[cfg(feature = "hex")]
56 #[error("hex decoding errro")]
57 Hex(#[from] hex::FromHexError),
58 #[cfg(feature = "base32")]
60 #[error("base32 decoding error")]
61 Base32Error,
62 #[error("length mismatch")]
64 Length,
65}
66
67pub const PUBKEY_LEN: usize = 32;
69
70pub const PRIVKEY_LEN: usize = 32;
72
73pub const SECRET_LEN: usize = 32;
75
76#[cfg_attr(feature = "schema", derive(JsonSchema))]
78#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Zeroize)]
79pub struct Pubkey([u8; PUBKEY_LEN]);
80
81impl_new!(Pubkey, PUBKEY_LEN);
82impl_display!(Pubkey);
83impl_deref!(Pubkey, PUBKEY_LEN);
84#[cfg(feature = "hex")]
85impl_hex!(Pubkey);
86#[cfg(feature = "base64")]
87impl_base64!(Pubkey);
88#[cfg(feature = "base32")]
89impl_base32!(Pubkey);
90impl_parse!(Pubkey);
91#[cfg(feature = "serde")]
92impl_serde!(Pubkey, "WireGuard public key");
93#[cfg(feature = "rocket")]
94impl_rocket!(Pubkey);
95
96impl Pubkey {
97 #[cfg(test)]
98 fn generate() -> Pubkey {
99 Privkey::generate().pubkey()
100 }
101}
102
103#[test]
104fn test_pubkey_from_slice() {
105 let slice = [0; 3];
106 match Pubkey::try_from(&slice[..]) {
107 Err(ParseError::Length) => {}
108 _ => assert!(false),
109 }
110 let slice = [0; PUBKEY_LEN];
111 match Pubkey::try_from(&slice[..]) {
112 Ok(_) => {}
113 _ => assert!(false),
114 }
115}
116
117impl TryFrom<&[u8]> for Pubkey {
118 type Error = ParseError;
119 fn try_from(key: &[u8]) -> Result<Self, Self::Error> {
120 if key.len() != PUBKEY_LEN {
121 Err(ParseError::Length)
122 } else {
123 let mut data = [0; PUBKEY_LEN];
124 data[0..PUBKEY_LEN].copy_from_slice(&key[0..PUBKEY_LEN]);
125 Ok(Pubkey(data))
126 }
127 }
128}
129
130#[cfg_attr(feature = "schema", derive(JsonSchema))]
132#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Zeroize)]
133pub struct Privkey([u8; PRIVKEY_LEN]);
134
135impl_display!(Privkey);
136impl_new!(Privkey, PRIVKEY_LEN);
137impl_deref!(Privkey, PRIVKEY_LEN);
138#[cfg(feature = "hex")]
139impl_hex!(Privkey);
140#[cfg(feature = "base64")]
141impl_base64!(Privkey);
142#[cfg(feature = "base32")]
143impl_base32!(Privkey);
144impl_parse!(Privkey);
145#[cfg(feature = "serde")]
146impl_serde!(Privkey, "WireGuard private key");
147#[cfg(feature = "rocket")]
148impl_rocket!(Privkey);
149
150impl Privkey {
151 pub fn generate() -> Self {
153 let private_key = StaticSecret::new(OsRng);
154 Privkey(private_key.to_bytes())
155 }
156
157 pub fn valid(&self) -> bool {
159 if self.0 == [0; PRIVKEY_LEN] {
160 return false;
161 }
162
163 let private_key = StaticSecret::from(self.0.clone());
164 self.0 == private_key.to_bytes()
165 }
166
167 pub fn pubkey(&self) -> Pubkey {
169 let private_key = StaticSecret::from(self.0.clone());
170 let public_key: PublicKey = (&private_key).into();
171 Pubkey(public_key.to_bytes())
172 }
173}
174
175#[test]
176fn test_privkey_from_slice() {
177 let slice = [0; 3];
178 match Privkey::try_from(&slice[..]) {
179 Err(ParseError::Length) => {}
180 _ => assert!(false),
181 }
182 let slice = [0; PRIVKEY_LEN];
183 match Privkey::try_from(&slice[..]) {
184 Ok(_) => {}
185 _ => assert!(false),
186 }
187}
188
189impl TryFrom<&[u8]> for Privkey {
190 type Error = ParseError;
191 fn try_from(key: &[u8]) -> Result<Self, Self::Error> {
192 if key.len() != PUBKEY_LEN {
193 Err(ParseError::Length)
194 } else {
195 let mut data = [0; PUBKEY_LEN];
196 data[0..PUBKEY_LEN].copy_from_slice(&key[0..PUBKEY_LEN]);
197 Ok(Privkey(data))
198 }
199 }
200}
201
202#[test]
203fn test_wireguard_privkey() {
204 let key = Privkey::new([0; PRIVKEY_LEN]);
205 assert_eq!(key.valid(), false);
206 let key = Privkey::new([255; PRIVKEY_LEN]);
207 assert_eq!(key.valid(), false);
208 let key = Privkey::generate();
209 assert_eq!(key.valid(), true);
210 assert_eq!(key.pubkey(), key.pubkey());
212}
213
214#[cfg_attr(feature = "schema", derive(JsonSchema))]
216#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Zeroize)]
217pub struct Secret([u8; SECRET_LEN]);
218
219impl_new!(Secret, SECRET_LEN);
220impl_display!(Secret);
221impl_deref!(Secret, SECRET_LEN);
222#[cfg(feature = "hex")]
223impl_hex!(Secret);
224#[cfg(feature = "base64")]
225impl_base64!(Secret);
226#[cfg(feature = "base32")]
227impl_base32!(Secret);
228impl_parse!(Secret);
229#[cfg(feature = "serde")]
230impl_serde!(Secret, "WireGuard preshared key");
231#[cfg(feature = "rocket")]
232impl_rocket!(Secret);
233
234impl Secret {
235 pub fn generate() -> Self {
237 let mut data = [0; SECRET_LEN];
238 OsRng.fill_bytes(&mut data);
239 Secret(data)
240 }
241}
242
243#[test]
244fn test_secret_from_slice() {
245 let slice = [0; 3];
246 match Secret::try_from(&slice[..]) {
247 Err(ParseError::Length) => {}
248 _ => assert!(false),
249 }
250 let slice = [0; PRIVKEY_LEN];
251 match Secret::try_from(&slice[..]) {
252 Ok(_) => {}
253 _ => assert!(false),
254 }
255}
256
257impl TryFrom<&[u8]> for Secret {
258 type Error = ParseError;
259 fn try_from(key: &[u8]) -> Result<Self, Self::Error> {
260 if key.len() != PUBKEY_LEN {
261 Err(ParseError::Length)
262 } else {
263 let mut data = [0; PUBKEY_LEN];
264 data[0..PUBKEY_LEN].copy_from_slice(&key[0..PUBKEY_LEN]);
265 Ok(Secret(data))
266 }
267 }
268}