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}