-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};
{_, <<B, Rest/binary>>} ->
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
<<B, Rest/binary>> ->
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
<<B, Rest/binary>> ->
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, <<Bit_len:64/big>>]
).
-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
<<B, Rest/binary>> ->
Mixed = erlang:'bxor'(B, Mask),
xor_with_byte_loop(
Rest,
Mask,
gleam_stdlib:bit_array_concat([Acc, <<Mixed>>])
);
_ ->
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
{<<L, L_rest/binary>>, <<R, R_rest/binary>>} ->
Mixed = erlang:'bxor'(L, R),
xor_bit_arrays_loop(
L_rest,
R_rest,
gleam_stdlib:bit_array_concat([Acc, <<Mixed>>])
);
{_, _} ->
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
<<B, Rest/binary>> ->
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
<<B, Rest/binary>> ->
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};
<<W0:32/big,
W1:32/big,
W2:32/big,
W3:32/big,
W4:32/big,
W5:32/big,
W6:32/big,
W7:32/big,
W8:32/big,
W9:32/big,
W10:32/big,
W11:32/big,
W12:32/big,
W13:32/big,
W14:32/big,
W15:32/big,
Rest/binary>> ->
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, <<Bit_len:64/big>>]
),
{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)
),
<<H0:32, H1:32, H2:32, H3:32, H4:32, H5:32, H6:32, H7:32>>.
-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
<<Block:64/binary, Rest/binary>> ->
{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
),
<<H0:32, H1:32, H2:32, H3:32, H4:32, H5:32, H6:32, H7:32>>.
-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};
<<W0:32/big,
W1:32/big,
W2:32/big,
W3:32/big,
W4:32/big,
W5:32/big,
W6:32/big,
W7:32/big,
W8:32/big,
W9:32/big,
W10:32/big,
W11:32/big,
W12:32/big,
W13:32/big,
W14:32/big,
W15:32/big,
Rest/binary>> ->
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
),
<<H0:32, H1:32, H2:32, H3:32, H4:32>>.
-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, <<Index:32/big>>])
),
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).