| 1 | pub const fn sha1(data: &ConstBuffer) -> Digest { |
| 2 | let state: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; |
| 3 | let len: u64 = 0; |
| 4 | let blocks: Blocks = Blocks { |
| 5 | len: 0, |
| 6 | data: [0; 64], |
| 7 | }; |
| 8 | let (blocks: Blocks, len: u64, state: [u32; 5]) = process_blocks(blocks, data, len, state); |
| 9 | digest(state, len, blocks) |
| 10 | } |
| 11 | |
| 12 | const BUFFER_SIZE: usize = 1024; |
| 13 | |
| 14 | pub struct ConstBuffer { |
| 15 | data: [u8; BUFFER_SIZE], |
| 16 | head: usize, |
| 17 | } |
| 18 | |
| 19 | impl ConstBuffer { |
| 20 | pub const fn for_class<C: crate::RuntimeName, I: crate::RuntimeType>() -> Self { |
| 21 | Self::new() |
| 22 | .push_slice(b"rc(" ) |
| 23 | .push_slice(C::NAME.as_bytes()) |
| 24 | .push(b';' ) |
| 25 | .push_other(I::SIGNATURE) |
| 26 | .push(b')' ) |
| 27 | } |
| 28 | |
| 29 | pub const fn for_interface<T: crate::Interface>() -> Self { |
| 30 | Self::new().push_guid(&T::IID) |
| 31 | } |
| 32 | |
| 33 | pub const fn from_slice(slice: &[u8]) -> Self { |
| 34 | let s = Self::new(); |
| 35 | s.push_slice(slice) |
| 36 | } |
| 37 | |
| 38 | pub const fn new() -> Self { |
| 39 | Self { |
| 40 | data: [0; BUFFER_SIZE], |
| 41 | head: 0, |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | pub const fn push_slice(self, slice: &[u8]) -> Self { |
| 46 | self.push_amount(slice, slice.len()) |
| 47 | } |
| 48 | |
| 49 | const fn get(&self, index: usize) -> u8 { |
| 50 | self.data[index] |
| 51 | } |
| 52 | |
| 53 | const fn len(&self) -> usize { |
| 54 | self.head |
| 55 | } |
| 56 | |
| 57 | pub fn as_slice(&self) -> &[u8] { |
| 58 | &self.data[..self.head] |
| 59 | } |
| 60 | |
| 61 | pub const fn push_other(self, other: Self) -> Self { |
| 62 | self.push_amount(&other.data, other.len()) |
| 63 | } |
| 64 | |
| 65 | const fn push(mut self, value: u8) -> Self { |
| 66 | self.data[self.head] = value; |
| 67 | self.head += 1; |
| 68 | self |
| 69 | } |
| 70 | |
| 71 | const fn push_hex_u8(self, value: u8) -> Self { |
| 72 | const fn digit(mut value: u8) -> u8 { |
| 73 | value &= 0xF; |
| 74 | |
| 75 | if value < 10 { |
| 76 | b'0' + value |
| 77 | } else { |
| 78 | b'a' + (value - 10) |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | self.push(digit(value >> 4)).push(digit(value)) |
| 83 | } |
| 84 | |
| 85 | const fn push_hex_u16(self, value: u16) -> Self { |
| 86 | self.push_hex_u8((value >> 8) as u8) |
| 87 | .push_hex_u8((value & 0xFF) as u8) |
| 88 | } |
| 89 | |
| 90 | const fn push_hex_u32(self, value: u32) -> Self { |
| 91 | self.push_hex_u16((value >> 16) as u16) |
| 92 | .push_hex_u16((value & 0xFFFF) as u16) |
| 93 | } |
| 94 | |
| 95 | const fn push_amount(mut self, slice: &[u8], amount: usize) -> Self { |
| 96 | let mut i = 0; |
| 97 | while i < amount { |
| 98 | self.data[self.head + i] = slice[i]; |
| 99 | i += 1; |
| 100 | } |
| 101 | self.head += i; |
| 102 | self |
| 103 | } |
| 104 | |
| 105 | const fn push_guid(self, guid: &crate::GUID) -> Self { |
| 106 | self.push(b'{' ) |
| 107 | .push_hex_u32(guid.data1) |
| 108 | .push(b'-' ) |
| 109 | .push_hex_u16(guid.data2) |
| 110 | .push(b'-' ) |
| 111 | .push_hex_u16(guid.data3) |
| 112 | .push(b'-' ) |
| 113 | .push_hex_u16(((guid.data4[0] as u16) << 8) | guid.data4[1] as u16) |
| 114 | .push(b'-' ) |
| 115 | .push_hex_u16(((guid.data4[2] as u16) << 8) | guid.data4[3] as u16) |
| 116 | .push_hex_u16(((guid.data4[4] as u16) << 8) | guid.data4[5] as u16) |
| 117 | .push_hex_u16(((guid.data4[6] as u16) << 8) | guid.data4[7] as u16) |
| 118 | .push(b'}' ) |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | struct Blocks { |
| 123 | len: u32, |
| 124 | data: [u8; 64], |
| 125 | } |
| 126 | |
| 127 | const fn process_blocks( |
| 128 | mut blocks: Blocks, |
| 129 | data: &ConstBuffer, |
| 130 | mut len: u64, |
| 131 | mut state: [u32; 5], |
| 132 | ) -> (Blocks, u64, [u32; 5]) { |
| 133 | const fn as_block(input: &ConstBuffer, offset: usize) -> [u32; 16] { |
| 134 | let mut result = [0u32; 16]; |
| 135 | |
| 136 | let mut i = 0; |
| 137 | while i != 16 { |
| 138 | let off = offset + (i * 4); |
| 139 | result[i] = (input.get(off + 3) as u32) |
| 140 | | ((input.get(off + 2) as u32) << 8) |
| 141 | | ((input.get(off + 1) as u32) << 16) |
| 142 | | ((input.get(off) as u32) << 24); |
| 143 | i += 1; |
| 144 | } |
| 145 | result |
| 146 | } |
| 147 | |
| 148 | const fn clone_from_slice_64( |
| 149 | mut data: [u8; 64], |
| 150 | slice: &[u8], |
| 151 | offset: usize, |
| 152 | num_elems: usize, |
| 153 | ) -> [u8; 64] { |
| 154 | let mut i = 0; |
| 155 | while i < num_elems { |
| 156 | data[i] = slice[offset + i]; |
| 157 | i += 1; |
| 158 | } |
| 159 | data |
| 160 | } |
| 161 | |
| 162 | let mut i = 0; |
| 163 | while i < data.len() { |
| 164 | if data.len() - i >= 64 { |
| 165 | let chunk_block = as_block(data, i); |
| 166 | len += 64; |
| 167 | state = process_state(state, chunk_block); |
| 168 | i += 64; |
| 169 | } else { |
| 170 | let num_elems = data.len() - i; |
| 171 | blocks.data = clone_from_slice_64(blocks.data, &data.data, i, num_elems); |
| 172 | blocks.len = num_elems as u32; |
| 173 | break; |
| 174 | } |
| 175 | } |
| 176 | (blocks, len, state) |
| 177 | } |
| 178 | |
| 179 | const fn process_state(mut state: [u32; 5], block: [u32; 16]) -> [u32; 5] { |
| 180 | let a = state[0]; |
| 181 | let b = state[1]; |
| 182 | let c = state[2]; |
| 183 | let d = state[3]; |
| 184 | let e = state[4]; |
| 185 | let (block, b, e) = r0(block, a, b, c, d, e, 0); |
| 186 | let (block, a, d) = r0(block, e, a, b, c, d, 1); |
| 187 | let (block, e, c) = r0(block, d, e, a, b, c, 2); |
| 188 | let (block, d, b) = r0(block, c, d, e, a, b, 3); |
| 189 | let (block, c, a) = r0(block, b, c, d, e, a, 4); |
| 190 | let (block, b, e) = r0(block, a, b, c, d, e, 5); |
| 191 | let (block, a, d) = r0(block, e, a, b, c, d, 6); |
| 192 | let (block, e, c) = r0(block, d, e, a, b, c, 7); |
| 193 | let (block, d, b) = r0(block, c, d, e, a, b, 8); |
| 194 | let (block, c, a) = r0(block, b, c, d, e, a, 9); |
| 195 | let (block, b, e) = r0(block, a, b, c, d, e, 10); |
| 196 | let (block, a, d) = r0(block, e, a, b, c, d, 11); |
| 197 | let (block, e, c) = r0(block, d, e, a, b, c, 12); |
| 198 | let (block, d, b) = r0(block, c, d, e, a, b, 13); |
| 199 | let (block, c, a) = r0(block, b, c, d, e, a, 14); |
| 200 | let (block, b, e) = r0(block, a, b, c, d, e, 15); |
| 201 | let (block, a, d) = r1(block, e, a, b, c, d, 0); |
| 202 | let (block, e, c) = r1(block, d, e, a, b, c, 1); |
| 203 | let (block, d, b) = r1(block, c, d, e, a, b, 2); |
| 204 | let (block, c, a) = r1(block, b, c, d, e, a, 3); |
| 205 | let (block, b, e) = r2(block, a, b, c, d, e, 4); |
| 206 | let (block, a, d) = r2(block, e, a, b, c, d, 5); |
| 207 | let (block, e, c) = r2(block, d, e, a, b, c, 6); |
| 208 | let (block, d, b) = r2(block, c, d, e, a, b, 7); |
| 209 | let (block, c, a) = r2(block, b, c, d, e, a, 8); |
| 210 | let (block, b, e) = r2(block, a, b, c, d, e, 9); |
| 211 | let (block, a, d) = r2(block, e, a, b, c, d, 10); |
| 212 | let (block, e, c) = r2(block, d, e, a, b, c, 11); |
| 213 | let (block, d, b) = r2(block, c, d, e, a, b, 12); |
| 214 | let (block, c, a) = r2(block, b, c, d, e, a, 13); |
| 215 | let (block, b, e) = r2(block, a, b, c, d, e, 14); |
| 216 | let (block, a, d) = r2(block, e, a, b, c, d, 15); |
| 217 | let (block, e, c) = r2(block, d, e, a, b, c, 0); |
| 218 | let (block, d, b) = r2(block, c, d, e, a, b, 1); |
| 219 | let (block, c, a) = r2(block, b, c, d, e, a, 2); |
| 220 | let (block, b, e) = r2(block, a, b, c, d, e, 3); |
| 221 | let (block, a, d) = r2(block, e, a, b, c, d, 4); |
| 222 | let (block, e, c) = r2(block, d, e, a, b, c, 5); |
| 223 | let (block, d, b) = r2(block, c, d, e, a, b, 6); |
| 224 | let (block, c, a) = r2(block, b, c, d, e, a, 7); |
| 225 | let (block, b, e) = r3(block, a, b, c, d, e, 8); |
| 226 | let (block, a, d) = r3(block, e, a, b, c, d, 9); |
| 227 | let (block, e, c) = r3(block, d, e, a, b, c, 10); |
| 228 | let (block, d, b) = r3(block, c, d, e, a, b, 11); |
| 229 | let (block, c, a) = r3(block, b, c, d, e, a, 12); |
| 230 | let (block, b, e) = r3(block, a, b, c, d, e, 13); |
| 231 | let (block, a, d) = r3(block, e, a, b, c, d, 14); |
| 232 | let (block, e, c) = r3(block, d, e, a, b, c, 15); |
| 233 | let (block, d, b) = r3(block, c, d, e, a, b, 0); |
| 234 | let (block, c, a) = r3(block, b, c, d, e, a, 1); |
| 235 | let (block, b, e) = r3(block, a, b, c, d, e, 2); |
| 236 | let (block, a, d) = r3(block, e, a, b, c, d, 3); |
| 237 | let (block, e, c) = r3(block, d, e, a, b, c, 4); |
| 238 | let (block, d, b) = r3(block, c, d, e, a, b, 5); |
| 239 | let (block, c, a) = r3(block, b, c, d, e, a, 6); |
| 240 | let (block, b, e) = r3(block, a, b, c, d, e, 7); |
| 241 | let (block, a, d) = r3(block, e, a, b, c, d, 8); |
| 242 | let (block, e, c) = r3(block, d, e, a, b, c, 9); |
| 243 | let (block, d, b) = r3(block, c, d, e, a, b, 10); |
| 244 | let (block, c, a) = r3(block, b, c, d, e, a, 11); |
| 245 | let (block, b, e) = r4(block, a, b, c, d, e, 12); |
| 246 | let (block, a, d) = r4(block, e, a, b, c, d, 13); |
| 247 | let (block, e, c) = r4(block, d, e, a, b, c, 14); |
| 248 | let (block, d, b) = r4(block, c, d, e, a, b, 15); |
| 249 | let (block, c, a) = r4(block, b, c, d, e, a, 0); |
| 250 | let (block, b, e) = r4(block, a, b, c, d, e, 1); |
| 251 | let (block, a, d) = r4(block, e, a, b, c, d, 2); |
| 252 | let (block, e, c) = r4(block, d, e, a, b, c, 3); |
| 253 | let (block, d, b) = r4(block, c, d, e, a, b, 4); |
| 254 | let (block, c, a) = r4(block, b, c, d, e, a, 5); |
| 255 | let (block, b, e) = r4(block, a, b, c, d, e, 6); |
| 256 | let (block, a, d) = r4(block, e, a, b, c, d, 7); |
| 257 | let (block, e, c) = r4(block, d, e, a, b, c, 8); |
| 258 | let (block, d, b) = r4(block, c, d, e, a, b, 9); |
| 259 | let (block, c, a) = r4(block, b, c, d, e, a, 10); |
| 260 | let (block, b, e) = r4(block, a, b, c, d, e, 11); |
| 261 | let (block, a, d) = r4(block, e, a, b, c, d, 12); |
| 262 | let (block, e, c) = r4(block, d, e, a, b, c, 13); |
| 263 | let (block, d, b) = r4(block, c, d, e, a, b, 14); |
| 264 | let (_, c, a) = r4(block, b, c, d, e, a, 15); |
| 265 | |
| 266 | state[0] = state[0].wrapping_add(a); |
| 267 | state[1] = state[1].wrapping_add(b); |
| 268 | state[2] = state[2].wrapping_add(c); |
| 269 | state[3] = state[3].wrapping_add(d); |
| 270 | state[4] = state[4].wrapping_add(e); |
| 271 | state |
| 272 | } |
| 273 | |
| 274 | const fn digest(mut state: [u32; 5], len: u64, blocks: Blocks) -> Digest { |
| 275 | const fn clone_from_slice_128( |
| 276 | mut data: [u8; 128], |
| 277 | slice: &[u8], |
| 278 | offset: usize, |
| 279 | num_elems: usize, |
| 280 | ) -> [u8; 128] { |
| 281 | let mut i = 0; |
| 282 | while i < num_elems { |
| 283 | data[i] = slice[offset + i]; |
| 284 | i += 1; |
| 285 | } |
| 286 | data |
| 287 | } |
| 288 | |
| 289 | const fn clone_slice_128(mut data: [u8; 128], slice: &[u8], _offset: usize) -> [u8; 128] { |
| 290 | let mut i = 0; |
| 291 | while i < slice.len() { |
| 292 | data[_offset + i] = slice[i]; |
| 293 | i += 1; |
| 294 | } |
| 295 | data |
| 296 | } |
| 297 | |
| 298 | const fn as_block(input: &[u8], offset: usize) -> [u32; 16] { |
| 299 | let mut result = [0u32; 16]; |
| 300 | |
| 301 | let mut i = 0; |
| 302 | while i != 16 { |
| 303 | let off = offset + (i * 4); |
| 304 | result[i] = (input[off + 3] as u32) |
| 305 | | ((input[off + 2] as u32) << 8) |
| 306 | | ((input[off + 1] as u32) << 16) |
| 307 | | ((input[off] as u32) << 24); |
| 308 | i += 1; |
| 309 | } |
| 310 | result |
| 311 | } |
| 312 | |
| 313 | let bits = (len + (blocks.len as u64)) * 8; |
| 314 | let extra = [ |
| 315 | (bits >> 56) as u8, |
| 316 | (bits >> 48) as u8, |
| 317 | (bits >> 40) as u8, |
| 318 | (bits >> 32) as u8, |
| 319 | (bits >> 24) as u8, |
| 320 | (bits >> 16) as u8, |
| 321 | (bits >> 8) as u8, |
| 322 | bits as u8, |
| 323 | ]; |
| 324 | let mut last = [0; 128]; |
| 325 | let blocklen = blocks.len as usize; |
| 326 | last = clone_from_slice_128(last, &blocks.data, 0, blocklen); |
| 327 | last[blocklen] = 0x80; |
| 328 | |
| 329 | if blocklen < 56 { |
| 330 | last = clone_slice_128(last, &extra, 56); |
| 331 | state = process_state(state, as_block(&last, 0)); |
| 332 | } else { |
| 333 | last = clone_slice_128(last, &extra, 120); |
| 334 | state = process_state(state, as_block(&last, 0)); |
| 335 | state = process_state(state, as_block(&last, 64)); |
| 336 | } |
| 337 | Digest { data: state } |
| 338 | } |
| 339 | |
| 340 | const fn rol(value: u32, bits: usize) -> u32 { |
| 341 | (value << bits) | (value >> (32 - bits)) |
| 342 | } |
| 343 | |
| 344 | const fn blk(block: &[u32], i: usize) -> u32 { |
| 345 | let value: u32 = block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i]; |
| 346 | rol(value, bits:1) |
| 347 | } |
| 348 | |
| 349 | const fn r0( |
| 350 | block: [u32; 16], |
| 351 | v: u32, |
| 352 | mut w: u32, |
| 353 | x: u32, |
| 354 | y: u32, |
| 355 | mut z: u32, |
| 356 | i: usize, |
| 357 | ) -> ([u32; 16], u32, u32) { |
| 358 | let n: u32 = ((w & (x ^ y)) ^ y) |
| 359 | .wrapping_add(block[i]) |
| 360 | .wrapping_add(0x5a82_7999) |
| 361 | .wrapping_add(rol(value:v, bits:5)); |
| 362 | z = z.wrapping_add(n); |
| 363 | w = rol(value:w, bits:30); |
| 364 | (block, w, z) |
| 365 | } |
| 366 | |
| 367 | const fn r1( |
| 368 | mut block: [u32; 16], |
| 369 | v: u32, |
| 370 | mut w: u32, |
| 371 | x: u32, |
| 372 | y: u32, |
| 373 | mut z: u32, |
| 374 | i: usize, |
| 375 | ) -> ([u32; 16], u32, u32) { |
| 376 | block[i] = blk(&block, i); |
| 377 | let n: u32 = ((w & (x ^ y)) ^ y) |
| 378 | .wrapping_add(block[i]) |
| 379 | .wrapping_add(0x5a82_7999) |
| 380 | .wrapping_add(rol(value:v, bits:5)); |
| 381 | z = z.wrapping_add(n); |
| 382 | w = rol(value:w, bits:30); |
| 383 | (block, w, z) |
| 384 | } |
| 385 | |
| 386 | const fn r2( |
| 387 | mut block: [u32; 16], |
| 388 | v: u32, |
| 389 | mut w: u32, |
| 390 | x: u32, |
| 391 | y: u32, |
| 392 | mut z: u32, |
| 393 | i: usize, |
| 394 | ) -> ([u32; 16], u32, u32) { |
| 395 | block[i] = blk(&block, i); |
| 396 | let n: u32 = (w ^ x ^ y) |
| 397 | .wrapping_add(block[i]) |
| 398 | .wrapping_add(0x6ed9_eba1) |
| 399 | .wrapping_add(rol(value:v, bits:5)); |
| 400 | z = z.wrapping_add(n); |
| 401 | w = rol(value:w, bits:30); |
| 402 | (block, w, z) |
| 403 | } |
| 404 | |
| 405 | const fn r3( |
| 406 | mut block: [u32; 16], |
| 407 | v: u32, |
| 408 | mut w: u32, |
| 409 | x: u32, |
| 410 | y: u32, |
| 411 | mut z: u32, |
| 412 | i: usize, |
| 413 | ) -> ([u32; 16], u32, u32) { |
| 414 | block[i] = blk(&block, i); |
| 415 | let n: u32 = (((w | x) & y) | (w & x)) |
| 416 | .wrapping_add(block[i]) |
| 417 | .wrapping_add(0x8f1b_bcdc) |
| 418 | .wrapping_add(rol(value:v, bits:5)); |
| 419 | z = z.wrapping_add(n); |
| 420 | w = rol(value:w, bits:30); |
| 421 | (block, w, z) |
| 422 | } |
| 423 | |
| 424 | const fn r4( |
| 425 | mut block: [u32; 16], |
| 426 | v: u32, |
| 427 | mut w: u32, |
| 428 | x: u32, |
| 429 | y: u32, |
| 430 | mut z: u32, |
| 431 | i: usize, |
| 432 | ) -> ([u32; 16], u32, u32) { |
| 433 | block[i] = blk(&block, i); |
| 434 | let n: u32 = (w ^ x ^ y) |
| 435 | .wrapping_add(block[i]) |
| 436 | .wrapping_add(0xca62_c1d6) |
| 437 | .wrapping_add(rol(value:v, bits:5)); |
| 438 | z = z.wrapping_add(n); |
| 439 | w = rol(value:w, bits:30); |
| 440 | (block, w, z) |
| 441 | } |
| 442 | |
| 443 | pub struct Digest { |
| 444 | data: [u32; 5], |
| 445 | } |
| 446 | |
| 447 | impl Digest { |
| 448 | pub const fn bytes(&self) -> [u8; 20] { |
| 449 | [ |
| 450 | (self.data[0] >> 24) as u8, |
| 451 | (self.data[0] >> 16) as u8, |
| 452 | (self.data[0] >> 8) as u8, |
| 453 | self.data[0] as u8, |
| 454 | (self.data[1] >> 24) as u8, |
| 455 | (self.data[1] >> 16) as u8, |
| 456 | (self.data[1] >> 8) as u8, |
| 457 | self.data[1] as u8, |
| 458 | (self.data[2] >> 24) as u8, |
| 459 | (self.data[2] >> 16) as u8, |
| 460 | (self.data[2] >> 8) as u8, |
| 461 | self.data[2] as u8, |
| 462 | (self.data[3] >> 24) as u8, |
| 463 | (self.data[3] >> 16) as u8, |
| 464 | (self.data[3] >> 8) as u8, |
| 465 | self.data[3] as u8, |
| 466 | (self.data[4] >> 24) as u8, |
| 467 | (self.data[4] >> 16) as u8, |
| 468 | (self.data[4] >> 8) as u8, |
| 469 | self.data[4] as u8, |
| 470 | ] |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | impl core::fmt::Display for Digest { |
| 475 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| 476 | for i: &u32 in self.data.iter() { |
| 477 | write!(f, " {:08x}" , i)?; |
| 478 | } |
| 479 | Ok(()) |
| 480 | } |
| 481 | } |
| 482 | |