blazehash 0.2.4

Forensic file hasher — hashdeep for the modern era, BLAKE3 by default
Documentation
// MD5 compute shader (little-endian)
// Input: padded MD5 message as little-endian u32 words
// Output: 4 u32 words (little-endian digest)

struct Params {
    num_blocks: u32,
}

@group(0) @binding(0) var<storage, read>       msg:    array<u32>;
@group(0) @binding(1) var<storage, read_write> digest: array<u32>;
@group(0) @binding(2) var<uniform>             params: Params;

fn rotl(x: u32, n: u32) -> u32 { return (x << n) | (x >> (32u - n)); }
fn F(b: u32, c: u32, d: u32) -> u32 { return (b & c) | (~b & d); }
fn G(b: u32, c: u32, d: u32) -> u32 { return (b & d) | (c & ~d); }
fn H(b: u32, c: u32, d: u32) -> u32 { return b ^ c ^ d; }
fn I(b: u32, c: u32, d: u32) -> u32 { return c ^ (b | ~d); }

fn t_val(i: u32) -> u32 {
    switch i {
        case 0u: { return 0xd76aa478u; }
        case 1u: { return 0xe8c7b756u; }
        case 2u: { return 0x242070dbu; }
        case 3u: { return 0xc1bdceeeu; }
        case 4u: { return 0xf57c0fafu; }
        case 5u: { return 0x4787c62au; }
        case 6u: { return 0xa8304613u; }
        case 7u: { return 0xfd469501u; }
        case 8u: { return 0x698098d8u; }
        case 9u: { return 0x8b44f7afu; }
        case 10u: { return 0xffff5bb1u; }
        case 11u: { return 0x895cd7beu; }
        case 12u: { return 0x6b901122u; }
        case 13u: { return 0xfd987193u; }
        case 14u: { return 0xa679438eu; }
        case 15u: { return 0x49b40821u; }
        case 16u: { return 0xf61e2562u; }
        case 17u: { return 0xc040b340u; }
        case 18u: { return 0x265e5a51u; }
        case 19u: { return 0xe9b6c7aau; }
        case 20u: { return 0xd62f105du; }
        case 21u: { return 0x02441453u; }
        case 22u: { return 0xd8a1e681u; }
        case 23u: { return 0xe7d3fbc8u; }
        case 24u: { return 0x21e1cde6u; }
        case 25u: { return 0xc33707d6u; }
        case 26u: { return 0xf4d50d87u; }
        case 27u: { return 0x455a14edu; }
        case 28u: { return 0xa9e3e905u; }
        case 29u: { return 0xfcefa3f8u; }
        case 30u: { return 0x676f02d9u; }
        case 31u: { return 0x8d2a4c8au; }
        case 32u: { return 0xfffa3942u; }
        case 33u: { return 0x8771f681u; }
        case 34u: { return 0x6d9d6122u; }
        case 35u: { return 0xfde5380cu; }
        case 36u: { return 0xa4beea44u; }
        case 37u: { return 0x4bdecfa9u; }
        case 38u: { return 0xf6bb4b60u; }
        case 39u: { return 0xbebfbc70u; }
        case 40u: { return 0x289b7ec6u; }
        case 41u: { return 0xeaa127fau; }
        case 42u: { return 0xd4ef3085u; }
        case 43u: { return 0x04881d05u; }
        case 44u: { return 0xd9d4d039u; }
        case 45u: { return 0xe6db99e5u; }
        case 46u: { return 0x1fa27cf8u; }
        case 47u: { return 0xc4ac5665u; }
        case 48u: { return 0xf4292244u; }
        case 49u: { return 0x432aff97u; }
        case 50u: { return 0xab9423a7u; }
        case 51u: { return 0xfc93a039u; }
        case 52u: { return 0x655b59c3u; }
        case 53u: { return 0x8f0ccc92u; }
        case 54u: { return 0xffeff47du; }
        case 55u: { return 0x85845dd1u; }
        case 56u: { return 0x6fa87e4fu; }
        case 57u: { return 0xfe2ce6e0u; }
        case 58u: { return 0xa3014314u; }
        case 59u: { return 0x4e0811a1u; }
        case 60u: { return 0xf7537e82u; }
        case 61u: { return 0xbd3af235u; }
        case 62u: { return 0x2ad7d2bbu; }
        case 63u: { return 0xeb86d391u; }
        default: { return 0u; }
    }
}

fn s_val(i: u32) -> u32 {
    // Shift amounts derived from round (i % 4) — same pattern repeats every 4 steps per round
    // Round 1 (i < 16): 7,12,17,22
    // Round 2 (i < 32): 5,9,14,20
    // Round 3 (i < 48): 4,11,16,23
    // Round 4 (i < 64): 6,10,15,21
    let j = i % 4u;
    if i < 16u {
        switch j {
            case 0u: { return 7u; }
            case 1u: { return 12u; }
            case 2u: { return 17u; }
            default: { return 22u; }
        }
    } else if i < 32u {
        switch j {
            case 0u: { return 5u; }
            case 1u: { return 9u; }
            case 2u: { return 14u; }
            default: { return 20u; }
        }
    } else if i < 48u {
        switch j {
            case 0u: { return 4u; }
            case 1u: { return 11u; }
            case 2u: { return 16u; }
            default: { return 23u; }
        }
    } else {
        switch j {
            case 0u: { return 6u; }
            case 1u: { return 10u; }
            case 2u: { return 15u; }
            default: { return 21u; }
        }
    }
}

@compute @workgroup_size(1)
fn main() {
    var a0: u32 = 0x67452301u;
    var b0: u32 = 0xefcdab89u;
    var c0: u32 = 0x98badcfeu;
    var d0: u32 = 0x10325476u;

    for (var blk: u32 = 0u; blk < params.num_blocks; blk++) {
        let base: u32 = blk * 16u;

        var M: array<u32, 16>;
        for (var i: u32 = 0u; i < 16u; i++) {
            M[i] = msg[base + i];
        }

        var A: u32 = a0;
        var B: u32 = b0;
        var C: u32 = c0;
        var D: u32 = d0;

        for (var i: u32 = 0u; i < 64u; i++) {
            var f_val: u32;
            var g: u32;
            if i < 16u {
                f_val = F(B, C, D);
                g = i;
            } else if i < 32u {
                f_val = G(B, C, D);
                g = (5u * i + 1u) % 16u;
            } else if i < 48u {
                f_val = H(B, C, D);
                g = (3u * i + 5u) % 16u;
            } else {
                f_val = I(B, C, D);
                g = (7u * i) % 16u;
            }

            let temp: u32 = D;
            D = C;
            C = B;
            B = B + rotl(A + f_val + t_val(i) + M[g], s_val(i));
            A = temp;
        }

        a0 += A;
        b0 += B;
        c0 += C;
        d0 += D;
    }

    digest[0] = a0;
    digest[1] = b0;
    digest[2] = c0;
    digest[3] = d0;
}