Skip to content

Commit

Permalink
token decryption + tests (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
GwendalLaurent authored Sep 17, 2024
1 parent be82628 commit e8ed0c2
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ jobs:

- name: Dialyzer
run: rebar3 dialyzer

- name: Common test
run: rebar3 ct
19 changes: 14 additions & 5 deletions src/rebar3_grisp_io_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@

%--- Types ---------------------------------------------------------------------

-type config() :: #{username := binary(),
encrypted_token := binary()}.
-type clear_token() :: <<_:_*128>>. % AES => data blocks of 16 bytes (128 bits).

%--- API -----------------------------------------------------------------------

%% @doc Write the new configuration stored
%% Note: The token must be already encrypted in the Config map
-spec write_config(rebar_state:t(), config()) -> ok.
write_config(State, Config) ->
GIoConfigFile = auth_config_file(State),
ok = filelib:ensure_dir(GIoConfigFile),
Expand All @@ -35,7 +39,7 @@ write_config(State, Config) ->

%% @doc Read the stored configuration file
%% Note: The stored token stays encrypted in the Config map
-spec read_config(rebar_state:t()) -> map() | no_return().
-spec read_config(rebar_state:t()) -> config() | no_return().
read_config(State) ->
GIoConfigFile = auth_config_file(State),
case file:consult(GIoConfigFile) of
Expand All @@ -45,13 +49,19 @@ read_config(State) ->
error(Reason)
end.

%% @doc encrypt the token provided in the args
%% Warning: the token must have a bytes size that is a multiple of 16
-spec encrypt_token(binary(), clear_token()) -> binary().
encrypt_token(LocalPassword, Token) ->
PaddedPassword = password_padding(LocalPassword),
crypto:crypto_one_time(?AES, PaddedPassword, Token, true).

%% @todo
decrypt_token(_LocalPassword, _Config) ->
ok.
%% @doc Decrypt the token present in Encrypted token
-spec decrypt_token(binary(), binary()) -> clear_token().
decrypt_token(LocalPassword, EncryptedToken) ->
PaddedPassword = password_padding(LocalPassword),
crypto:crypto_one_time(?AES, PaddedPassword, EncryptedToken, false).

%--- Internals -----------------------------------------------------------------
auth_config_file(State) ->
filename:join(rebar_dir:global_config_dir(State), ?CONFIG_FILE).
Expand All @@ -61,4 +71,3 @@ password_padding(LocalPassword) when bit_size(LocalPassword) < ?AES_KEY_SIZE ->
<<LocalPassword/binary, 0:NbPaddingBits>>;
password_padding(_) ->
error(local_password_too_big).

61 changes: 61 additions & 0 deletions test/rebar3_grisp_io_config_SUITE.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
-module(rebar3_grisp_io_config_SUITE).

% callbacks
-export([all/0]).
-export([init_per_suite/1]).
-export([end_per_suite/1]).
-export([init_per_testcase/2]).
-export([end_per_testcase/2]).

% testcases
-export([read_write_config_test/1]).
-export([encrypt_decrypt_token/1]).

%--- Include -------------------------------------------------------------------

-include_lib("common_test/include/ct.hrl").
-include_lib("stdlib/include/assert.hrl").

%--- Callbacks -----------------------------------------------------------------

all() -> [
read_write_config_test,
encrypt_decrypt_token
].

init_per_suite(Config) ->
DataDir = ?config(data_dir, Config),
os:putenv("REBAR_GLOBAL_CONFIG_DIR", DataDir),
RState = rebar_state:new(),
[{rebar_state, RState} | Config].

end_per_suite(_Config) ->
ok.

init_per_testcase(_, Config) ->
Token = <<"abcdefghijklmnop">>,
Password = <<"s3cur3pa55w0rd">>,
[{token, Token}, {local_password, Password} | Config].

end_per_testcase(_, _Config) ->
ok.

%--- Testcases -----------------------------------------------------------------

read_write_config_test(Config) ->
RState = ?config(rebar_state, Config),
Token = ?config(token, Config),
Password = ?config(local_password, Config),
EncryptedToken = rebar3_grisp_io_config:encrypt_token(Password, Token),
PluginConfig = #{username => <<"Test">>, encrypted_token => EncryptedToken},
rebar3_grisp_io_config:write_config(RState, PluginConfig),
ReadConfig = rebar3_grisp_io_config:read_config(RState),
?assertEqual(PluginConfig, ReadConfig).

encrypt_decrypt_token(Config) ->
Token = ?config(token, Config),
Password = ?config(local_password, Config),
EncryptedToken = rebar3_grisp_io_config:encrypt_token(Password, Token),
?assertNotEqual(<<>>, EncryptedToken),
?assertNotEqual(Token, EncryptedToken),
?assertEqual(Token, rebar3_grisp_io_config:decrypt_token(Password, EncryptedToken)).

0 comments on commit e8ed0c2

Please sign in to comment.