1pub 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
99pub 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 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
164pub 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
199pub 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
267pub 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}