libcrypt_rs/lib.rs
1//! # rust binding for POSIX crypt library (libcrypt)
2//!
3//! ## Example
4//! ```
5//! // Import Crypt struct and Encryptions enum.
6//! use libcrypt_rs::{Crypt, Encryptions};
7//!
8//! fn main() {
9//! // Create new instance of Crypt object.
10//! let mut engine = Crypt::new();
11//!
12//! // Generate new encryption salt for sha256crypt encryption algorithm.
13//! engine.gen_salt(Encryptions::Sha256).expect("Salt generation failed");
14//!
15//! // Encrypt "1234" string.
16//! engine.encrypt("1234".to_string()).expect("Encryption failed");
17//!
18//! // Encrypted data is stored in engine.encrypted. Let's print it to stdout.
19//! println!("Encrypted data: '{}'", engine.encrypted);
20//! }
21//! ```
22
23#[cfg(test)]
24mod tests;
25
26use std::ffi::{CString, NulError, CStr};
27
28pub mod encryptions;
29pub use encryptions::Encryptions;
30pub mod raw;
31
32/// Encryption struct.
33pub struct Crypt {
34 /// Stores encrypted data.
35 pub encrypted: String,
36 salt: Option<CString>
37}
38
39impl Crypt {
40 /// Create new instance of Crypt object.
41 pub fn new() -> Self {
42 Crypt {
43 encrypted: String::new(),
44 salt: None
45 }
46 }
47
48 /// Set custom salt for encryption.
49 /// ```
50 /// use libcrypt_rs::Crypt;
51 ///
52 /// let mut engine = Crypt::new();
53 /// engine.set_salt("$1$N1TAWHQs".to_string()).expect("Setting custom salt failed");
54 ///
55 /// println!("{}", engine.get_salt().unwrap());
56 pub fn set_salt(&mut self, salt: String) -> Result<(), NulError> {
57 self.salt = Some(CString::new(salt)?);
58
59 Ok(())
60 }
61
62 /// Generate salt.
63 /// ```
64 /// use libcrypt_rs::{Crypt, Encryptions};
65 ///
66 /// let mut engine = Crypt::new();
67 /// engine.gen_salt(Encryptions::Sha256).expect("Salt generation failed");
68 ///
69 /// println!("{}", engine.get_salt().unwrap());
70 /// ```
71 pub fn gen_salt(&mut self, encryption: Encryptions) -> Result<(), String> {
72 let decoded = encryption.decode();
73
74 self.salt = Some(unsafe {
75 let enc = match CString::new(decoded) {
76 Ok(o) => o,
77 Err(e) => return Err(format!("Failed to create C string: {e}"))
78 };
79 CString::from(
80 CStr::from_ptr(raw::crypt_gensalt(enc.as_ptr(), 15, std::ptr::null(), 0))
81 )
82 });
83
84 Ok(())
85 }
86
87 /// Encrypt data. Encrypted data can be accessed in the `encrypted` field of Crypt struct.
88 /// ```
89 /// use libcrypt_rs::{Crypt, Encryptions};
90 ///
91 /// let mut engine = Crypt::new();
92 /// engine.gen_salt(Encryptions::Sha256).expect("Salt generation failed");
93 ///
94 /// engine.encrypt("example_phrase".to_string()).expect("Encryption failed");
95 ///
96 /// println!("Encrypted data: {}", engine.encrypted);
97 pub fn encrypt(&mut self, encrypt: String) -> Result<(), String> {
98 if let None = self.salt {
99 return Err("Salt hasn't been set".to_string());
100 }
101
102 let enc = match CString::new(encrypt) {
103 Ok(o) => o,
104 Err(e) => return Err(format!("Failed to allocate C string: {e}"))
105 };
106 let ptr = unsafe {
107 raw::crypt(enc.clone().as_ptr(), self.salt.clone().unwrap().as_ptr())
108 };
109
110 self.encrypted = unsafe {
111 match CStr::from_ptr(ptr).to_str() {
112 Err(e) => return Err(format!("Failed to encode C string: {e}")),
113 Ok(o) => o.to_string(),
114 }
115 };
116
117 Ok(())
118 }
119
120 /// `salt` is a private field of Crypt struct, using this function.
121 pub fn get_salt(&self) -> Result<String, String> {
122 match self.salt.clone().unwrap().to_str() {
123 Err(e) => return Err(format!("Failed to encode C string: {e}")),
124 Ok(o) => Ok(o.to_string())
125 }
126 }
127}