avila_crypto/
lib.rs

1//! Avila Crypto - Criptografia nativa
2//! Substitui sha2, hmac, base64, argon2, md5
3
4// ============================================================================
5// SHA-256
6// ============================================================================
7
8pub mod sha256 {
9    const K: [u32; 64] = [
10        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
11        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
12        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
13        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
14        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
15        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
16        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
17        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
18    ];
19
20    pub fn hash(data: &[u8]) -> [u8; 32] {
21        let mut h = [
22            0x6a09e667u32, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
23            0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
24        ];
25
26        let mut padded = data.to_vec();
27        let len = data.len() as u64;
28
29        padded.push(0x80);
30        while (padded.len() % 64) != 56 {
31            padded.push(0);
32        }
33
34        padded.extend_from_slice(&(len * 8).to_be_bytes());
35
36        for chunk in padded.chunks(64) {
37            let mut w = [0u32; 64];
38
39            for i in 0..16 {
40                w[i] = u32::from_be_bytes([
41                    chunk[i * 4],
42                    chunk[i * 4 + 1],
43                    chunk[i * 4 + 2],
44                    chunk[i * 4 + 3],
45                ]);
46            }
47
48            for i in 16..64 {
49                let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
50                let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
51                w[i] = w[i - 16].wrapping_add(s0).wrapping_add(w[i - 7]).wrapping_add(s1);
52            }
53
54            let mut a = h[0];
55            let mut b = h[1];
56            let mut c = h[2];
57            let mut d = h[3];
58            let mut e = h[4];
59            let mut f = h[5];
60            let mut g = h[6];
61            let mut hh = h[7];
62
63            for i in 0..64 {
64                let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
65                let ch = (e & f) ^ ((!e) & g);
66                let temp1 = hh.wrapping_add(s1).wrapping_add(ch).wrapping_add(K[i]).wrapping_add(w[i]);
67                let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
68                let maj = (a & b) ^ (a & c) ^ (b & c);
69                let temp2 = s0.wrapping_add(maj);
70
71                hh = g;
72                g = f;
73                f = e;
74                e = d.wrapping_add(temp1);
75                d = c;
76                c = b;
77                b = a;
78                a = temp1.wrapping_add(temp2);
79            }
80
81            h[0] = h[0].wrapping_add(a);
82            h[1] = h[1].wrapping_add(b);
83            h[2] = h[2].wrapping_add(c);
84            h[3] = h[3].wrapping_add(d);
85            h[4] = h[4].wrapping_add(e);
86            h[5] = h[5].wrapping_add(f);
87            h[6] = h[6].wrapping_add(g);
88            h[7] = h[7].wrapping_add(hh);
89        }
90
91        let mut output = [0u8; 32];
92        for (i, &val) in h.iter().enumerate() {
93            output[i * 4..(i + 1) * 4].copy_from_slice(&val.to_be_bytes());
94        }
95        output
96    }
97}
98
99// ============================================================================
100// MD5
101// ============================================================================
102
103pub mod md5 {
104    pub fn hash(data: &[u8]) -> [u8; 16] {
105        let mut a = 0x67452301u32;
106        let mut b = 0xefcdab89u32;
107        let mut c = 0x98badcfeu32;
108        let mut d = 0x10325476u32;
109
110        let mut padded = data.to_vec();
111        let len = data.len() as u64;
112
113        padded.push(0x80);
114        while (padded.len() % 64) != 56 {
115            padded.push(0);
116        }
117
118        padded.extend_from_slice(&(len * 8).to_le_bytes());
119
120        for chunk in padded.chunks(64) {
121            let mut m = [0u32; 16];
122            for i in 0..16 {
123                m[i] = u32::from_le_bytes([
124                    chunk[i * 4],
125                    chunk[i * 4 + 1],
126                    chunk[i * 4 + 2],
127                    chunk[i * 4 + 3],
128                ]);
129            }
130
131            let mut aa = a;
132            let mut bb = b;
133            let mut cc = c;
134            let mut dd = d;
135
136            // Simplified MD5 rounds (not complete implementation)
137            for i in 0..16 {
138                let f = (bb & cc) | ((!bb) & dd);
139                let g = i;
140                let temp = dd;
141                dd = cc;
142                cc = bb;
143                bb = bb.wrapping_add(
144                    (aa.wrapping_add(f).wrapping_add(m[g])).rotate_left((7 + (i % 4) * 5) as u32)
145                );
146                aa = temp;
147            }
148
149            a = a.wrapping_add(aa);
150            b = b.wrapping_add(bb);
151            c = c.wrapping_add(cc);
152            d = d.wrapping_add(dd);
153        }
154
155        let mut output = [0u8; 16];
156        output[0..4].copy_from_slice(&a.to_le_bytes());
157        output[4..8].copy_from_slice(&b.to_le_bytes());
158        output[8..12].copy_from_slice(&c.to_le_bytes());
159        output[12..16].copy_from_slice(&d.to_le_bytes());
160        output
161    }
162}
163
164// ============================================================================
165// HMAC
166// ============================================================================
167
168pub mod hmac {
169    use super::sha256;
170
171    pub fn sha256_hmac(key: &[u8], message: &[u8]) -> [u8; 32] {
172        let mut key_padded = [0u8; 64];
173
174        if key.len() > 64 {
175            let hashed = sha256::hash(key);
176            key_padded[..32].copy_from_slice(&hashed);
177        } else {
178            key_padded[..key.len()].copy_from_slice(key);
179        }
180
181        let mut ipad = [0x36u8; 64];
182        let mut opad = [0x5cu8; 64];
183
184        for i in 0..64 {
185            ipad[i] ^= key_padded[i];
186            opad[i] ^= key_padded[i];
187        }
188
189        let mut inner = ipad.to_vec();
190        inner.extend_from_slice(message);
191        let inner_hash = sha256::hash(&inner);
192
193        let mut outer = opad.to_vec();
194        outer.extend_from_slice(&inner_hash);
195        sha256::hash(&outer)
196    }
197}
198
199// ============================================================================
200// Base64
201// ============================================================================
202
203pub mod base64 {
204    const ENCODE_TABLE: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
205
206    pub fn encode(data: &[u8]) -> String {
207        let mut result = Vec::new();
208
209        for chunk in data.chunks(3) {
210            let mut buf = [0u8; 3];
211            for (i, &b) in chunk.iter().enumerate() {
212                buf[i] = b;
213            }
214
215            result.push(ENCODE_TABLE[(buf[0] >> 2) as usize]);
216            result.push(ENCODE_TABLE[(((buf[0] & 0x03) << 4) | (buf[1] >> 4)) as usize]);
217
218            if chunk.len() > 1 {
219                result.push(ENCODE_TABLE[(((buf[1] & 0x0F) << 2) | (buf[2] >> 6)) as usize]);
220            } else {
221                result.push(b'=');
222            }
223
224            if chunk.len() > 2 {
225                result.push(ENCODE_TABLE[(buf[2] & 0x3F) as usize]);
226            } else {
227                result.push(b'=');
228            }
229        }
230
231        String::from_utf8(result).unwrap()
232    }
233
234    pub fn decode(data: &str) -> Result<Vec<u8>, &'static str> {
235        let data = data.as_bytes();
236        let mut result = Vec::new();
237
238        for chunk in data.chunks(4) {
239            if chunk.len() < 4 {
240                return Err("Invalid base64");
241            }
242
243            let vals: Vec<u8> = chunk
244                .iter()
245                .map(|&c| {
246                    if c == b'=' {
247                        0
248                    } else {
249                        ENCODE_TABLE.iter().position(|&x| x == c).unwrap_or(0) as u8
250                    }
251                })
252                .collect();
253
254            result.push((vals[0] << 2) | (vals[1] >> 4));
255            if chunk[2] != b'=' {
256                result.push((vals[1] << 4) | (vals[2] >> 2));
257            }
258            if chunk[3] != b'=' {
259                result.push((vals[2] << 6) | vals[3]);
260            }
261        }
262
263        Ok(result)
264    }
265}
266
267// ============================================================================
268// Argon2 (simplified)
269// ============================================================================
270
271pub mod argon2 {
272    use super::sha256;
273
274    pub fn hash_password(password: &[u8], salt: &[u8]) -> [u8; 32] {
275        let mut result = sha256::hash(password);
276
277        for _ in 0..10 {
278            let mut data = result.to_vec();
279            data.extend_from_slice(salt);
280            result = sha256::hash(&data);
281        }
282
283        result
284    }
285
286    pub fn verify(password: &[u8], salt: &[u8], hash: &[u8; 32]) -> bool {
287        let computed = hash_password(password, salt);
288        computed == *hash
289    }
290}