crypt_ro/lib.rs
1//! A cryptographic library providing matrix-based encryption and decryption.
2//!
3//! This library implements a custom encryption scheme using:
4//! - Matrix transformations with configurable size
5//! - Key-derived shuffling operations
6//! - Random padding and mixing operations
7//! - URL-safe base64 encoding for text operations
8//!
9//! # Features
10//! - Configurable matrix size for transformation blocks
11//! - Both raw byte and text-friendly operations
12//! - Key-based encryption/decryption
13//! - Randomized padding for better security
14//!
15//! # Examples
16//!
17//! Basic usage:
18//!
19//! ```
20//! use crypt_ro::Cryptor;
21//!
22//! let cryptor = Cryptor::new();
23//! let secret = "my secret message";
24//! let key = "strong password";
25//!
26//! // Encrypt and decrypt text
27//! let encrypted = cryptor.encrypt_text(secret, key).unwrap();
28//! let decrypted = cryptor.decrypt_text(&encrypted, key).unwrap();
29//!
30//! assert_eq!(decrypted, secret);
31//!
32//! // Using custom matrix size
33//! let mut cryptor = Cryptor::new();
34//! cryptor.set_matrix(64); // Use larger blocks
35//! let encrypted = cryptor.encrypt_text(secret, key).unwrap();
36//! let decrypted = cryptor.decrypt_text(&encrypted, key).unwrap();
37//!
38//! assert_eq!(decrypted, secret);
39//! ```
40//!
41//! Working with raw bytes:
42//!
43//! ```
44//! use crypt_ro::Cryptor;
45//!
46//! let cryptor = Cryptor::new();
47//! let data = b"binary data \x01\x02\x03";
48//! let key = "encryption key";
49//!
50//! let encrypted = cryptor.encrypt(data, key).unwrap();
51//! let decrypted = cryptor.decrypt(&encrypted, key).unwrap();
52//!
53//! assert_eq!(decrypted.as_bytes(), data);
54//! ```
55
56mod util;
57
58use base64::{engine::general_purpose::URL_SAFE, Engine as _};
59use std::error::Error;
60use crate::util::{generate_password, get_random_bytes, mix, shuffle, unmix, unshuffle};
61
62/// A cryptographic utility for encrypting and decrypting text using a matrix-based transformation.
63///
64/// The `Cryptor` uses a combination of shuffling, mixing, and matrix operations to obscure the
65/// original text. It supports configurable matrix sizes for the transformation process.
66///
67/// # Examples
68///
69/// ```
70/// use crypt_ro::Cryptor;
71///
72/// let cryptor = Cryptor::new();
73/// let encrypted = cryptor.encrypt_text("secret message", "password").unwrap();
74/// let decrypted = cryptor.decrypt_text(&encrypted, "password").unwrap();
75/// assert_eq!(decrypted, "secret message");
76/// ```
77pub struct Cryptor {
78 matrix: usize,
79}
80
81impl Cryptor {
82 /// Creates a new `Cryptor` instance with default matrix size (32).
83 pub fn new() -> Self {
84 Self { matrix: 32 }
85 }
86
87 /// Encrypts raw bytes using the provided key.
88 ///
89 /// # Arguments
90 /// * `data` - The bytes to encrypt
91 /// * `key` - The encryption key
92 ///
93 /// # Returns
94 /// A `Result` containing the encrypted bytes or an error if encryption fails.
95 ///
96 /// # Example
97 /// ```
98 /// use crypt_ro::Cryptor;
99 ///
100 /// let cryptor = Cryptor::new();
101 /// let encrypted = cryptor.encrypt(b"secret data", "key123").unwrap();
102 /// assert!(!encrypted.is_empty());
103 /// ```
104 pub fn encrypt(&self, data: &[u8], key: &str) -> Result<Vec<u8>, Box<dyn Error>> {
105 let matrix_size=self.matrix;
106 let key_bytes = generate_password(matrix_size,key.as_bytes());
107 let data_size = (data.len() as u16).to_be_bytes();
108 let random_prefix = get_random_bytes(6);
109
110 let mut padded_text = Vec::with_capacity(8 + data.len());
111 padded_text.extend_from_slice(&data_size);
112 padded_text.extend_from_slice(&random_prefix);
113 padded_text.extend_from_slice(data);
114
115 let seed_sum: u64 = key_bytes.iter().map(|&b| b as u64).sum();
116 shuffle(&mut padded_text,seed_sum,5);
117
118 let mut matrix = padded_text.chunks_exact_mut(matrix_size).collect::<Vec<_>>();
119 let matrix_len=matrix.len();
120
121 for i in 0..matrix_len {
122 let seed = match matrix.get(i+1) {
123 None => {
124 key_bytes[0] as u64}
125 Some(a) => {
126 a[0] as u64
127 }
128 };
129 shuffle(&mut matrix[i], seed,2);
130 }
131
132 mix(matrix_size,&mut padded_text, &key_bytes);
133 Ok(padded_text)
134 }
135
136
137 /// Encrypts raw bytes using the provided key.
138 ///
139 /// # Arguments
140 /// * `text` - The plaintext to encrypt
141 /// * `key` - The encryption key
142 ///
143 /// # Returns
144 /// A `Result` URL-safe base64 string without padding or an error if encryption fails.
145 ///
146 /// # Example
147 /// ```
148 /// use crypt_ro::Cryptor;
149 ///
150 /// let cryptor = Cryptor::new();
151 /// let encrypted = cryptor.encrypt_text("secret message", "password").unwrap();
152 /// assert!(!encrypted.contains('/')); // URL-safe
153 pub fn encrypt_text(&self, text: &str, key: &str) -> Result<String, Box<dyn Error>> {
154 Ok(URL_SAFE.encode(self.encrypt(text.as_bytes(), key)?).trim_end_matches('=').to_string())
155 }
156
157 /// Decrypts bytes using the provided key.
158 ///
159 /// # Arguments
160 /// * `encoded` - The encrypted bytes to decrypt
161 /// * `key` - The decryption key
162 ///
163 /// # Returns
164 /// A `Result` containing the decrypted bytes or an error if decryption fails.
165 ///
166 /// # Example
167 /// ```
168 /// use crypt_ro::Cryptor;
169 ///
170 /// let cryptor = Cryptor::new();
171 /// let encrypted = cryptor.encrypt(b"data", "key").unwrap();
172 /// let decrypted = cryptor.decrypt(&encrypted, "key").unwrap();
173 /// assert_eq!(decrypted, b"data");
174 /// ```
175 pub fn decrypt(&self, encoded: &Vec<u8>, key: &str) -> Result<Vec<u8>, Box<dyn Error>> {
176 let mut decoded = encoded.clone();
177 let matrix_size=self.matrix;
178
179 let key_bytes = generate_password(matrix_size,key.as_bytes());
180 unmix(matrix_size,&mut decoded, &key_bytes);
181 let mut matrix = decoded.chunks_exact_mut(matrix_size).collect::<Vec<_>>();
182 let matrix_len=matrix.len();
183 for i in (0..matrix_len).rev() {
184 let seed = match matrix.get(i + 1) {
185 None => {key_bytes[0] as u64}
186 Some(a) => {a[0] as u64}
187 };
188 unshuffle(&mut matrix[i], seed,2);
189 }
190
191
192 let seed_sum: u64 = key_bytes.iter().map(|&b| b as u64).sum();
193 unshuffle(&mut decoded, seed_sum,5);
194
195 let data_size = u16::from_be_bytes([decoded[0], decoded[1]]) as usize;
196 if decoded.len() < data_size+8 {
197 return Err("Invalid Token Matrix Length".into());
198 }
199 let result_bytes = &decoded[8..data_size+8];
200 Ok(result_bytes.to_vec())
201 }
202
203 /// Decrypts a URL-safe base64 encoded string using the provided key.
204 ///
205 /// # Arguments
206 /// * `encoded` - A URL-safe base64 encoded string to decrypt
207 /// * `key` - The decryption key
208 ///
209 /// # Returns
210 /// A `Result` containing the decrypted string or an error if decryption fails.
211 ///
212 /// # Example
213 /// ```
214 /// use crypt_ro::Cryptor;
215 ///
216 /// let cryptor = Cryptor::new();
217 /// let encrypted = cryptor.encrypt_text("message", "pass").unwrap();
218 /// let decrypted = cryptor.decrypt_text(&encrypted, "pass").unwrap();
219 /// assert_eq!(decrypted, "message");
220 /// ```
221 pub fn decrypt_text(&self, encoded: &str, key: &str) -> Result<String, Box<dyn Error>> {
222 let mut input = encoded.to_string();
223 let padding = input.len() % 4;
224 if padding != 0 {
225 input.push_str(&"=".repeat(4 - padding));
226 }
227
228 let data = URL_SAFE.decode(&input)?;
229 let result = String::from_utf8(self.decrypt(&data, &key)?)?
230 .to_string();
231 Ok(result)
232 }
233
234 /// Sets the matrix size used for cryptographic operations.
235 ///
236 /// The matrix size determines how data is chunked and processed during encryption/decryption.
237 /// Must be a positive non-zero value.
238 ///
239 /// # Example
240 /// ```
241 /// use crypt_ro::Cryptor;
242 ///
243 /// let mut cryptor = Cryptor::new();
244 /// cryptor.set_matrix(64); // Use larger blocks
245 /// ```
246 pub fn set_matrix(&mut self, size: usize) {
247 if size>0{
248 self.matrix = size;
249 }
250 }
251}