-module(packkit@checksum). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/packkit/checksum.gleam"). -export([sha256_init/0, adler32/1, adler32_continue/2, crc32/1, crc32_continue/2, crc32c/1, bzip2_crc32/1, crc64_xz/1, snappy_mask/1, sha256_finalize/1, sha256_update/2, sha256/1, sha1/1, hmac_sha1/2, pbkdf2_hmac_sha1/4]). -export_type([sha256_state/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Adler-32 and CRC-32 checksums used by zlib (RFC 1950) and gzip\n" " (RFC 1952).\n" "\n" " The implementations are pure Gleam and behave identically on the\n" " Erlang and JavaScript targets.\n" ). -opaque sha256_state() :: {sha256_state, integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), bitstring(), integer()}. -file("src/packkit/checksum.gleam", 52). -spec adler32_chunk(bitstring(), integer(), integer(), integer()) -> {bitstring(), integer(), integer()}. adler32_chunk(Data, Remaining, S1, S2) -> case {Remaining, Data} of {0, _} -> {Data, S1, S2}; {_, <>} -> S1@1 = S1 + B, S2@1 = S2 + S1@1, adler32_chunk(Rest, Remaining - 1, S1@1, S2@1); {_, _} -> {Data, S1, S2} end. -file("src/packkit/checksum.gleam", 69). -spec combine_adler(integer(), integer()) -> integer(). combine_adler(S1, S2) -> erlang:'bor'(erlang:'bsl'(S2, 16), S1). -file("src/packkit/checksum.gleam", 184). -spec crc64_nibble_low(integer()) -> integer(). crc64_nibble_low(Index) -> case Index of 0 -> 16#00000000; 1 -> 16#51336649; 2 -> 16#A266CC92; 3 -> 16#F355AADB; 4 -> 16#EBC387A1; 5 -> 16#BAF0E1E8; 6 -> 16#49A54B33; 7 -> 16#18962D7A; 8 -> 16#D7870F42; 9 -> 16#86B4690B; 10 -> 16#75E1C3D0; 11 -> 16#24D2A599; 12 -> 16#3C4488E3; 13 -> 16#6D77EEAA; 14 -> 16#9E224471; _ -> 16#CF112238 end. -file("src/packkit/checksum.gleam", 205). -spec crc64_nibble_high(integer()) -> integer(). crc64_nibble_high(Index) -> case Index of 0 -> 16#00000000; 1 -> 16#7D9BA138; 2 -> 16#FB374270; 3 -> 16#86ACE348; 4 -> 16#64B62BCA; 5 -> 16#192D8AF2; 6 -> 16#9F8169BA; 7 -> 16#E21AC882; 8 -> 16#C96C5795; 9 -> 16#B4F7F6AD; 10 -> 16#325B15E5; 11 -> 16#4FC0B4DD; 12 -> 16#ADDA7C5F; 13 -> 16#D041DD67; 14 -> 16#56ED3E2F; _ -> 16#2B769F17 end. -file("src/packkit/checksum.gleam", 255). -spec crc32_nibble(integer()) -> integer(). crc32_nibble(Index) -> case Index of 0 -> 16#00000000; 1 -> 16#1DB71064; 2 -> 16#3B6E20C8; 3 -> 16#26D930AC; 4 -> 16#76DC4190; 5 -> 16#6B6B51F4; 6 -> 16#4DB26158; 7 -> 16#5005713C; 8 -> 16#EDB88320; 9 -> 16#F00F9344; 10 -> 16#D6D6A3E8; 11 -> 16#CB61B38C; 12 -> 16#9B64C2B0; 13 -> 16#86D3D2D4; 14 -> 16#A00AE278; _ -> 16#BDBDF21C end. -file("src/packkit/checksum.gleam", 249). -spec step4(integer()) -> integer(). step4(Crc) -> Low = erlang:'band'(Crc, 15), Shifted = erlang:'bsr'(Crc, 4), erlang:'bxor'(crc32_nibble(Low), Shifted). -file("src/packkit/checksum.gleam", 237). -spec crc32_loop(bitstring(), integer()) -> integer(). crc32_loop(Data, Crc) -> case Data of <> -> Crc@1 = erlang:'bxor'(Crc, B), Crc@2 = step4(Crc@1), Crc@3 = step4(Crc@2), crc32_loop(Rest, Crc@3); _ -> Crc end. -file("src/packkit/checksum.gleam", 294). -spec crc32c_nibble(integer()) -> integer(). crc32c_nibble(Index) -> case Index of 0 -> 16#00000000; 1 -> 16#105EC76F; 2 -> 16#20BD8EDE; 3 -> 16#30E349B1; 4 -> 16#417B1DBC; 5 -> 16#5125DAD3; 6 -> 16#61C69362; 7 -> 16#7198540D; 8 -> 16#82F63B78; 9 -> 16#92A8FC17; 10 -> 16#A24BB5A6; 11 -> 16#B21572C9; 12 -> 16#C38D26C4; 13 -> 16#D3D3E1AB; 14 -> 16#E330A81A; _ -> 16#F36E6F75 end. -file("src/packkit/checksum.gleam", 288). -spec step4_c(integer()) -> integer(). step4_c(Crc) -> Low = erlang:'band'(Crc, 15), Shifted = erlang:'bsr'(Crc, 4), erlang:'bxor'(crc32c_nibble(Low), Shifted). -file("src/packkit/checksum.gleam", 276). -spec crc32c_loop(bitstring(), integer()) -> integer(). crc32c_loop(Data, Crc) -> case Data of <> -> Crc@1 = erlang:'bxor'(Crc, B), Crc@2 = step4_c(Crc@1), Crc@3 = step4_c(Crc@2), crc32c_loop(Rest, Crc@3); _ -> Crc end. -file("src/packkit/checksum.gleam", 315). -spec mod(integer(), integer()) -> integer(). mod(Value, Divisor) -> Value - ((case Divisor of 0 -> 0; Gleam@denominator -> Value div Gleam@denominator end) * Divisor). -file("src/packkit/checksum.gleam", 348). ?DOC( " Fresh SHA-256 state using the FIPS 180-4 §5.3.3 initial hash\n" " constants.\n" ). -spec sha256_init() -> sha256_state(). sha256_init() -> {sha256_state, 16#6A09E667, 16#BB67AE85, 16#3C6EF372, 16#A54FF53A, 16#510E527F, 16#9B05688C, 16#1F83D9AB, 16#5BE0CD19, <<>>, 0}. -file("src/packkit/checksum.gleam", 500). -spec pad_zeros(integer(), bitstring()) -> bitstring(). pad_zeros(Count, Acc) -> case Count of 0 -> Acc; _ -> pad_zeros(Count - 1, gleam_stdlib:bit_array_concat([Acc, <<0>>])) end. -file("src/packkit/checksum.gleam", 487). ?DOC( " Pad `data` to a multiple of 64 bytes following FIPS 180-4 §5.1.1:\n" " append `0x80`, then enough `0x00` to leave 8 bytes for the\n" " 64-bit big-endian bit-length.\n" ). -spec sha256_pad(bitstring()) -> bitstring(). sha256_pad(Data) -> Len = erlang:byte_size(Data), Bit_len = Len * 8, Mod_len = mod(Len + 9, 64), Zeros = case Mod_len of 0 -> 0; N -> 64 - N end, Padding = pad_zeros(Zeros, <<>>), gleam_stdlib:bit_array_concat( [Data, <<16#80>>, Padding, <>] ). -file("src/packkit/checksum.gleam", 606). -spec nth_from_head(list(integer()), integer()) -> integer(). nth_from_head(List_value, Index) -> case {List_value, Index} of {[Head | _], 0} -> Head; {[_ | Rest], N} -> nth_from_head(Rest, N - 1); {[], _} -> 0 end. -file("src/packkit/checksum.gleam", 698). -spec sha256_k(integer()) -> integer(). sha256_k(Round) -> case Round of 0 -> 16#428A2F98; 1 -> 16#71374491; 2 -> 16#B5C0FBCF; 3 -> 16#E9B5DBA5; 4 -> 16#3956C25B; 5 -> 16#59F111F1; 6 -> 16#923F82A4; 7 -> 16#AB1C5ED5; 8 -> 16#D807AA98; 9 -> 16#12835B01; 10 -> 16#243185BE; 11 -> 16#550C7DC3; 12 -> 16#72BE5D74; 13 -> 16#80DEB1FE; 14 -> 16#9BDC06A7; 15 -> 16#C19BF174; 16 -> 16#E49B69C1; 17 -> 16#EFBE4786; 18 -> 16#0FC19DC6; 19 -> 16#240CA1CC; 20 -> 16#2DE92C6F; 21 -> 16#4A7484AA; 22 -> 16#5CB0A9DC; 23 -> 16#76F988DA; 24 -> 16#983E5152; 25 -> 16#A831C66D; 26 -> 16#B00327C8; 27 -> 16#BF597FC7; 28 -> 16#C6E00BF3; 29 -> 16#D5A79147; 30 -> 16#06CA6351; 31 -> 16#14292967; 32 -> 16#27B70A85; 33 -> 16#2E1B2138; 34 -> 16#4D2C6DFC; 35 -> 16#53380D13; 36 -> 16#650A7354; 37 -> 16#766A0ABB; 38 -> 16#81C2C92E; 39 -> 16#92722C85; 40 -> 16#A2BFE8A1; 41 -> 16#A81A664B; 42 -> 16#C24B8B70; 43 -> 16#C76C51A3; 44 -> 16#D192E819; 45 -> 16#D6990624; 46 -> 16#F40E3585; 47 -> 16#106AA070; 48 -> 16#19A4C116; 49 -> 16#1E376C08; 50 -> 16#2748774C; 51 -> 16#34B0BCB5; 52 -> 16#391C0CB3; 53 -> 16#4ED8AA4A; 54 -> 16#5B9CCA4F; 55 -> 16#682E6FF3; 56 -> 16#748F82EE; 57 -> 16#78A5636F; 58 -> 16#84C87814; 59 -> 16#8CC70208; 60 -> 16#90BEFFFA; 61 -> 16#A4506CEB; 62 -> 16#BEF9A3F7; _ -> 16#C67178F2 end. -file("src/packkit/checksum.gleam", 948). -spec xor_with_byte_loop(bitstring(), integer(), bitstring()) -> bitstring(). xor_with_byte_loop(Data, Mask, Acc) -> case Data of <> -> Mixed = erlang:'bxor'(B, Mask), xor_with_byte_loop( Rest, Mask, gleam_stdlib:bit_array_concat([Acc, <>]) ); _ -> Acc end. -file("src/packkit/checksum.gleam", 944). -spec xor_with_byte(bitstring(), integer()) -> bitstring(). xor_with_byte(Key_block, Mask) -> xor_with_byte_loop(Key_block, Mask, <<>>). -file("src/packkit/checksum.gleam", 1042). -spec xor_bit_arrays_loop(bitstring(), bitstring(), bitstring()) -> bitstring(). xor_bit_arrays_loop(Left, Right, Acc) -> case {Left, Right} of {<>, <>} -> Mixed = erlang:'bxor'(L, R), xor_bit_arrays_loop( L_rest, R_rest, gleam_stdlib:bit_array_concat([Acc, <>]) ); {_, _} -> Acc end. -file("src/packkit/checksum.gleam", 1038). -spec xor_bit_arrays(bitstring(), bitstring()) -> bitstring(). xor_bit_arrays(Left, Right) -> xor_bit_arrays_loop(Left, Right, <<>>). -file("src/packkit/checksum.gleam", 36). -spec adler32_loop(bitstring(), integer(), integer(), integer()) -> integer(). adler32_loop(Data, Remaining, S1, S2) -> case Remaining of 0 -> combine_adler(S1, S2); _ -> K = case Remaining < 5552 of true -> Remaining; false -> 5552 end, {Rest, New_s1, New_s2} = adler32_chunk(Data, K, S1, S2), New_s1@1 = mod(New_s1, 65521), New_s2@1 = mod(New_s2, 65521), adler32_loop(Rest, Remaining - K, New_s1@1, New_s2@1) end. -file("src/packkit/checksum.gleam", 23). ?DOC( " Compute the Adler-32 checksum of `data`, returning the canonical\n" " 32-bit value `(s2 << 16) | s1`.\n" ). -spec adler32(bitstring()) -> integer(). adler32(Data) -> Length = erlang:byte_size(Data), adler32_loop(Data, Length, 1, 0). -file("src/packkit/checksum.gleam", 29). ?DOC(" Continue an Adler-32 computation from a previous checksum value.\n"). -spec adler32_continue(integer(), bitstring()) -> integer(). adler32_continue(Previous, Data) -> S1 = erlang:'band'(Previous, 65535), S2 = erlang:'band'(erlang:'bsr'(Previous, 16), 65535), Length = erlang:byte_size(Data), adler32_loop(Data, Length, S1, S2). -file("src/packkit/checksum.gleam", 75). ?DOC( " Compute the CRC-32 checksum of `data` using the IEEE 802.3 reflected\n" " polynomial `0xEDB88320` and the same final XOR as zlib's `crc32`.\n" ). -spec crc32(bitstring()) -> integer(). crc32(Data) -> Crc = crc32_loop(Data, 4294967295), erlang:'band'(erlang:'bxor'(Crc, 4294967295), 4294967295). -file("src/packkit/checksum.gleam", 81). ?DOC(" Continue a CRC-32 computation from a previous checksum value.\n"). -spec crc32_continue(integer(), bitstring()) -> integer(). crc32_continue(Previous, Data) -> Crc = erlang:'bxor'(erlang:'band'(Previous, 4294967295), 4294967295), Crc@1 = crc32_loop(Data, Crc), erlang:'band'(erlang:'bxor'(Crc@1, 4294967295), 4294967295). -file("src/packkit/checksum.gleam", 91). ?DOC( " Compute the CRC-32C (Castagnoli) checksum of `data` using the\n" " reflected polynomial `0x82F63B78`. CRC-32C underlies the masked\n" " checksums in Snappy's frame format.\n" ). -spec crc32c(bitstring()) -> integer(). crc32c(Data) -> Crc = crc32c_loop(Data, 4294967295), erlang:'band'(erlang:'bxor'(Crc, 4294967295), 4294967295). -file("src/packkit/checksum.gleam", 131). -spec bzip2_step_bit(integer()) -> integer(). bzip2_step_bit(Crc) -> Shifted = erlang:'band'(erlang:'bsl'(Crc, 1), 4294967295), case erlang:'band'(Crc, 16#80000000) of 0 -> Shifted; _ -> erlang:'bxor'(Shifted, 16#04C11DB7) end. -file("src/packkit/checksum.gleam", 120). -spec bzip2_step_byte(integer()) -> integer(). bzip2_step_byte(Crc) -> _pipe = bzip2_step_bit(Crc), _pipe@1 = bzip2_step_bit(_pipe), _pipe@2 = bzip2_step_bit(_pipe@1), _pipe@3 = bzip2_step_bit(_pipe@2), _pipe@4 = bzip2_step_bit(_pipe@3), _pipe@5 = bzip2_step_bit(_pipe@4), _pipe@6 = bzip2_step_bit(_pipe@5), bzip2_step_bit(_pipe@6). -file("src/packkit/checksum.gleam", 107). -spec bzip2_crc32_loop(bitstring(), integer()) -> integer(). bzip2_crc32_loop(Data, Crc) -> case Data of <> -> Crc@1 = begin _pipe = erlang:'bxor'(Crc, erlang:'bsl'(B, 24)), erlang:'band'(_pipe, 4294967295) end, Crc@2 = bzip2_step_byte(Crc@1), bzip2_crc32_loop(Rest, Crc@2); _ -> Crc end. -file("src/packkit/checksum.gleam", 102). ?DOC( " Compute the bzip2 CRC-32 of `data`.\n" "\n" " bzip2 reuses the IEEE 802.3 polynomial `0x04C11DB7` but processes\n" " each byte MSB-first (without reflection) and XORs the final value\n" " with `0xFFFFFFFF`, matching the per-block and stream CRC fields\n" " that appear in `.bz2` files.\n" ). -spec bzip2_crc32(bitstring()) -> integer(). bzip2_crc32(Data) -> Crc = bzip2_crc32_loop(Data, 4294967295), erlang:'band'(erlang:'bxor'(Crc, 4294967295), 4294967295). -file("src/packkit/checksum.gleam", 168). -spec crc64_step4(integer(), integer()) -> {integer(), integer()}. crc64_step4(Low, High) -> Nibble = erlang:'band'(Low, 15), New_low = erlang:'bor'( erlang:'bsr'(Low, 4), erlang:'band'(erlang:'bsl'(High, 28), 4294967295) ), New_high = erlang:'bsr'(High, 4), {erlang:'bxor'(New_low, crc64_nibble_low(Nibble)), erlang:'bxor'(New_high, crc64_nibble_high(Nibble))}. -file("src/packkit/checksum.gleam", 156). -spec crc64_loop(bitstring(), integer(), integer()) -> {integer(), integer()}. crc64_loop(Data, Low, High) -> case Data of <> -> Low@1 = erlang:'bxor'(Low, B), {Low@2, High@1} = crc64_step4(Low@1, High), {Low@3, High@2} = crc64_step4(Low@2, High@1), crc64_loop(Rest, Low@3, High@2); _ -> {Low, High} end. -file("src/packkit/checksum.gleam", 148). ?DOC( " Compute the CRC-64 (ECMA-182, reflected) checksum of `data` used\n" " by the xz block-check field (`check_type = 4`, see RFC `xz-format`\n" " §2.1.1.2). Polynomial `0x42F0E1EBA9EA3693` reflected to\n" " `0xC96C5795D7870F42`, init / final-xor `0xFFFFFFFFFFFFFFFF`.\n" "\n" " The result is returned as a `#(low_u32, high_u32)` pair instead of\n" " a single 64-bit Int so the implementation stays exact on the\n" " JavaScript target, whose `Number` cannot safely represent the full\n" " 64-bit space and whose bitwise operators are 32-bit anyway.\n" ). -spec crc64_xz(bitstring()) -> {integer(), integer()}. crc64_xz(Data) -> {Low, High} = crc64_loop(Data, 4294967295, 4294967295), {erlang:'band'(erlang:'bxor'(Low, 4294967295), 4294967295), erlang:'band'(erlang:'bxor'(High, 4294967295), 4294967295)}. -file("src/packkit/checksum.gleam", 230). ?DOC( " Mask a CRC-32C value as Snappy's framing layer requires.\n" "\n" " The masking is `((crc >> 15) | (crc << 17)) + 0xa282ead8` taken\n" " modulo `2^32`.\n" ). -spec snappy_mask(integer()) -> integer(). snappy_mask(Crc) -> High = erlang:'bsr'(Crc, 15), Low = erlang:'band'(erlang:'bsl'(Crc, 17), 4294967295), Rotated = erlang:'bor'(High, Low), erlang:'band'(Rotated + 16#A282EAD8, 4294967295). -file("src/packkit/checksum.gleam", 660). -spec u32_add(integer(), integer()) -> integer(). u32_add(X, Y) -> erlang:'band'(X + Y, 4294967295). -file("src/packkit/checksum.gleam", 664). -spec u32_rotr(integer(), integer()) -> integer(). u32_rotr(X, N) -> Right = erlang:'bsr'(X, N), Left = erlang:'band'(erlang:'bsl'(X, 32 - N), 4294967295), erlang:'bor'(Right, Left). -file("src/packkit/checksum.gleam", 670). -spec sha256_small_sigma0(integer()) -> integer(). sha256_small_sigma0(X) -> erlang:'bxor'( erlang:'bxor'(u32_rotr(X, 7), u32_rotr(X, 18)), erlang:'bsr'(X, 3) ). -file("src/packkit/checksum.gleam", 677). -spec sha256_small_sigma1(integer()) -> integer(). sha256_small_sigma1(X) -> erlang:'bxor'( erlang:'bxor'(u32_rotr(X, 17), u32_rotr(X, 19)), erlang:'bsr'(X, 10) ). -file("src/packkit/checksum.gleam", 590). ?DOC( " Build W[0..63] in reverse order (newest at head) so the head of the\n" " list is `W[count - 1]`. When `count` reaches 64 we have the full\n" " schedule and the caller reverses it.\n" ). -spec expand_schedule(list(integer()), integer()) -> list(integer()). expand_schedule(Reversed, Count) -> case Count of 64 -> Reversed; _ -> W_m2 = nth_from_head(Reversed, 1), W_m7 = nth_from_head(Reversed, 6), W_m15 = nth_from_head(Reversed, 14), W_m16 = nth_from_head(Reversed, 15), S0 = sha256_small_sigma0(W_m15), S1 = sha256_small_sigma1(W_m2), Next = u32_add(u32_add(u32_add(W_m16, S0), W_m7), S1), expand_schedule([Next | Reversed], Count + 1) end. -file("src/packkit/checksum.gleam", 684). -spec sha256_big_sigma0(integer()) -> integer(). sha256_big_sigma0(X) -> erlang:'bxor'( erlang:'bxor'(u32_rotr(X, 2), u32_rotr(X, 13)), u32_rotr(X, 22) ). -file("src/packkit/checksum.gleam", 691). -spec sha256_big_sigma1(integer()) -> integer(). sha256_big_sigma1(X) -> erlang:'bxor'( erlang:'bxor'(u32_rotr(X, 6), u32_rotr(X, 11)), u32_rotr(X, 25) ). -file("src/packkit/checksum.gleam", 614). -spec sha256_compress( list(integer()), integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer() ) -> {integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer()}. sha256_compress(Schedule, Round, A, B, C, D, E, F, G, H) -> case Schedule of [] -> {A, B, C, D, E, F, G, H}; [W | Rest] -> S1 = sha256_big_sigma1(E), Ch = erlang:'bxor'( erlang:'band'(E, F), erlang:'band'(erlang:'bxor'(E, 4294967295), G) ), Temp1 = u32_add( u32_add(u32_add(u32_add(H, S1), Ch), sha256_k(Round)), W ), S0 = sha256_big_sigma0(A), Maj = erlang:'bxor'( erlang:'bxor'(erlang:'band'(A, B), erlang:'band'(A, C)), erlang:'band'(B, C) ), Temp2 = u32_add(S0, Maj), sha256_compress( Rest, Round + 1, u32_add(Temp1, Temp2), A, B, C, u32_add(D, Temp1), E, F, G ) end. -file("src/packkit/checksum.gleam", 507). -spec sha256_process_blocks( bitstring(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer() ) -> {integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer()}. sha256_process_blocks(Data, H0, H1, H2, H3, H4, H5, H6, H7) -> case Data of <<>> -> {H0, H1, H2, H3, H4, H5, H6, H7}; <> -> Initial = [W15, W14, W13, W12, W11, W10, W9, W8, W7, W6, W5, W4, W3, W2, W1, W0], Schedule = expand_schedule(Initial, 16), {A, B, C, D, E, F, G, H} = sha256_compress( lists:reverse(Schedule), 0, H0, H1, H2, H3, H4, H5, H6, H7 ), sha256_process_blocks( Rest, u32_add(H0, A), u32_add(H1, B), u32_add(H2, C), u32_add(H3, D), u32_add(H4, E), u32_add(H5, F), u32_add(H6, G), u32_add(H7, H) ); _ -> {H0, H1, H2, H3, H4, H5, H6, H7} end. -file("src/packkit/checksum.gleam", 399). ?DOC( " Apply FIPS 180-4 padding to whatever bytes are still buffered\n" " in `state`, process the final block(s), and return the 32-byte\n" " digest.\n" ). -spec sha256_finalize(sha256_state()) -> bitstring(). sha256_finalize(State) -> Bit_len = erlang:element(11, State) * 8, Buf_len = erlang:byte_size(erlang:element(10, State)), Mod_len = mod(Buf_len + 9, 64), Zeros = case Mod_len of 0 -> 0; N -> 64 - N end, Padding = pad_zeros(Zeros, <<>>), Final_block = gleam_stdlib:bit_array_concat( [erlang:element(10, State), <<16#80>>, Padding, <>] ), {H0, H1, H2, H3, H4, H5, H6, H7} = sha256_process_blocks( Final_block, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State) ), <>. -file("src/packkit/checksum.gleam", 434). -spec sha256_consume_blocks( bitstring(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer() ) -> {integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), bitstring()}. sha256_consume_blocks(Data, H0, H1, H2, H3, H4, H5, H6, H7) -> case Data of <> -> {A0, A1, A2, A3, A4, A5, A6, A7} = sha256_process_blocks( Block, H0, H1, H2, H3, H4, H5, H6, H7 ), sha256_consume_blocks(Rest, A0, A1, A2, A3, A4, A5, A6, A7); _ -> {H0, H1, H2, H3, H4, H5, H6, H7, Data} end. -file("src/packkit/checksum.gleam", 367). ?DOC( " Absorb `data` into the running SHA-256 state. Bytes accumulate\n" " in an internal buffer and full 64-byte blocks are consumed as\n" " soon as they're available, so callers may pass arbitrarily small\n" " chunks without blowing memory.\n" ). -spec sha256_update(sha256_state(), bitstring()) -> sha256_state(). sha256_update(State, Data) -> Combined = <<(erlang:element(10, State))/bitstring, Data/bitstring>>, New_total = erlang:element(11, State) + erlang:byte_size(Data), {H0, H1, H2, H3, H4, H5, H6, H7, Remainder} = sha256_consume_blocks( Combined, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State) ), {sha256_state, H0, H1, H2, H3, H4, H5, H6, H7, Remainder, New_total}. -file("src/packkit/checksum.gleam", 458). ?DOC( " Compute the SHA-256 digest of `data` and return the 32-byte digest\n" " as a `BitArray`. Used by the xz block-check field (`check_type =\n" " 10`).\n" ). -spec sha256(bitstring()) -> bitstring(). sha256(Data) -> Padded = sha256_pad(Data), {H0, H1, H2, H3, H4, H5, H6, H7} = sha256_process_blocks( Padded, 16#6A09E667, 16#BB67AE85, 16#3C6EF372, 16#A54FF53A, 16#510E527F, 16#9B05688C, 16#1F83D9AB, 16#5BE0CD19 ), <>. -file("src/packkit/checksum.gleam", 878). -spec sha1_round_constants(integer(), integer(), integer(), integer()) -> {integer(), integer()}. sha1_round_constants(Round, B, C, D) -> case Round of N when N < 20 -> {erlang:'bor'( erlang:'band'(B, C), erlang:'band'(erlang:'bxor'(B, 4294967295), D) ), 16#5A827999}; N@1 when N@1 < 40 -> {erlang:'bxor'(erlang:'bxor'(B, C), D), 16#6ED9EBA1}; N@2 when N@2 < 60 -> {erlang:'bor'( erlang:'bor'(erlang:'band'(B, C), erlang:'band'(B, D)), erlang:'band'(C, D) ), 16#8F1BBCDC}; _ -> {erlang:'bxor'(erlang:'bxor'(B, C), D), 16#CA62C1D6} end. -file("src/packkit/checksum.gleam", 905). -spec u32_rotl(integer(), integer()) -> integer(). u32_rotl(X, N) -> Left = erlang:'band'(erlang:'bsl'(X, N), 4294967295), Right = erlang:'bsr'(X, 32 - N), erlang:'bor'(Left, Right). -file("src/packkit/checksum.gleam", 841). -spec sha1_expand_schedule(list(integer()), integer()) -> list(integer()). sha1_expand_schedule(Reversed, Count) -> case Count of 80 -> Reversed; _ -> W3 = nth_from_head(Reversed, 2), W8 = nth_from_head(Reversed, 7), W14 = nth_from_head(Reversed, 13), W16 = nth_from_head(Reversed, 15), Mixed = erlang:'bxor'( erlang:'bxor'(W3, W8), erlang:'bxor'(W14, W16) ), sha1_expand_schedule([u32_rotl(Mixed, 1) | Reversed], Count + 1) end. -file("src/packkit/checksum.gleam", 859). -spec sha1_compress( list(integer()), integer(), integer(), integer(), integer(), integer(), integer() ) -> {integer(), integer(), integer(), integer(), integer()}. sha1_compress(Schedule, A, B, C, D, E, Round) -> case Schedule of [] -> {A, B, C, D, E}; [W | Rest] -> {F, K} = sha1_round_constants(Round, B, C, D), T = u32_add(u32_add(u32_add(u32_add(u32_rotl(A, 5), F), E), K), W), sha1_compress(Rest, T, A, u32_rotl(B, 30), C, D, Round + 1) end. -file("src/packkit/checksum.gleam", 791). -spec sha1_process_blocks( bitstring(), integer(), integer(), integer(), integer(), integer() ) -> {integer(), integer(), integer(), integer(), integer()}. sha1_process_blocks(Data, H0, H1, H2, H3, H4) -> case Data of <<>> -> {H0, H1, H2, H3, H4}; <> -> Schedule_reversed = [W15, W14, W13, W12, W11, W10, W9, W8, W7, W6, W5, W4, W3, W2, W1, W0], Full_reversed = sha1_expand_schedule(Schedule_reversed, 16), Full = lists:reverse(Full_reversed), {A, B, C, D, E} = sha1_compress(Full, H0, H1, H2, H3, H4, 0), sha1_process_blocks( Rest, u32_add(H0, A), u32_add(H1, B), u32_add(H2, C), u32_add(H3, D), u32_add(H4, E) ); _ -> {H0, H1, H2, H3, H4} end. -file("src/packkit/checksum.gleam", 777). ?DOC( " Compute the SHA-1 digest of `data` (FIPS 180-4 §6.1). Returns a\n" " 20-byte `BitArray`. Used by `hmac_sha1` for ZIP AE-x.\n" ). -spec sha1(bitstring()) -> bitstring(). sha1(Data) -> Padded = sha256_pad(Data), {H0, H1, H2, H3, H4} = sha1_process_blocks( Padded, 16#67452301, 16#EFCDAB89, 16#98BADCFE, 16#10325476, 16#C3D2E1F0 ), <>. -file("src/packkit/checksum.gleam", 930). -spec hmac_sha1_prepare_key(bitstring()) -> bitstring(). hmac_sha1_prepare_key(Key) -> Key_size = erlang:byte_size(Key), Normalised = case Key_size > 64 of true -> sha1(Key); false -> Key end, Normalised_size = erlang:byte_size(Normalised), Padding_len = 64 - Normalised_size, case Padding_len of 0 -> Normalised; _ -> gleam_stdlib:bit_array_concat( [Normalised, pad_zeros(Padding_len, <<>>)] ) end. -file("src/packkit/checksum.gleam", 922). ?DOC( " Compute the HMAC-SHA1 of `data` keyed by `key` (RFC 2104).\n" " Returns the 20-byte tag as a `BitArray`.\n" ). -spec hmac_sha1(bitstring(), bitstring()) -> bitstring(). hmac_sha1(Key, Data) -> Key_block = hmac_sha1_prepare_key(Key), Outer_pad = xor_with_byte(Key_block, 16#5C), Inner_pad = xor_with_byte(Key_block, 16#36), Inner = sha1(gleam_stdlib:bit_array_concat([Inner_pad, Data])), sha1(gleam_stdlib:bit_array_concat([Outer_pad, Inner])). -file("src/packkit/checksum.gleam", 1018). -spec pbkdf2_iterate(bitstring(), bitstring(), bitstring(), integer()) -> bitstring(). pbkdf2_iterate(Password, Previous, Accumulator, Remaining) -> case Remaining of 0 -> Accumulator; _ -> Next = hmac_sha1(Password, Previous), pbkdf2_iterate( Password, Next, xor_bit_arrays(Accumulator, Next), Remaining - 1 ) end. -file("src/packkit/checksum.gleam", 1004). -spec pbkdf2_one_block(bitstring(), bitstring(), integer(), integer()) -> bitstring(). pbkdf2_one_block(Password, Salt, Iterations, Index) -> Initial = hmac_sha1( Password, gleam_stdlib:bit_array_concat([Salt, <>]) ), pbkdf2_iterate(Password, Initial, Initial, Iterations - 1). -file("src/packkit/checksum.gleam", 984). -spec pbkdf2_blocks( bitstring(), bitstring(), integer(), integer(), integer(), bitstring() ) -> bitstring(). pbkdf2_blocks(Password, Salt, Iterations, Block_count, Index, Acc) -> gleam@bool:guard( Index > Block_count, Acc, fun() -> Block = pbkdf2_one_block(Password, Salt, Iterations, Index), pbkdf2_blocks( Password, Salt, Iterations, Block_count, Index + 1, gleam_stdlib:bit_array_concat([Acc, Block]) ) end ). -file("src/packkit/checksum.gleam", 969). ?DOC( " Derive `dk_len` bytes from `password` and `salt` via PBKDF2-HMAC-SHA1\n" " (RFC 2898). Used by the ZIP AE-x scheme with `iterations = 1000`\n" " and `dk_len = key_len * 2 + 2` (encryption key + HMAC key +\n" " 2-byte password verifier).\n" ). -spec pbkdf2_hmac_sha1(bitstring(), bitstring(), integer(), integer()) -> bitstring(). pbkdf2_hmac_sha1(Password, Salt, Iterations, Dk_len) -> Block_count = (Dk_len + 19) div 20, Raw = pbkdf2_blocks(Password, Salt, Iterations, Block_count, 1, <<>>), gleam@result:unwrap(gleam_stdlib:bit_array_slice(Raw, 0, Dk_len), Raw).