Skip to main content

src/packkit@internal@aes.erl

-module(packkit@internal@aes).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/packkit/internal/aes.gleam").
-export([encrypt_block/2, decrypt_block/2, expand_key/1]).
-export_type([expanded_key/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(false).

-opaque expanded_key() :: {expanded_key, list(integer()), integer()}.

-file("src/packkit/internal/aes.gleam", 113).
?DOC(false).
-spec rcon_byte(integer()) -> integer().
rcon_byte(Round) ->
    case Round of
        1 ->
            16#01;

        2 ->
            16#02;

        3 ->
            16#04;

        4 ->
            16#08;

        5 ->
            16#10;

        6 ->
            16#20;

        7 ->
            16#40;

        8 ->
            16#80;

        9 ->
            16#1B;

        10 ->
            16#36;

        _ ->
            16#00
    end.

-file("src/packkit/internal/aes.gleam", 108).
?DOC(false).
-spec rcon_value(integer()) -> integer().
rcon_value(Round) ->
    Rc = rcon_byte(Round),
    erlang:'bsl'(Rc, 24).

-file("src/packkit/internal/aes.gleam", 178).
?DOC(false).
-spec xor_word_lists(list(integer()), list(integer()), list(integer())) -> list(integer()).
xor_word_lists(A, B, Acc) ->
    case {A, B} of
        {[], _} ->
            lists:reverse(Acc);

        {_, []} ->
            lists:reverse(Acc);

        {[X | Rest_a], [Y | Rest_b]} ->
            xor_word_lists(Rest_a, Rest_b, [erlang:'bxor'(X, Y) | Acc])
    end.

-file("src/packkit/internal/aes.gleam", 169).
?DOC(false).
-spec add_round_key(list(integer()), list(integer()), integer()) -> list(integer()).
add_round_key(State, Round_keys, Round) ->
    Key_slice = gleam@list:take(gleam@list:drop(Round_keys, Round * 4), 4),
    xor_word_lists(State, Key_slice, []).

-file("src/packkit/internal/aes.gleam", 236).
?DOC(false).
-spec mix_xor4(integer(), integer(), integer(), integer()) -> integer().
mix_xor4(A, B, C, D) ->
    erlang:'bxor'(erlang:'bxor'(A, B), erlang:'bxor'(C, D)).

-file("src/packkit/internal/aes.gleam", 245).
?DOC(false).
-spec gmul2(integer()) -> integer().
gmul2(Value) ->
    Shifted = erlang:'band'(erlang:'bsl'(Value, 1), 16#FF),
    case erlang:'band'(Value, 16#80) of
        0 ->
            Shifted;

        _ ->
            erlang:'bxor'(Shifted, 16#1B)
    end.

-file("src/packkit/internal/aes.gleam", 253).
?DOC(false).
-spec gmul3(integer()) -> integer().
gmul3(Value) ->
    erlang:'bxor'(gmul2(Value), Value).

-file("src/packkit/internal/aes.gleam", 215).
?DOC(false).
-spec mix_one_column(integer()) -> integer().
mix_one_column(Word) ->
    S0 = erlang:'band'(erlang:'bsr'(Word, 24), 16#FF),
    S1 = erlang:'band'(erlang:'bsr'(Word, 16), 16#FF),
    S2 = erlang:'band'(erlang:'bsr'(Word, 8), 16#FF),
    S3 = erlang:'band'(Word, 16#FF),
    R0 = mix_xor4(gmul2(S0), gmul3(S1), S2, S3),
    R1 = mix_xor4(S0, gmul2(S1), gmul3(S2), S3),
    R2 = mix_xor4(S0, S1, gmul2(S2), gmul3(S3)),
    R3 = mix_xor4(gmul3(S0), S1, S2, gmul2(S3)),
    erlang:'bor'(
        erlang:'bor'(
            erlang:'bor'(erlang:'bsl'(R0, 24), erlang:'bsl'(R1, 16)),
            erlang:'bsl'(R2, 8)
        ),
        R3
    ).

-file("src/packkit/internal/aes.gleam", 211).
?DOC(false).
-spec mix_columns(list(integer())) -> list(integer()).
mix_columns(State) ->
    gleam@list:map(State, fun mix_one_column/1).

-file("src/packkit/internal/aes.gleam", 361).
?DOC(false).
-spec gmul4(integer()) -> integer().
gmul4(Value) ->
    gmul2(gmul2(Value)).

-file("src/packkit/internal/aes.gleam", 365).
?DOC(false).
-spec gmul8(integer()) -> integer().
gmul8(Value) ->
    gmul2(gmul4(Value)).

-file("src/packkit/internal/aes.gleam", 369).
?DOC(false).
-spec gmul9(integer()) -> integer().
gmul9(Value) ->
    erlang:'bxor'(gmul8(Value), Value).

-file("src/packkit/internal/aes.gleam", 373).
?DOC(false).
-spec gmul11(integer()) -> integer().
gmul11(Value) ->
    erlang:'bxor'(erlang:'bxor'(gmul8(Value), gmul2(Value)), Value).

-file("src/packkit/internal/aes.gleam", 380).
?DOC(false).
-spec gmul13(integer()) -> integer().
gmul13(Value) ->
    erlang:'bxor'(erlang:'bxor'(gmul8(Value), gmul4(Value)), Value).

-file("src/packkit/internal/aes.gleam", 387).
?DOC(false).
-spec gmul14(integer()) -> integer().
gmul14(Value) ->
    erlang:'bxor'(erlang:'bxor'(gmul8(Value), gmul4(Value)), gmul2(Value)).

-file("src/packkit/internal/aes.gleam", 340).
?DOC(false).
-spec inv_mix_one_column(integer()) -> integer().
inv_mix_one_column(Word) ->
    S0 = erlang:'band'(erlang:'bsr'(Word, 24), 16#FF),
    S1 = erlang:'band'(erlang:'bsr'(Word, 16), 16#FF),
    S2 = erlang:'band'(erlang:'bsr'(Word, 8), 16#FF),
    S3 = erlang:'band'(Word, 16#FF),
    R0 = mix_xor4(gmul14(S0), gmul11(S1), gmul13(S2), gmul9(S3)),
    R1 = mix_xor4(gmul9(S0), gmul14(S1), gmul11(S2), gmul13(S3)),
    R2 = mix_xor4(gmul13(S0), gmul9(S1), gmul14(S2), gmul11(S3)),
    R3 = mix_xor4(gmul11(S0), gmul13(S1), gmul9(S2), gmul14(S3)),
    erlang:'bor'(
        erlang:'bor'(
            erlang:'bor'(erlang:'bsl'(R0, 24), erlang:'bsl'(R1, 16)),
            erlang:'bsl'(R2, 8)
        ),
        R3
    ).

-file("src/packkit/internal/aes.gleam", 336).
?DOC(false).
-spec inv_mix_columns(list(integer())) -> list(integer()).
inv_mix_columns(State) ->
    gleam@list:map(State, fun inv_mix_one_column/1).

-file("src/packkit/internal/aes.gleam", 398).
?DOC(false).
-spec bit_array_to_u32_words(bitstring(), list(integer())) -> list(integer()).
bit_array_to_u32_words(Bytes, Acc) ->
    case Bytes of
        <<Word:32/big, Rest/binary>> ->
            bit_array_to_u32_words(Rest, [Word | Acc]);

        _ ->
            lists:reverse(Acc)
    end.

-file("src/packkit/internal/aes.gleam", 406).
?DOC(false).
-spec u32_words_to_bit_array(list(integer()), bitstring()) -> bitstring().
u32_words_to_bit_array(Words, Acc) ->
    case Words of
        [] ->
            Acc;

        [W | Rest] ->
            u32_words_to_bit_array(
                Rest,
                gleam_stdlib:bit_array_concat([Acc, <<W:32/big>>])
            )
    end.

-file("src/packkit/internal/aes.gleam", 418).
?DOC(false).
-spec words_to_bytes_loop(list(integer()), list(integer())) -> list(integer()).
words_to_bytes_loop(Words, Acc) ->
    case Words of
        [] ->
            lists:reverse(Acc);

        [W | Rest] ->
            B0 = erlang:'band'(erlang:'bsr'(W, 24), 16#FF),
            B1 = erlang:'band'(erlang:'bsr'(W, 16), 16#FF),
            B2 = erlang:'band'(erlang:'bsr'(W, 8), 16#FF),
            B3 = erlang:'band'(W, 16#FF),
            words_to_bytes_loop(Rest, [B3, B2, B1, B0 | Acc])
    end.

-file("src/packkit/internal/aes.gleam", 414).
?DOC(false).
-spec words_to_bytes(list(integer())) -> list(integer()).
words_to_bytes(Words) ->
    words_to_bytes_loop(Words, []).

-file("src/packkit/internal/aes.gleam", 435).
?DOC(false).
-spec bytes_to_words_loop(list(integer()), list(integer())) -> list(integer()).
bytes_to_words_loop(Bytes, Acc) ->
    case Bytes of
        [B0, B1, B2, B3 | Rest] ->
            Word = erlang:'bor'(
                erlang:'bor'(
                    erlang:'bor'(erlang:'bsl'(B0, 24), erlang:'bsl'(B1, 16)),
                    erlang:'bsl'(B2, 8)
                ),
                B3
            ),
            bytes_to_words_loop(Rest, [Word | Acc]);

        _ ->
            lists:reverse(Acc)
    end.

-file("src/packkit/internal/aes.gleam", 431).
?DOC(false).
-spec bytes_to_words(list(integer())) -> list(integer()).
bytes_to_words(Bytes) ->
    bytes_to_words_loop(Bytes, []).

-file("src/packkit/internal/aes.gleam", 190).
?DOC(false).
-spec shift_rows(list(integer())) -> list(integer()).
shift_rows(State) ->
    case words_to_bytes(State) of
        [B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15] ->
            bytes_to_words(
                [B0,
                    B5,
                    B10,
                    B15,
                    B4,
                    B9,
                    B14,
                    B3,
                    B8,
                    B13,
                    B2,
                    B7,
                    B12,
                    B1,
                    B6,
                    B11]
            );

        _ ->
            State
    end.

-file("src/packkit/internal/aes.gleam", 320).
?DOC(false).
-spec inv_shift_rows(list(integer())) -> list(integer()).
inv_shift_rows(State) ->
    case words_to_bytes(State) of
        [B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15] ->
            bytes_to_words(
                [B0,
                    B13,
                    B10,
                    B7,
                    B4,
                    B1,
                    B14,
                    B11,
                    B8,
                    B5,
                    B2,
                    B15,
                    B12,
                    B9,
                    B6,
                    B3]
            );

        _ ->
            State
    end.

-file("src/packkit/internal/aes.gleam", 457).
?DOC(false).
-spec sbox(integer()) -> integer().
sbox(Byte) ->
    case Byte of
        16#00 ->
            16#63;

        16#01 ->
            16#7C;

        16#02 ->
            16#77;

        16#03 ->
            16#7B;

        16#04 ->
            16#F2;

        16#05 ->
            16#6B;

        16#06 ->
            16#6F;

        16#07 ->
            16#C5;

        16#08 ->
            16#30;

        16#09 ->
            16#01;

        16#0A ->
            16#67;

        16#0B ->
            16#2B;

        16#0C ->
            16#FE;

        16#0D ->
            16#D7;

        16#0E ->
            16#AB;

        16#0F ->
            16#76;

        16#10 ->
            16#CA;

        16#11 ->
            16#82;

        16#12 ->
            16#C9;

        16#13 ->
            16#7D;

        16#14 ->
            16#FA;

        16#15 ->
            16#59;

        16#16 ->
            16#47;

        16#17 ->
            16#F0;

        16#18 ->
            16#AD;

        16#19 ->
            16#D4;

        16#1A ->
            16#A2;

        16#1B ->
            16#AF;

        16#1C ->
            16#9C;

        16#1D ->
            16#A4;

        16#1E ->
            16#72;

        16#1F ->
            16#C0;

        16#20 ->
            16#B7;

        16#21 ->
            16#FD;

        16#22 ->
            16#93;

        16#23 ->
            16#26;

        16#24 ->
            16#36;

        16#25 ->
            16#3F;

        16#26 ->
            16#F7;

        16#27 ->
            16#CC;

        16#28 ->
            16#34;

        16#29 ->
            16#A5;

        16#2A ->
            16#E5;

        16#2B ->
            16#F1;

        16#2C ->
            16#71;

        16#2D ->
            16#D8;

        16#2E ->
            16#31;

        16#2F ->
            16#15;

        16#30 ->
            16#04;

        16#31 ->
            16#C7;

        16#32 ->
            16#23;

        16#33 ->
            16#C3;

        16#34 ->
            16#18;

        16#35 ->
            16#96;

        16#36 ->
            16#05;

        16#37 ->
            16#9A;

        16#38 ->
            16#07;

        16#39 ->
            16#12;

        16#3A ->
            16#80;

        16#3B ->
            16#E2;

        16#3C ->
            16#EB;

        16#3D ->
            16#27;

        16#3E ->
            16#B2;

        16#3F ->
            16#75;

        16#40 ->
            16#09;

        16#41 ->
            16#83;

        16#42 ->
            16#2C;

        16#43 ->
            16#1A;

        16#44 ->
            16#1B;

        16#45 ->
            16#6E;

        16#46 ->
            16#5A;

        16#47 ->
            16#A0;

        16#48 ->
            16#52;

        16#49 ->
            16#3B;

        16#4A ->
            16#D6;

        16#4B ->
            16#B3;

        16#4C ->
            16#29;

        16#4D ->
            16#E3;

        16#4E ->
            16#2F;

        16#4F ->
            16#84;

        16#50 ->
            16#53;

        16#51 ->
            16#D1;

        16#52 ->
            16#00;

        16#53 ->
            16#ED;

        16#54 ->
            16#20;

        16#55 ->
            16#FC;

        16#56 ->
            16#B1;

        16#57 ->
            16#5B;

        16#58 ->
            16#6A;

        16#59 ->
            16#CB;

        16#5A ->
            16#BE;

        16#5B ->
            16#39;

        16#5C ->
            16#4A;

        16#5D ->
            16#4C;

        16#5E ->
            16#58;

        16#5F ->
            16#CF;

        16#60 ->
            16#D0;

        16#61 ->
            16#EF;

        16#62 ->
            16#AA;

        16#63 ->
            16#FB;

        16#64 ->
            16#43;

        16#65 ->
            16#4D;

        16#66 ->
            16#33;

        16#67 ->
            16#85;

        16#68 ->
            16#45;

        16#69 ->
            16#F9;

        16#6A ->
            16#02;

        16#6B ->
            16#7F;

        16#6C ->
            16#50;

        16#6D ->
            16#3C;

        16#6E ->
            16#9F;

        16#6F ->
            16#A8;

        16#70 ->
            16#51;

        16#71 ->
            16#A3;

        16#72 ->
            16#40;

        16#73 ->
            16#8F;

        16#74 ->
            16#92;

        16#75 ->
            16#9D;

        16#76 ->
            16#38;

        16#77 ->
            16#F5;

        16#78 ->
            16#BC;

        16#79 ->
            16#B6;

        16#7A ->
            16#DA;

        16#7B ->
            16#21;

        16#7C ->
            16#10;

        16#7D ->
            16#FF;

        16#7E ->
            16#F3;

        16#7F ->
            16#D2;

        16#80 ->
            16#CD;

        16#81 ->
            16#0C;

        16#82 ->
            16#13;

        16#83 ->
            16#EC;

        16#84 ->
            16#5F;

        16#85 ->
            16#97;

        16#86 ->
            16#44;

        16#87 ->
            16#17;

        16#88 ->
            16#C4;

        16#89 ->
            16#A7;

        16#8A ->
            16#7E;

        16#8B ->
            16#3D;

        16#8C ->
            16#64;

        16#8D ->
            16#5D;

        16#8E ->
            16#19;

        16#8F ->
            16#73;

        16#90 ->
            16#60;

        16#91 ->
            16#81;

        16#92 ->
            16#4F;

        16#93 ->
            16#DC;

        16#94 ->
            16#22;

        16#95 ->
            16#2A;

        16#96 ->
            16#90;

        16#97 ->
            16#88;

        16#98 ->
            16#46;

        16#99 ->
            16#EE;

        16#9A ->
            16#B8;

        16#9B ->
            16#14;

        16#9C ->
            16#DE;

        16#9D ->
            16#5E;

        16#9E ->
            16#0B;

        16#9F ->
            16#DB;

        16#A0 ->
            16#E0;

        16#A1 ->
            16#32;

        16#A2 ->
            16#3A;

        16#A3 ->
            16#0A;

        16#A4 ->
            16#49;

        16#A5 ->
            16#06;

        16#A6 ->
            16#24;

        16#A7 ->
            16#5C;

        16#A8 ->
            16#C2;

        16#A9 ->
            16#D3;

        16#AA ->
            16#AC;

        16#AB ->
            16#62;

        16#AC ->
            16#91;

        16#AD ->
            16#95;

        16#AE ->
            16#E4;

        16#AF ->
            16#79;

        16#B0 ->
            16#E7;

        16#B1 ->
            16#C8;

        16#B2 ->
            16#37;

        16#B3 ->
            16#6D;

        16#B4 ->
            16#8D;

        16#B5 ->
            16#D5;

        16#B6 ->
            16#4E;

        16#B7 ->
            16#A9;

        16#B8 ->
            16#6C;

        16#B9 ->
            16#56;

        16#BA ->
            16#F4;

        16#BB ->
            16#EA;

        16#BC ->
            16#65;

        16#BD ->
            16#7A;

        16#BE ->
            16#AE;

        16#BF ->
            16#08;

        16#C0 ->
            16#BA;

        16#C1 ->
            16#78;

        16#C2 ->
            16#25;

        16#C3 ->
            16#2E;

        16#C4 ->
            16#1C;

        16#C5 ->
            16#A6;

        16#C6 ->
            16#B4;

        16#C7 ->
            16#C6;

        16#C8 ->
            16#E8;

        16#C9 ->
            16#DD;

        16#CA ->
            16#74;

        16#CB ->
            16#1F;

        16#CC ->
            16#4B;

        16#CD ->
            16#BD;

        16#CE ->
            16#8B;

        16#CF ->
            16#8A;

        16#D0 ->
            16#70;

        16#D1 ->
            16#3E;

        16#D2 ->
            16#B5;

        16#D3 ->
            16#66;

        16#D4 ->
            16#48;

        16#D5 ->
            16#03;

        16#D6 ->
            16#F6;

        16#D7 ->
            16#0E;

        16#D8 ->
            16#61;

        16#D9 ->
            16#35;

        16#DA ->
            16#57;

        16#DB ->
            16#B9;

        16#DC ->
            16#86;

        16#DD ->
            16#C1;

        16#DE ->
            16#1D;

        16#DF ->
            16#9E;

        16#E0 ->
            16#E1;

        16#E1 ->
            16#F8;

        16#E2 ->
            16#98;

        16#E3 ->
            16#11;

        16#E4 ->
            16#69;

        16#E5 ->
            16#D9;

        16#E6 ->
            16#8E;

        16#E7 ->
            16#94;

        16#E8 ->
            16#9B;

        16#E9 ->
            16#1E;

        16#EA ->
            16#87;

        16#EB ->
            16#E9;

        16#EC ->
            16#CE;

        16#ED ->
            16#55;

        16#EE ->
            16#28;

        16#EF ->
            16#DF;

        16#F0 ->
            16#8C;

        16#F1 ->
            16#A1;

        16#F2 ->
            16#89;

        16#F3 ->
            16#0D;

        16#F4 ->
            16#BF;

        16#F5 ->
            16#E6;

        16#F6 ->
            16#42;

        16#F7 ->
            16#68;

        16#F8 ->
            16#41;

        16#F9 ->
            16#99;

        16#FA ->
            16#2D;

        16#FB ->
            16#0F;

        16#FC ->
            16#B0;

        16#FD ->
            16#54;

        16#FE ->
            16#BB;

        _ ->
            16#16
    end.

-file("src/packkit/internal/aes.gleam", 91).
?DOC(false).
-spec sub_word(integer()) -> integer().
sub_word(Word) ->
    B0 = sbox(erlang:'band'(erlang:'bsr'(Word, 24), 16#FF)),
    B1 = sbox(erlang:'band'(erlang:'bsr'(Word, 16), 16#FF)),
    B2 = sbox(erlang:'band'(erlang:'bsr'(Word, 8), 16#FF)),
    B3 = sbox(erlang:'band'(Word, 16#FF)),
    erlang:'bor'(
        erlang:'bor'(
            erlang:'bor'(erlang:'bsl'(B0, 24), erlang:'bsl'(B1, 16)),
            erlang:'bsl'(B2, 8)
        ),
        B3
    ).

-file("src/packkit/internal/aes.gleam", 186).
?DOC(false).
-spec sub_bytes(list(integer())) -> list(integer()).
sub_bytes(State) ->
    gleam@list:map(State, fun sub_word/1).

-file("src/packkit/internal/aes.gleam", 146).
?DOC(false).
-spec encrypt_rounds(list(integer()), list(integer()), integer(), integer()) -> list(integer()).
encrypt_rounds(State, Round_keys, Round, Total) ->
    case Round of
        N when N =:= Total ->
            After_sub = sub_bytes(State),
            After_shift = shift_rows(After_sub),
            add_round_key(After_shift, Round_keys, Total);

        _ ->
            After_sub@1 = sub_bytes(State),
            After_shift@1 = shift_rows(After_sub@1),
            After_mix = mix_columns(After_shift@1),
            After_key = add_round_key(After_mix, Round_keys, Round),
            encrypt_rounds(After_key, Round_keys, Round + 1, Total)
    end.

-file("src/packkit/internal/aes.gleam", 133).
?DOC(false).
-spec encrypt_block(expanded_key(), bitstring()) -> {ok, bitstring()} |
    {error, nil}.
encrypt_block(Key, Block) ->
    case erlang:byte_size(Block) of
        16 ->
            State = bit_array_to_u32_words(Block, []),
            State_xored = add_round_key(State, erlang:element(2, Key), 0),
            Final_state = encrypt_rounds(
                State_xored,
                erlang:element(2, Key),
                1,
                erlang:element(3, Key)
            ),
            {ok, u32_words_to_bit_array(Final_state, <<>>)};

        _ ->
            {error, nil}
    end.

-file("src/packkit/internal/aes.gleam", 720).
?DOC(false).
-spec inv_sbox(integer()) -> integer().
inv_sbox(Byte) ->
    case Byte of
        16#00 ->
            16#52;

        16#01 ->
            16#09;

        16#02 ->
            16#6A;

        16#03 ->
            16#D5;

        16#04 ->
            16#30;

        16#05 ->
            16#36;

        16#06 ->
            16#A5;

        16#07 ->
            16#38;

        16#08 ->
            16#BF;

        16#09 ->
            16#40;

        16#0A ->
            16#A3;

        16#0B ->
            16#9E;

        16#0C ->
            16#81;

        16#0D ->
            16#F3;

        16#0E ->
            16#D7;

        16#0F ->
            16#FB;

        16#10 ->
            16#7C;

        16#11 ->
            16#E3;

        16#12 ->
            16#39;

        16#13 ->
            16#82;

        16#14 ->
            16#9B;

        16#15 ->
            16#2F;

        16#16 ->
            16#FF;

        16#17 ->
            16#87;

        16#18 ->
            16#34;

        16#19 ->
            16#8E;

        16#1A ->
            16#43;

        16#1B ->
            16#44;

        16#1C ->
            16#C4;

        16#1D ->
            16#DE;

        16#1E ->
            16#E9;

        16#1F ->
            16#CB;

        16#20 ->
            16#54;

        16#21 ->
            16#7B;

        16#22 ->
            16#94;

        16#23 ->
            16#32;

        16#24 ->
            16#A6;

        16#25 ->
            16#C2;

        16#26 ->
            16#23;

        16#27 ->
            16#3D;

        16#28 ->
            16#EE;

        16#29 ->
            16#4C;

        16#2A ->
            16#95;

        16#2B ->
            16#0B;

        16#2C ->
            16#42;

        16#2D ->
            16#FA;

        16#2E ->
            16#C3;

        16#2F ->
            16#4E;

        16#30 ->
            16#08;

        16#31 ->
            16#2E;

        16#32 ->
            16#A1;

        16#33 ->
            16#66;

        16#34 ->
            16#28;

        16#35 ->
            16#D9;

        16#36 ->
            16#24;

        16#37 ->
            16#B2;

        16#38 ->
            16#76;

        16#39 ->
            16#5B;

        16#3A ->
            16#A2;

        16#3B ->
            16#49;

        16#3C ->
            16#6D;

        16#3D ->
            16#8B;

        16#3E ->
            16#D1;

        16#3F ->
            16#25;

        16#40 ->
            16#72;

        16#41 ->
            16#F8;

        16#42 ->
            16#F6;

        16#43 ->
            16#64;

        16#44 ->
            16#86;

        16#45 ->
            16#68;

        16#46 ->
            16#98;

        16#47 ->
            16#16;

        16#48 ->
            16#D4;

        16#49 ->
            16#A4;

        16#4A ->
            16#5C;

        16#4B ->
            16#CC;

        16#4C ->
            16#5D;

        16#4D ->
            16#65;

        16#4E ->
            16#B6;

        16#4F ->
            16#92;

        16#50 ->
            16#6C;

        16#51 ->
            16#70;

        16#52 ->
            16#48;

        16#53 ->
            16#50;

        16#54 ->
            16#FD;

        16#55 ->
            16#ED;

        16#56 ->
            16#B9;

        16#57 ->
            16#DA;

        16#58 ->
            16#5E;

        16#59 ->
            16#15;

        16#5A ->
            16#46;

        16#5B ->
            16#57;

        16#5C ->
            16#A7;

        16#5D ->
            16#8D;

        16#5E ->
            16#9D;

        16#5F ->
            16#84;

        16#60 ->
            16#90;

        16#61 ->
            16#D8;

        16#62 ->
            16#AB;

        16#63 ->
            16#00;

        16#64 ->
            16#8C;

        16#65 ->
            16#BC;

        16#66 ->
            16#D3;

        16#67 ->
            16#0A;

        16#68 ->
            16#F7;

        16#69 ->
            16#E4;

        16#6A ->
            16#58;

        16#6B ->
            16#05;

        16#6C ->
            16#B8;

        16#6D ->
            16#B3;

        16#6E ->
            16#45;

        16#6F ->
            16#06;

        16#70 ->
            16#D0;

        16#71 ->
            16#2C;

        16#72 ->
            16#1E;

        16#73 ->
            16#8F;

        16#74 ->
            16#CA;

        16#75 ->
            16#3F;

        16#76 ->
            16#0F;

        16#77 ->
            16#02;

        16#78 ->
            16#C1;

        16#79 ->
            16#AF;

        16#7A ->
            16#BD;

        16#7B ->
            16#03;

        16#7C ->
            16#01;

        16#7D ->
            16#13;

        16#7E ->
            16#8A;

        16#7F ->
            16#6B;

        16#80 ->
            16#3A;

        16#81 ->
            16#91;

        16#82 ->
            16#11;

        16#83 ->
            16#41;

        16#84 ->
            16#4F;

        16#85 ->
            16#67;

        16#86 ->
            16#DC;

        16#87 ->
            16#EA;

        16#88 ->
            16#97;

        16#89 ->
            16#F2;

        16#8A ->
            16#CF;

        16#8B ->
            16#CE;

        16#8C ->
            16#F0;

        16#8D ->
            16#B4;

        16#8E ->
            16#E6;

        16#8F ->
            16#73;

        16#90 ->
            16#96;

        16#91 ->
            16#AC;

        16#92 ->
            16#74;

        16#93 ->
            16#22;

        16#94 ->
            16#E7;

        16#95 ->
            16#AD;

        16#96 ->
            16#35;

        16#97 ->
            16#85;

        16#98 ->
            16#E2;

        16#99 ->
            16#F9;

        16#9A ->
            16#37;

        16#9B ->
            16#E8;

        16#9C ->
            16#1C;

        16#9D ->
            16#75;

        16#9E ->
            16#DF;

        16#9F ->
            16#6E;

        16#A0 ->
            16#47;

        16#A1 ->
            16#F1;

        16#A2 ->
            16#1A;

        16#A3 ->
            16#71;

        16#A4 ->
            16#1D;

        16#A5 ->
            16#29;

        16#A6 ->
            16#C5;

        16#A7 ->
            16#89;

        16#A8 ->
            16#6F;

        16#A9 ->
            16#B7;

        16#AA ->
            16#62;

        16#AB ->
            16#0E;

        16#AC ->
            16#AA;

        16#AD ->
            16#18;

        16#AE ->
            16#BE;

        16#AF ->
            16#1B;

        16#B0 ->
            16#FC;

        16#B1 ->
            16#56;

        16#B2 ->
            16#3E;

        16#B3 ->
            16#4B;

        16#B4 ->
            16#C6;

        16#B5 ->
            16#D2;

        16#B6 ->
            16#79;

        16#B7 ->
            16#20;

        16#B8 ->
            16#9A;

        16#B9 ->
            16#DB;

        16#BA ->
            16#C0;

        16#BB ->
            16#FE;

        16#BC ->
            16#78;

        16#BD ->
            16#CD;

        16#BE ->
            16#5A;

        16#BF ->
            16#F4;

        16#C0 ->
            16#1F;

        16#C1 ->
            16#DD;

        16#C2 ->
            16#A8;

        16#C3 ->
            16#33;

        16#C4 ->
            16#88;

        16#C5 ->
            16#07;

        16#C6 ->
            16#C7;

        16#C7 ->
            16#31;

        16#C8 ->
            16#B1;

        16#C9 ->
            16#12;

        16#CA ->
            16#10;

        16#CB ->
            16#59;

        16#CC ->
            16#27;

        16#CD ->
            16#80;

        16#CE ->
            16#EC;

        16#CF ->
            16#5F;

        16#D0 ->
            16#60;

        16#D1 ->
            16#51;

        16#D2 ->
            16#7F;

        16#D3 ->
            16#A9;

        16#D4 ->
            16#19;

        16#D5 ->
            16#B5;

        16#D6 ->
            16#4A;

        16#D7 ->
            16#0D;

        16#D8 ->
            16#2D;

        16#D9 ->
            16#E5;

        16#DA ->
            16#7A;

        16#DB ->
            16#9F;

        16#DC ->
            16#93;

        16#DD ->
            16#C9;

        16#DE ->
            16#9C;

        16#DF ->
            16#EF;

        16#E0 ->
            16#A0;

        16#E1 ->
            16#E0;

        16#E2 ->
            16#3B;

        16#E3 ->
            16#4D;

        16#E4 ->
            16#AE;

        16#E5 ->
            16#2A;

        16#E6 ->
            16#F5;

        16#E7 ->
            16#B0;

        16#E8 ->
            16#C8;

        16#E9 ->
            16#EB;

        16#EA ->
            16#BB;

        16#EB ->
            16#3C;

        16#EC ->
            16#83;

        16#ED ->
            16#53;

        16#EE ->
            16#99;

        16#EF ->
            16#61;

        16#F0 ->
            16#17;

        16#F1 ->
            16#2B;

        16#F2 ->
            16#04;

        16#F3 ->
            16#7E;

        16#F4 ->
            16#BA;

        16#F5 ->
            16#77;

        16#F6 ->
            16#D6;

        16#F7 ->
            16#26;

        16#F8 ->
            16#E1;

        16#F9 ->
            16#69;

        16#FA ->
            16#14;

        16#FB ->
            16#63;

        16#FC ->
            16#55;

        16#FD ->
            16#21;

        16#FE ->
            16#0C;

        _ ->
            16#7D
    end.

-file("src/packkit/internal/aes.gleam", 303).
?DOC(false).
-spec inv_sub_word(integer()) -> integer().
inv_sub_word(Word) ->
    B0 = inv_sbox(erlang:'band'(erlang:'bsr'(Word, 24), 16#FF)),
    B1 = inv_sbox(erlang:'band'(erlang:'bsr'(Word, 16), 16#FF)),
    B2 = inv_sbox(erlang:'band'(erlang:'bsr'(Word, 8), 16#FF)),
    B3 = inv_sbox(erlang:'band'(Word, 16#FF)),
    erlang:'bor'(
        erlang:'bor'(
            erlang:'bor'(erlang:'bsl'(B0, 24), erlang:'bsl'(B1, 16)),
            erlang:'bsl'(B2, 8)
        ),
        B3
    ).

-file("src/packkit/internal/aes.gleam", 299).
?DOC(false).
-spec inv_sub_bytes(list(integer())) -> list(integer()).
inv_sub_bytes(State) ->
    gleam@list:map(State, fun inv_sub_word/1).

-file("src/packkit/internal/aes.gleam", 276).
?DOC(false).
-spec decrypt_rounds(list(integer()), list(integer()), integer()) -> list(integer()).
decrypt_rounds(State, Round_keys, Round) ->
    case Round of
        0 ->
            After_shift = inv_shift_rows(State),
            After_sub = inv_sub_bytes(After_shift),
            add_round_key(After_sub, Round_keys, 0);

        _ ->
            After_shift@1 = inv_shift_rows(State),
            After_sub@1 = inv_sub_bytes(After_shift@1),
            After_key = add_round_key(After_sub@1, Round_keys, Round),
            After_mix = inv_mix_columns(After_key),
            decrypt_rounds(After_mix, Round_keys, Round - 1)
    end.

-file("src/packkit/internal/aes.gleam", 263).
?DOC(false).
-spec decrypt_block(expanded_key(), bitstring()) -> {ok, bitstring()} |
    {error, nil}.
decrypt_block(Key, Block) ->
    case erlang:byte_size(Block) of
        16 ->
            State = bit_array_to_u32_words(Block, []),
            State_xored = add_round_key(
                State,
                erlang:element(2, Key),
                erlang:element(3, Key)
            ),
            Final_state = decrypt_rounds(
                State_xored,
                erlang:element(2, Key),
                erlang:element(3, Key) - 1
            ),
            {ok, u32_words_to_bit_array(Final_state, <<>>)};

        _ ->
            {error, nil}
    end.

-file("src/packkit/internal/aes.gleam", 85).
?DOC(false).
-spec rotate_word(integer()) -> integer().
rotate_word(Word) ->
    High = erlang:'band'(erlang:'bsl'(Word, 8), 16#FFFFFFFF),
    Low = erlang:'bsr'(Word, 24),
    erlang:'bor'(High, Low).

-file("src/packkit/internal/aes.gleam", 53).
?DOC(false).
-spec expand_loop(list(integer()), integer(), integer(), integer()) -> list(integer()).
expand_loop(Reversed, Index, Nk, Total) ->
    gleam@bool:guard(
        Index >= Total,
        Reversed,
        fun() ->
            case {Reversed, gleam@list:first(gleam@list:drop(Reversed, Nk - 1))} of
                {[Previous | _], {ok, Word_nk_ago}} ->
                    Transformed = case case Nk of
                        0 -> 0;
                        Gleam@denominator -> Index rem Gleam@denominator
                    end of
                        0 ->
                            Rotated = rotate_word(Previous),
                            Subbed = sub_word(Rotated),
                            Rcon = rcon_value(case Nk of
                                    0 -> 0;
                                    Gleam@denominator@1 -> Index div Gleam@denominator@1
                                end),
                            erlang:'bxor'(Subbed, Rcon);

                        4 when Nk > 6 ->
                            sub_word(Previous);

                        _ ->
                            Previous
                    end,
                    Next = erlang:'bxor'(Word_nk_ago, Transformed),
                    expand_loop([Next | Reversed], Index + 1, Nk, Total);

                {_, _} ->
                    Reversed
            end
        end
    ).

-file("src/packkit/internal/aes.gleam", 45).
?DOC(false).
-spec do_expand(list(integer()), integer(), integer()) -> expanded_key().
do_expand(Key_words, Nk, Rounds) ->
    Total_words = 4 * (Rounds + 1),
    Reversed_initial = lists:reverse(Key_words),
    Reversed_all = expand_loop(Reversed_initial, Nk, Nk, Total_words),
    Round_keys = lists:reverse(Reversed_all),
    {expanded_key, Round_keys, Rounds}.

-file("src/packkit/internal/aes.gleam", 34).
?DOC(false).
-spec expand_key(bitstring()) -> {ok, expanded_key()} | {error, nil}.
expand_key(Key) ->
    Key_words = bit_array_to_u32_words(Key, []),
    Nk = erlang:length(Key_words),
    case Nk of
        4 ->
            {ok, do_expand(Key_words, 4, 10)};

        6 ->
            {ok, do_expand(Key_words, 6, 12)};

        8 ->
            {ok, do_expand(Key_words, 8, 14)};

        _ ->
            {error, nil}
    end.