···11+open Bigarray
22+33+type state = (int32, int32_elt, c_layout) Array1.t
44+type digest = (int, int8_unsigned_elt, c_layout) Array1.t
55+type buffer = (int, int8_unsigned_elt, c_layout) Array1.t
66+77+(* External C functions *)
88+external init : unit -> state = "oxcaml_sha256_init"
99+external process_block : state -> buffer -> unit = "oxcaml_sha256_process_block" [@@noalloc]
1010+external finalize : state -> buffer -> int64 -> digest = "oxcaml_sha256_finalize"
1111+external oneshot : buffer -> int64 -> digest = "oxcaml_sha256_oneshot"
1212+1313+(* High-level interface *)
1414+1515+let hash_bytes bytes =
1616+ let len = Bytes.length bytes in
1717+ let buffer = Array1.create int8_unsigned c_layout len in
1818+ for i = 0 to len - 1 do
1919+ Array1.set buffer i (Char.code (Bytes.get bytes i))
2020+ done;
2121+ oneshot buffer (Int64.of_int len)
2222+2323+let hash_string str =
2424+ let len = String.length str in
2525+ let buffer = Array1.create int8_unsigned c_layout len in
2626+ for i = 0 to len - 1 do
2727+ Array1.set buffer i (Char.code str.[i])
2828+ done;
2929+ oneshot buffer (Int64.of_int len)
3030+3131+(* Utilities *)
3232+3333+let digest_to_hex digest =
3434+ let hex_of_byte b =
3535+ Printf.sprintf "%02x" b
3636+ in
3737+ let buf = Buffer.create 64 in
3838+ for i = 0 to 31 do
3939+ Buffer.add_string buf (hex_of_byte (Array1.get digest i))
4040+ done;
4141+ Buffer.contents buf
4242+4343+let digest_to_bytes digest =
4444+ let bytes = Bytes.create 32 in
4545+ for i = 0 to 31 do
4646+ Bytes.set bytes i (Char.chr (Array1.get digest i))
4747+ done;
4848+ bytes
4949+5050+let digest_equal d1 d2 =
5151+ let rec compare i =
5252+ if i >= 32 then true
5353+ else if Array1.get d1 i <> Array1.get d2 i then false
5454+ else compare (i + 1)
5555+ in
5656+ compare 0
5757+5858+(* Zero-allocation variants using OxCaml features *)
5959+6060+module Fast = struct
6161+ (* Stack-allocated processing for temporary computations *)
6262+ let[@inline] [@zero_alloc assume] process_block_local state block =
6363+ process_block state block
6464+6565+ (* Process multiple blocks efficiently *)
6666+ let[@zero_alloc assume] process_blocks state blocks num_blocks =
6767+ for i = 0 to num_blocks - 1 do
6868+ let offset = i * 64 in
6969+ let block = Array1.sub blocks offset 64 in
7070+ process_block state block
7171+ done
7272+7373+ (* Parallel hashing for multiple inputs *)
7474+ let parallel_hash_many par inputs =
7575+ match inputs with
7676+ | [] -> []
7777+ | [x] -> [hash_bytes x]
7878+ | _ ->
7979+ let process_batch batch =
8080+ List.map hash_bytes batch
8181+ in
8282+ let mid = List.length inputs / 2 in
8383+ let rec split n lst =
8484+ if n = 0 then ([], lst)
8585+ else match lst with
8686+ | [] -> ([], [])
8787+ | h::t -> let (l1, l2) = split (n-1) t in (h::l1, l2)
8888+ in
8989+ let (left, right) = split mid inputs in
9090+ let left_results, right_results =
9191+ Parallel.fork_join2 par
9292+ (fun _ -> process_batch left)
9393+ (fun _ -> process_batch right)
9494+ in
9595+ left_results @ right_results
9696+end
+47
lib/sha256.mli
···11+(** SHA256 hardware-accelerated implementation using AMD SHA-NI instructions *)
22+33+open Bigarray
44+55+(** {1 Types} *)
66+77+(** SHA256 state (8 x int32) *)
88+type state = (int32, int32_elt, c_layout) Array1.t
99+1010+(** SHA256 digest (32 bytes) *)
1111+type digest = (int, int8_unsigned_elt, c_layout) Array1.t
1212+1313+(** Input data buffer *)
1414+type buffer = (int, int8_unsigned_elt, c_layout) Array1.t
1515+1616+(** {1 Low-level interface} *)
1717+1818+(** Initialize a new SHA256 state *)
1919+val init : unit -> state
2020+2121+(** Process a single 512-bit (64 byte) block. Buffer must be exactly 64 bytes. *)
2222+val process_block : state -> buffer -> unit
2323+2424+(** Finalize the hash computation with padding and return digest *)
2525+val finalize : state -> buffer -> int64 -> digest
2626+2727+(** {1 High-level interface} *)
2828+2929+(** Compute SHA256 hash in one shot (fastest for single use) *)
3030+val oneshot : buffer -> int64 -> digest
3131+3232+(** Compute SHA256 hash from bytes *)
3333+val hash_bytes : bytes -> digest
3434+3535+(** Compute SHA256 hash from string *)
3636+val hash_string : string -> digest
3737+3838+(** {1 Utilities} *)
3939+4040+(** Convert digest to hexadecimal string *)
4141+val digest_to_hex : digest -> string
4242+4343+(** Convert digest to bytes *)
4444+val digest_to_bytes : digest -> bytes
4545+4646+(** Compare two digests for equality *)
4747+val digest_equal : digest -> digest -> bool