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}