serialize_with_password/
lib.rs

1//! # Serialize_with_password
2//! Small crate that adds additional layer on top of the serde crate. This crate allows to encrypt serialized data with password
3//! 
4//! # Examples
5//! ## Serialization with password
6//! ```
7//! use serialize_with_password::{serialize, is_encrypted, deserialize};
8//! 
9//! let example_data = b"some data";
10//! let password = b"password";
11//! let encrypted = serialize(example_data, password).unwrap();
12//! 
13//! assert_ne!(example_data.to_vec(), encrypted);
14//! assert!(is_encrypted(&encrypted).expect("Correctly encrypted data always will return Ok(bool) for is_encrypted"));
15//! assert_eq!(example_data.to_vec(), deserialize(&encrypted, password).expect("Correct password"));
16//! assert!(deserialize(&encrypted, b"bacPass").is_err());
17//! ```
18//! 
19//! ## Serialize without password
20//! ```
21//! use serialize_with_password::{serialize_no_pass, is_encrypted, deserialize, deserialize_no_pass};
22//! 
23//! let example_data = b"some data";
24//! let encoded = serialize_no_pass(example_data);
25//! 
26//! assert!(!is_encrypted(&encoded).unwrap());
27//! assert_eq!(example_data.to_vec(), deserialize_no_pass(&encoded).unwrap());
28//! assert_eq!(example_data.to_vec(), deserialize(&encoded, b"Any password").unwrap());
29//! ```
30
31extern crate chacha20poly1305;
32extern crate argon2;
33
34use chacha20poly1305::{aead::Aead, XChaCha20Poly1305, Key, KeyInit};
35pub use chacha20poly1305::Error as ChaCha20Error;
36pub use argon2::Error as Argon2Error;
37
38#[cfg(feature = "serde")]
39pub use rmp_serde::encode::Error as EncodeError;
40#[cfg(feature = "serde")]
41pub use rmp_serde::decode::Error as DecodeError;
42
43#[derive(Debug)]
44pub enum Error {
45    DataIsEncrypted,
46    DataIsEmpty,
47    Argon2Error(Argon2Error),
48    ChaCha20Error(ChaCha20Error),
49    #[cfg(feature = "serde")]
50    SerdeEncodingError(EncodeError),
51    #[cfg(feature = "serde")]
52    SerdeDecodingError(DecodeError),
53}
54
55impl std::fmt::Display for Error {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        write!(f, "{}", match self {
58            Self::DataIsEncrypted => "DataIsEncrypted".to_owned(),
59            Self::DataIsEmpty => "DataIsEmpty".to_owned(),
60            Self::Argon2Error(err) => err.to_string(),
61            Self::ChaCha20Error(err) => err.to_string(),
62            #[cfg(feature = "serde")]
63            Self::SerdeEncodingError(err) => err.to_string(),
64            #[cfg(feature = "serde")]
65            Self::SerdeDecodingError(err) => err.to_string(),
66        })
67    }
68}
69
70impl From<Argon2Error> for Error {
71    fn from(value: Argon2Error) -> Self {
72        Self::Argon2Error(value)
73    }
74}
75
76impl From<ChaCha20Error> for Error {
77    fn from(value: ChaCha20Error) -> Self {
78        Self::ChaCha20Error(value)
79    }
80}
81
82impl std::error::Error for Error { }
83
84pub type Result<T> = core::result::Result<T, Error>;
85
86const SYMMETRIC_KEY_SIZE: usize = 32;
87const SYMMETRIC_NONE_SIZE: usize = 24;
88const SALT: &'static [u8] = b"WvgoXslnFkE0qM!R#gVONUCzVk2BeT!lSQ3$qnMLJ6q5dTbB3RrXRERlV2qAc%XMrN#A5f3P3W&!HUvznbqIFTnS3OdyYu3&lzEvLjItAamR8JN8wjR%Y0MPpzfE3ha7";
89
90#[inline]
91fn compute_key_and_nonce(password: &[u8]) -> core::result::Result<(Key, [u8; SYMMETRIC_NONE_SIZE]), Argon2Error> {
92    let mut dig = vec![0; SYMMETRIC_KEY_SIZE + SYMMETRIC_NONE_SIZE];
93    let mut key = [0; SYMMETRIC_KEY_SIZE];
94    let mut iv = [0; SYMMETRIC_NONE_SIZE];
95    argon2::Argon2::default().hash_password_into(password, SALT, &mut dig)?;
96    dig.iter().take(SYMMETRIC_KEY_SIZE).enumerate().for_each(|(i, v)| key[i] = *v);
97    dig.into_iter().skip(SYMMETRIC_KEY_SIZE).enumerate().for_each(|(i, v)| iv[i] = v);
98    Ok((Key::from(key), iv))
99}
100
101/// Encrypt data using password
102/// 
103/// # Example
104/// ```
105/// use serialize_with_password::{serialize, is_encrypted, deserialize, deserialize_no_pass};
106/// 
107/// let example_data = b"some data";
108/// let password = b"password";
109/// let encrypted = serialize(example_data, password).unwrap();
110/// 
111/// assert!(is_encrypted(&encrypted).expect("Data is encrypted correctly"));
112/// assert_ne!(example_data.to_vec(), encrypted);
113/// assert_eq!(example_data.to_vec(), deserialize(&encrypted, password).expect("Correct password"));
114/// assert!(deserialize(&encrypted, b"bacPass").is_err());
115/// assert!(deserialize_no_pass(&encrypted).is_err());
116/// ```
117#[inline]
118pub fn serialize(data: &[u8], password: &[u8]) -> Result<Vec<u8>> {
119    let (key, nonce) = compute_key_and_nonce(password)?;
120    let mut ans = vec![1];
121    ans.append(&mut XChaCha20Poly1305::new(&key).encrypt(&nonce.into(), data)?);
122    Ok(ans)
123}
124
125/// Serialize data without password
126/// 
127/// # Example
128/// ```
129/// use serialize_with_password::{serialize_no_pass, is_encrypted, deserialize, deserialize_no_pass};
130/// 
131/// let example_data = b"some data";
132/// let encoded = serialize_no_pass(example_data);
133/// 
134/// assert!(!is_encrypted(&encoded).expect("Data is encrypted correctly"));
135/// assert_eq!(example_data.to_vec(), deserialize_no_pass(&encoded).expect("Correctly serialized data will always return Ok(_)"));
136/// assert_eq!(example_data.to_vec(), deserialize(&encoded, b"any string of bytes").expect("Data serialized without password can be deserialized with any password"));
137/// ```
138#[inline]
139pub fn serialize_no_pass(data: &[u8]) -> Vec<u8> {
140    let mut ans = vec![0];
141    ans.extend(data.into_iter());
142    ans
143}
144
145
146/// Decrypt data with given password
147/// 
148/// # Error
149///  - if `data` slice is empty (Error::DataIsEmpty)
150///  - if `argon2` hasgin function return Error (Error::Argon2Error(Argon2Error))
151///  - if `password` is incorrect (Error::ChaCha20Error(ChaCha20Error))
152/// 
153/// # Example
154/// ```
155/// use serialize_with_password::{serialize, serialize_no_pass, is_encrypted, deserialize};
156/// 
157/// let example_data = b"some data";
158/// let encoded = serialize_no_pass(example_data);
159/// let password = b"password";
160/// let encrypted = serialize(example_data, password).unwrap();
161/// 
162/// assert!(!is_encrypted(&encoded).expect("Data is encrypted correctly"));
163/// assert!(is_encrypted(&encrypted).expect("Data is encrypted correctly"));
164/// assert_eq!(example_data.to_vec(), deserialize(&encoded, b"any string of bytes").expect("Data serialized without password can be deserialized with any password"));
165/// assert_eq!(example_data.to_vec(), deserialize(&encrypted, password).expect("Correct password"));
166/// assert!(deserialize(&encrypted, b"Wrong password").is_err());
167/// ```
168#[inline]
169pub fn deserialize(data: &[u8], password: &[u8]) -> Result<Vec<u8>> {
170    if data.is_empty() {
171        return Err(Error::DataIsEmpty);
172    }
173    if data[0] == 0 {
174        return Ok(data[1..].to_vec());
175    }
176    let (key, nonce) = compute_key_and_nonce(password)?;
177    Ok(XChaCha20Poly1305::new(&key).decrypt(&nonce.into(), &data[1..])?)
178}
179
180/// Deserialize data
181/// 
182/// # Error
183///  - if `data` slice is empty (Error::DataIsEmpty)
184///  - if `data` is encrypted (Error::DataIsEncrypted)
185/// 
186/// # Example
187/// ```
188/// use serialize_with_password::{serialize, is_encrypted, serialize_no_pass, deserialize_no_pass};
189/// 
190/// let example_data = b"some data";
191/// let encoded = serialize_no_pass(example_data);
192/// let password = b"password";
193/// let encrypted = serialize(example_data, password).unwrap();
194/// 
195/// assert!(!is_encrypted(&encoded).expect("Data is encrypted correctly"));
196/// assert!(is_encrypted(&encrypted).expect("Data is encrypted correctly"));
197/// assert_eq!(example_data.to_vec(), deserialize_no_pass(&encoded).expect("Data is serialized correctly"));
198/// assert!(deserialize_no_pass(&encrypted).is_err());
199/// assert!(deserialize_no_pass(&encrypted).is_err());
200/// ```
201#[inline]
202pub fn deserialize_no_pass(data: &[u8]) -> Result<Vec<u8>> {
203    if !is_encrypted(data)? {
204        return Ok(data[1..].to_vec());
205    }
206    Err(Error::DataIsEncrypted)
207}
208
209/// Returns whether data is encrypted
210/// For random non empty data returns random bool value
211/// 
212/// # Error
213/// Only if data is empty (Error::DataIsEmpty)
214/// 
215/// # Example
216/// ```
217/// use serialize_with_password::{serialize, serialize_no_pass, is_encrypted, deserialize_no_pass};
218/// 
219/// let example_data = b"some data";
220/// let encoded = serialize_no_pass(example_data);
221/// let password = b"password";
222/// let encrypted = serialize(example_data, password).unwrap();
223/// 
224/// assert!(!is_encrypted(&encoded).expect("Data is encoded correctly"));
225/// assert!(is_encrypted(&encrypted).expect("Data is encrypted correctly"));
226/// assert!(is_encrypted(&Vec::new()).is_err());
227/// ```
228#[inline]
229pub fn is_encrypted(data: &[u8]) -> Result<bool> {
230    if data.is_empty() {
231        return Err(Error::DataIsEmpty);
232    }
233    Ok(data[0] == 1)
234}
235
236#[cfg(feature = "serde")]
237mod serde_feature {
238    //! bbbb# Examples
239    //! 
240    //! ## Serialize serde with password
241    //! 
242    //! ```
243    //! use serde::{Serialize, Deserialize};
244    //! use serialize_with_password::{serialize_serde, is_encrypted, deserialize_serde};
245    //! 
246    //! #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
247    //! struct ExampleStruct {
248    //!     data: i32,
249    //!     more_data: Vec<u8>,
250    //! }
251    //! 
252    //! let example_data = ExampleStruct{ data: 16, more_data: vec![5,2,41,2] };
253    //! let password = b"password";
254    //! let encrypted = serialize_serde(&example_data, password).unwrap();
255    //! assert!(is_encrypted(&encrypted).unwrap());
256    //! assert_eq!(example_data, deserialize_serde(&encrypted, password).unwrap());
257    //! assert!(deserialize_serde::<ExampleStruct>(&encrypted, b"bacPass").is_err());
258    //! ```
259    //! 
260    //! ## Serialize serde without password
261    //! 
262    //! ```
263    //! use serde::{Serialize, Deserialize};
264    //! use serialize_with_password::{serialize_serde_no_pass, is_encrypted, deserialize_serde, deserialize_serde_no_pass};
265    //! 
266    //! #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
267    //! struct ExampleStruct {
268    //!     data: i32,
269    //!     more_data: Vec<u8>,
270    //! }
271    //! 
272    //! let example_data = ExampleStruct{ data: 16, more_data: vec![5,2,41,2] };
273    //! let encoded = serialize_serde_no_pass(&example_data).unwrap();
274    //! assert!(!is_encrypted(&encoded).unwrap());
275    //! assert_eq!(example_data, deserialize_serde_no_pass(&encoded).unwrap());
276    //! assert_eq!(example_data, deserialize_serde(&encoded, b"asdhas").unwrap());
277    //! ```
278
279    extern crate serde;
280    extern crate rmp_serde;
281    
282    pub use serde::{Serialize, Deserialize};
283    use super::*;
284    
285    impl From<EncodeError> for Error {
286        fn from(value: EncodeError) -> Self {
287            Self::SerdeEncodingError(value)
288        }
289    }
290    
291    impl From<DecodeError> for Error {
292        fn from(value: DecodeError) -> Self {
293            Self::SerdeDecodingError(value)
294        }
295    }
296   
297    /// Serialize data with serde then encrypt it
298    /// 
299    /// # Example
300    /// ```
301    /// use serde::{Serialize, Deserialize};
302    /// use serialize_with_password::{serialize_serde, is_encrypted, deserialize_serde, deserialize_serde_no_pass};
303    /// 
304    /// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
305    /// struct ExampleStruct {
306    ///     data: i32,
307    ///     more_data: Vec<u8>,
308    /// }
309    /// 
310    /// let example_data = ExampleStruct{ data: 16, more_data: vec![5,2,41,2] };
311    /// let password = b"password";
312    /// let encrypted = serialize_serde(&example_data, password).unwrap();
313    /// 
314    /// assert!(is_encrypted(&encrypted).expect("Data is encrypted correctly"));
315    /// assert_eq!(example_data, deserialize_serde(&encrypted, password).unwrap());
316    /// assert!(deserialize_serde::<ExampleStruct>(&encrypted, b"badPass").is_err());
317    /// assert!(deserialize_serde_no_pass::<ExampleStruct>(&encrypted).is_err());
318    /// ```
319    #[inline] 
320    pub fn serialize_serde<T: Serialize>(data: &T, password: &[u8]) -> Result<Vec<u8>> {
321        Ok(serialize(&rmp_serde::to_vec(data)?, password)?)
322    }
323    
324    /// Serialize data with serde
325    /// 
326    /// # Example
327    /// ```
328    /// use serde::{Serialize, Deserialize};
329    /// use serialize_with_password::{serialize_serde_no_pass, is_encrypted, deserialize_serde, deserialize_serde_no_pass};
330    /// 
331    /// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
332    /// struct ExampleStruct {
333    ///     data: i32,
334    ///     more_data: Vec<u8>,
335    /// }
336    /// 
337    /// let example_data = ExampleStruct{ data: 16, more_data: vec![5,2,41,2] };
338    /// let encoded = serialize_serde_no_pass(&example_data).unwrap();
339    /// 
340    /// assert!(!is_encrypted(&encoded).expect("Data is encrypted correctly"));
341    /// assert_eq!(example_data, deserialize_serde_no_pass(&encoded).unwrap());
342    /// assert_eq!(example_data, deserialize_serde(&encoded, b"Any password").unwrap());
343    /// ```
344    #[inline] 
345    pub fn serialize_serde_no_pass<T: Serialize>(data: &T) -> Result<Vec<u8>> {
346        Ok(serialize_no_pass(&rmp_serde::to_vec(data)?))
347    }
348
349    /// Decrypt data and deserialize it with serde
350    /// 
351    /// # Example
352    /// ```
353    /// use serde::{Serialize, Deserialize};
354    /// use serialize_with_password::{serialize_serde, serialize_serde_no_pass, is_encrypted, deserialize_serde};
355    /// 
356    /// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
357    /// struct ExampleStruct {
358    ///     data: i32,
359    ///     more_data: Vec<u8>,
360    /// }
361    /// 
362    /// let example_data = ExampleStruct{ data: 16, more_data: vec![5,2,41,2] };
363    /// let encoded = serialize_serde_no_pass(&example_data).unwrap();
364    /// let password = b"password";
365    /// let encrypted = serialize_serde(&example_data, password).unwrap();
366    /// 
367    /// assert!(!is_encrypted(&encoded).expect("Data is encoded correctly"));
368    /// assert!(is_encrypted(&encrypted).expect("Data is encrypted correctly"));
369    /// assert_eq!(example_data, deserialize_serde(&encoded, b"Any password").unwrap());
370    /// assert_eq!(example_data, deserialize_serde(&encrypted, password).unwrap());
371    /// assert!(deserialize_serde::<ExampleStruct>(&encrypted, b"badPass").is_err());
372    /// ```
373    #[inline]
374    pub fn deserialize_serde<T: for<'a> Deserialize<'a>>(data: &[u8], password: &[u8]) -> Result<T> {
375        Ok(rmp_serde::from_slice(&deserialize(data, password)?)?)
376    }
377
378    /// Deserialize data with serde
379    /// 
380    /// # Example
381    /// ```
382    /// use serde::{Serialize, Deserialize};
383    /// use serialize_with_password::{serialize_serde, serialize_serde_no_pass, is_encrypted, deserialize_serde_no_pass};
384    /// 
385    /// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
386    /// struct ExampleStruct {
387    ///     data: i32,
388    ///     more_data: Vec<u8>,
389    /// }
390    /// 
391    /// let example_data = ExampleStruct{ data: 16, more_data: vec![5,2,41,2] };
392    /// let encoded = serialize_serde_no_pass(&example_data).unwrap();
393    /// let password = b"password";
394    /// let encrypted = serialize_serde(&example_data, password).unwrap();
395    /// 
396    /// assert!(!is_encrypted(&encoded).expect("Data is encoded correctly"));
397    /// assert!(is_encrypted(&encrypted).expect("Data is encrypted correctly"));
398    /// assert_eq!(example_data, deserialize_serde_no_pass(&encoded).unwrap());
399    /// assert!(deserialize_serde_no_pass::<ExampleStruct>(&encrypted).is_err());
400    /// ```
401    #[inline]
402    pub fn deserialize_serde_no_pass<T: for<'a> Deserialize<'a>>(data: &[u8]) -> Result<T> {
403        Ok(rmp_serde::from_slice(&deserialize_no_pass(data)?)?)
404    }
405}
406
407#[cfg(feature = "serde")]
408pub use serde_feature::*;