Packages

Cryptographically secure random key generation for Gleam

Current section

Files

Jump to
apiculture src apiculture@key.erl
Raw

src/apiculture@key.erl

-module(apiculture@key).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/apiculture/key.gleam").
-export([new/0, with_random_bytes/2, with_random_chars/2, with_alphabet/2, with_encoding/2, with_prefix/2, with_separator/2, with_checksum/2, with_checksum_bytes/2, without_checksum/1, generate/1, value/1, bytes/1]).
-export_type([key_config/0, 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.
-type key_config() :: {key_config,
gleam@option:option(integer()),
gleam@option:option(integer()),
gleam@option:option(apiculture@alphabet:alphabet()),
gleam@option:option(apiculture@encoding:encoding()),
gleam@option:option(binary()),
gleam@option:option(binary()),
gleam@option:option(apiculture@checksum:checksum()),
gleam@option:option(integer())}.
-type key() :: {key, binary(), bitstring()}.
-file("src/apiculture/key.gleam", 35).
-spec new() -> key_config().
new() ->
{key_config, none, none, none, none, none, none, none, none}.
-file("src/apiculture/key.gleam", 48).
-spec with_random_bytes(key_config(), integer()) -> key_config().
with_random_bytes(Config, Count) ->
{key_config,
{some, Count},
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config)}.
-file("src/apiculture/key.gleam", 52).
-spec with_random_chars(key_config(), integer()) -> key_config().
with_random_chars(Config, Count) ->
{key_config,
erlang:element(2, Config),
{some, Count},
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config)}.
-file("src/apiculture/key.gleam", 56).
-spec with_alphabet(key_config(), apiculture@alphabet:alphabet()) -> key_config().
with_alphabet(Config, Alphabet) ->
{key_config,
erlang:element(2, Config),
erlang:element(3, Config),
{some, Alphabet},
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config)}.
-file("src/apiculture/key.gleam", 60).
-spec with_encoding(key_config(), apiculture@encoding:encoding()) -> key_config().
with_encoding(Config, Encoding) ->
{key_config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
{some, Encoding},
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config)}.
-file("src/apiculture/key.gleam", 64).
-spec with_prefix(key_config(), binary()) -> key_config().
with_prefix(Config, Prefix) ->
{key_config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
{some, Prefix},
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config)}.
-file("src/apiculture/key.gleam", 68).
-spec with_separator(key_config(), binary()) -> key_config().
with_separator(Config, Separator) ->
{key_config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
{some, Separator},
erlang:element(8, Config),
erlang:element(9, Config)}.
-file("src/apiculture/key.gleam", 72).
-spec with_checksum(key_config(), apiculture@checksum:checksum()) -> key_config().
with_checksum(Config, Checksum) ->
{key_config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
{some, Checksum},
erlang:element(9, Config)}.
-file("src/apiculture/key.gleam", 76).
-spec with_checksum_bytes(key_config(), integer()) -> key_config().
with_checksum_bytes(Config, Count) ->
{key_config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
{some, Count}}.
-file("src/apiculture/key.gleam", 80).
-spec without_checksum(key_config()) -> key_config().
without_checksum(Config) ->
{key_config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
none,
none}.
-file("src/apiculture/key.gleam", 239).
-spec hex_digit(integer()) -> binary().
hex_digit(Nibble) ->
case Nibble of
0 ->
<<"0"/utf8>>;
1 ->
<<"1"/utf8>>;
2 ->
<<"2"/utf8>>;
3 ->
<<"3"/utf8>>;
4 ->
<<"4"/utf8>>;
5 ->
<<"5"/utf8>>;
6 ->
<<"6"/utf8>>;
7 ->
<<"7"/utf8>>;
8 ->
<<"8"/utf8>>;
9 ->
<<"9"/utf8>>;
10 ->
<<"a"/utf8>>;
11 ->
<<"b"/utf8>>;
12 ->
<<"c"/utf8>>;
13 ->
<<"d"/utf8>>;
14 ->
<<"e"/utf8>>;
15 ->
<<"f"/utf8>>;
_ ->
<<""/utf8>>
end.
-file("src/apiculture/key.gleam", 233).
-spec int_to_hex(integer()) -> binary().
int_to_hex(Byte) ->
Nibble_high = Byte div 16,
Nibble_low = Byte rem 16,
<<(hex_digit(Nibble_high))/binary, (hex_digit(Nibble_low))/binary>>.
-file("src/apiculture/key.gleam", 222).
-spec do_bytes_to_hex(bitstring(), list(binary())) -> list(binary()).
do_bytes_to_hex(Bytes, Acc) ->
case Bytes of
<<>> ->
Acc;
<<Byte, Rest/bitstring>> ->
Hex = int_to_hex(Byte),
do_bytes_to_hex(Rest, [Hex | Acc]);
_ ->
Acc
end.
-file("src/apiculture/key.gleam", 215).
-spec bytes_to_hex(bitstring()) -> binary().
bytes_to_hex(Bytes) ->
_pipe = Bytes,
_pipe@1 = do_bytes_to_hex(_pipe, []),
_pipe@2 = lists:reverse(_pipe@1),
erlang:list_to_binary(_pipe@2).
-file("src/apiculture/key.gleam", 141).
-spec encode_bytes_with_config(bitstring(), key_config()) -> binary().
encode_bytes_with_config(Bytes, Config) ->
case erlang:element(5, Config) of
{some, Enc} ->
apiculture@encoding:encode(Enc, Bytes);
none ->
bytes_to_hex(Bytes)
end.
-file("src/apiculture/key.gleam", 93).
-spec generate_from_bytes(key_config()) -> {ok, key()} |
{error, apiculture@error:error()}.
generate_from_bytes(Config) ->
case erlang:element(2, Config) of
{some, Byte_count} ->
case apiculture@random:random_bytes(Byte_count) of
{ok, Bytes} ->
Encoded = encode_bytes_with_config(Bytes, Config),
{ok, {key, Encoded, Bytes}};
{error, E} ->
{error, E}
end;
none ->
{error, invalid_byte_count}
end.
-file("src/apiculture/key.gleam", 188).
-spec encode_checksum(bitstring(), key_config()) -> binary().
encode_checksum(Crc_bytes, Config) ->
case erlang:element(5, Config) of
{some, Enc} ->
apiculture@encoding:encode(Enc, Crc_bytes);
none ->
bytes_to_hex(Crc_bytes)
end.
-file("src/apiculture/key.gleam", 176).
-spec drop_first_bytes(bitstring(), integer()) -> bitstring().
drop_first_bytes(Bytes, N) ->
case N of
0 ->
Bytes;
_ ->
case Bytes of
<<_, Rest/binary>> ->
drop_first_bytes(Rest, N - 1);
_ ->
<<>>
end
end.
-file("src/apiculture/key.gleam", 169).
-spec truncate_checksum(bitstring(), gleam@option:option(integer())) -> bitstring().
truncate_checksum(Bytes, Byte_count) ->
case Byte_count of
{some, Count} ->
drop_first_bytes(Bytes, erlang:byte_size(Bytes) - Count);
none ->
Bytes
end.
-file("src/apiculture/key.gleam", 148).
-spec format_key(binary(), bitstring(), key_config()) -> binary().
format_key(Content, Bytes, Config) ->
Prefixed = case erlang:element(6, Config) of
{some, Prefix} ->
Sep = begin
_pipe = erlang:element(7, Config),
gleam@option:unwrap(_pipe, <<""/utf8>>)
end,
<<<<Prefix/binary, Sep/binary>>/binary, Content/binary>>;
none ->
Content
end,
case erlang:element(8, Config) of
{some, Chk} ->
Checksum = (erlang:element(2, Chk))(Bytes),
Checksum_truncated = truncate_checksum(
Checksum,
erlang:element(9, Config)
),
Checksum_encoded = encode_checksum(Checksum_truncated, Config),
<<Prefixed/binary, Checksum_encoded/binary>>;
none ->
Prefixed
end.
-file("src/apiculture/key.gleam", 125).
-spec generate_from_encoding(key_config()) -> {ok, key()} |
{error, apiculture@error:error()}.
generate_from_encoding(Config) ->
case {erlang:element(2, Config), erlang:element(5, Config)} of
{{some, Byte_count}, {some, Encoding}} ->
case apiculture@random:random_bytes(Byte_count) of
{ok, Bytes} ->
Encoded = apiculture@encoding:encode(Encoding, Bytes),
Formatted = format_key(Encoded, Bytes, Config),
{ok, {key, Formatted, Bytes}};
{error, E} ->
{error, E}
end;
{_, _} ->
{error, invalid_byte_count}
end.
-file("src/apiculture/key.gleam", 207).
-spec get_nth(integer(), list(binary())) -> binary().
get_nth(N, Items) ->
case {N, Items} of
{0, [First | _]} ->
First;
{_, [_ | Rest]} ->
get_nth(N - 1, Rest);
{_, []} ->
<<""/utf8>>
end.
-file("src/apiculture/key.gleam", 195).
-spec chars_from_indices(list(integer()), apiculture@alphabet:alphabet()) -> binary().
chars_from_indices(Indices, Alphabet) ->
Char_list = apiculture@alphabet:characters(Alphabet),
_pipe = Indices,
_pipe@1 = gleam@list:map(
_pipe,
fun(Index) ->
case (Index >= 0) andalso (Index < erlang:length(Char_list)) of
true ->
get_nth(Index, Char_list);
false ->
<<""/utf8>>
end
end
),
erlang:list_to_binary(_pipe@1).
-file("src/apiculture/key.gleam", 108).
-spec generate_from_alphabet(key_config()) -> {ok, key()} |
{error, apiculture@error:error()}.
generate_from_alphabet(Config) ->
case {erlang:element(3, Config), erlang:element(4, Config)} of
{{some, Char_count}, {some, Alphabet}} ->
case apiculture@random:random_chars(Alphabet, Char_count) of
{ok, Indices} ->
Chars = chars_from_indices(Indices, Alphabet),
Bytes = gleam_stdlib:identity(Chars),
Formatted = format_key(Chars, Bytes, Config),
{ok, {key, Formatted, Bytes}};
{error, E} ->
{error, E}
end;
{_, _} ->
{error, invalid_byte_count}
end.
-file("src/apiculture/key.gleam", 84).
-spec generate(key_config()) -> {ok, key()} | {error, apiculture@error:error()}.
generate(Config) ->
case {erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config)} of
{none, {some, _}, {some, _}, none} ->
generate_from_alphabet(Config);
{{some, _}, none, none, {some, _}} ->
generate_from_encoding(Config);
{{some, _}, none, none, none} ->
generate_from_bytes(Config);
{_, _, _, _} ->
{error, invalid_byte_count}
end.
-file("src/apiculture/key.gleam", 262).
?DOC(" Returns the string value of the key.\n").
-spec value(key()) -> binary().
value(Key) ->
erlang:element(2, Key).
-file("src/apiculture/key.gleam", 267).
?DOC(" Returns the raw bytes that were used to generate the key.\n").
-spec bytes(key()) -> bitstring().
bytes(Key) ->
erlang:element(3, Key).