From e56ba41027e5861276c4e21432f1b34df339bf67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=B8=B9?= Date: Thu, 16 Mar 2017 10:03:58 +0800 Subject: [PATCH 1/7] Update arg sslopts --- test/emqttd_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/emqttd_SUITE.erl b/test/emqttd_SUITE.erl index 926a68824..be60926fb 100644 --- a/test/emqttd_SUITE.erl +++ b/test/emqttd_SUITE.erl @@ -715,7 +715,7 @@ change_opts(SslType, DataDir, Vals) -> lists:foldl(fun({Protocol, Port, Opts} = Listener, Acc) -> case Protocol of ssl -> - SslOpts = proplists:get_value(ssl, Opts), + SslOpts = proplists:get_value(sslopts, Opts), Keyfile = filename:join([DataDir, proplists:get_value(keyfile, SslOpts)]), Certfile = filename:join([DataDir, proplists:get_value(certfile, SslOpts)]), TupleList1 = lists:keyreplace(keyfile, 1, SslOpts, {keyfile, Keyfile}), From 18c8785bf9e6613c9a58bd356edab33accc35da2 Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Fri, 24 Mar 2017 10:46:08 +0800 Subject: [PATCH 2/7] Fix 'rebar command not found' --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index b35c84f88..c830eed11 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,9 @@ PROJECT = emqttd PROJECT_DESCRIPTION = Erlang MQTT Broker PROJECT_VERSION = 2.1.0 -NO_AUTOPATCH = cuttlefish - -DEPS = gproc lager esockd mochiweb lager_syslog pbkdf2 +DEPS = goldrush gproc lager esockd mochiweb lager_syslog pbkdf2 +dep_goldrush = git https://github.com/basho/goldrush 0.1.9 dep_gproc = git https://github.com/uwiger/gproc dep_getopt = git https://github.com/jcomellas/getopt v0.8.2 dep_lager = git https://github.com/basho/lager master @@ -16,6 +15,8 @@ dep_pbkdf2 = git https://github.com/comtihon/erlang-pbkdf2.git 2.0.0 ERLC_OPTS += +'{parse_transform, lager_transform}' +NO_AUTOPATCH = cuttlefish + BUILD_DEPS = cuttlefish dep_cuttlefish = git https://github.com/emqtt/cuttlefish From 852c671881747503f43ea0d1a1d2e70df6b5bb36 Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Fri, 24 Mar 2017 10:46:52 +0800 Subject: [PATCH 3/7] Add goldrush dep --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 659b453cf..c3b10fabc 100644 --- a/rebar.config +++ b/rebar.config @@ -1,4 +1,4 @@ {deps, [ -{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager","master"}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}},{lager_syslog,".*",{git,"https://github.com/basho/lager_syslog",""}},{pbkdf2,".*",{git,"https://github.com/comtihon/erlang-pbkdf2.git","2.0.0"}} +{goldrush,".*",{git,"https://github.com/basho/goldrush","0.1.9"}},{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager","master"}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}},{lager_syslog,".*",{git,"https://github.com/basho/lager_syslog",""}},{pbkdf2,".*",{git,"https://github.com/comtihon/erlang-pbkdf2.git","2.0.0"}} ]}. {erl_opts, [{parse_transform,lager_transform}]}. From 181ac361717a33c03ff75e2898213f18327a738d Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Fri, 24 Mar 2017 11:26:42 +0800 Subject: [PATCH 4/7] Remove the 'erlang-pbkdf2' dep to resolve CI building error --- Makefile | 15 +++++++-------- rebar.config | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index c830eed11..276b383eb 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,13 @@ PROJECT_VERSION = 2.1.0 DEPS = goldrush gproc lager esockd mochiweb lager_syslog pbkdf2 -dep_goldrush = git https://github.com/basho/goldrush 0.1.9 -dep_gproc = git https://github.com/uwiger/gproc -dep_getopt = git https://github.com/jcomellas/getopt v0.8.2 -dep_lager = git https://github.com/basho/lager master -dep_esockd = git https://github.com/emqtt/esockd emq20 -dep_mochiweb = git https://github.com/emqtt/mochiweb -dep_lager_syslog = git https://github.com/basho/lager_syslog -dep_pbkdf2 = git https://github.com/comtihon/erlang-pbkdf2.git 2.0.0 +dep_goldrush = git https://github.com/basho/goldrush 0.1.9 +dep_gproc = git https://github.com/uwiger/gproc +dep_getopt = git https://github.com/jcomellas/getopt v0.8.2 +dep_lager = git https://github.com/basho/lager master +dep_esockd = git https://github.com/emqtt/esockd emq20 +dep_mochiweb = git https://github.com/emqtt/mochiweb +dep_lager_syslog = git https://github.com/basho/lager_syslog ERLC_OPTS += +'{parse_transform, lager_transform}' diff --git a/rebar.config b/rebar.config index c3b10fabc..a37fed199 100644 --- a/rebar.config +++ b/rebar.config @@ -1,4 +1,4 @@ {deps, [ -{goldrush,".*",{git,"https://github.com/basho/goldrush","0.1.9"}},{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager","master"}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}},{lager_syslog,".*",{git,"https://github.com/basho/lager_syslog",""}},{pbkdf2,".*",{git,"https://github.com/comtihon/erlang-pbkdf2.git","2.0.0"}} +{goldrush,".*",{git,"https://github.com/basho/goldrush","0.1.9"}},{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager","master"}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}},{lager_syslog,".*",{git,"https://github.com/basho/lager_syslog",""}},{pbkdf2,".*",{git,"",""}} ]}. {erl_opts, [{parse_transform,lager_transform}]}. From d9b4376c17c912ce6c6efbf482ed938d227ee6cc Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Fri, 24 Mar 2017 11:27:23 +0800 Subject: [PATCH 5/7] Copy the pbkdf2.erl module from erlang-pbkdf2 project --- src/pbkdf2.erl | 157 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 src/pbkdf2.erl diff --git a/src/pbkdf2.erl b/src/pbkdf2.erl new file mode 100644 index 000000000..34b7b5652 --- /dev/null +++ b/src/pbkdf2.erl @@ -0,0 +1,157 @@ +% Licensed under the Apache License, Version 2.0 (the "License"); you may not +% use this file except in compliance with the License. You may obtain a copy of +% the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +% License for the specific language governing permissions and limitations under +% the License. + +-module(pbkdf2). + +-export([pbkdf2/4, pbkdf2/5, compare_secure/2, to_hex/1]). + +-type(hex_char() :: 48 .. 57 | 97 .. 102). +-type(hex_list() :: [hex_char()]). + +-type(digest_func_info() :: md4 | md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512). + +-type(mac_func_info() :: {hmac, digest_func_info()} | digest_func_info()). + +-define(MAX_DERIVED_KEY_LENGTH, (1 bsl 32 - 1)). + +%%-------------------------------------------------------------------- +%% Public API +%%-------------------------------------------------------------------- + +-spec(pbkdf2(MacFunc, Password, Salt, Iterations) -> {ok, Key} | {error, derived_key_too_long} when + MacFunc :: mac_func_info(), + Password :: binary(), + Salt :: binary(), + Iterations :: integer(), + Key :: binary()). +pbkdf2(MacFunc, Password, Salt, Iterations) -> + MacFunc1 = resolve_mac_func(MacFunc), + DerivedLength = byte_size(MacFunc1(<<"test key">>, <<"test data">>)), + Bin = pbkdf2(MacFunc1, Password, Salt, Iterations, DerivedLength, 1, []), + {ok, Bin}. + +-spec(pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength) -> {ok, Key} | {error, derived_key_too_long} when + MacFunc :: mac_func_info(), + Password :: binary(), + Salt :: binary(), + Iterations :: integer(), + DerivedLength :: integer(), + Key :: binary()). +pbkdf2(_MacFunc, _Password, _Salt, _Iterations, DerivedLength) when DerivedLength > ?MAX_DERIVED_KEY_LENGTH -> + {error, derived_key_too_long}; +pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength) -> + MacFunc1 = resolve_mac_func(MacFunc), + Bin = pbkdf2(MacFunc1, Password, Salt, Iterations, DerivedLength, 1, []), + {ok, Bin}. + +-spec(to_hex(Data) -> HexData when + Data :: iolist(), + HexData :: binary() | hex_list()). +to_hex(<<>>) -> + <<>>; +to_hex(<>) -> + CharHex1 = to_hex_digit(Char div 16), + CharHex2 = to_hex_digit(Char rem 16), + RestHex = to_hex(Rest), + <>; +to_hex([]) -> + []; +to_hex([Char | Rest]) -> + [to_hex_digit(Char div 16), to_hex_digit(Char rem 16) | to_hex(Rest)]. + +%%-------------------------------------------------------------------- +%% Internal Functions +%%-------------------------------------------------------------------- + +-spec(pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength, BlockIndex, Acc) -> Key when + MacFunc :: fun((binary(), binary()) -> binary()), + Password :: binary(), + Salt :: binary(), + Iterations :: integer(), + DerivedLength :: integer(), + BlockIndex :: integer(), + Acc :: iolist(), + Key :: binary()). +pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength, BlockIndex, Acc) -> + case iolist_size(Acc) > DerivedLength of + true -> <> = iolist_to_binary(lists:reverse(Acc)), + Bin; + false -> Block = pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, 1, <<>>, <<>>), + pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength, BlockIndex + 1, [Block | Acc]) + end. + +-spec(pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, Iteration, Prev, Acc) -> Key when + MacFunc :: fun((binary(), binary()) -> binary()), + Password :: binary(), + Salt :: binary(), + Iterations :: integer(), + BlockIndex :: integer(), + Iteration :: integer(), + Prev :: binary(), + Acc :: binary(), + Key :: binary()). +pbkdf2(_MacFunc, _Password, _Salt, Iterations, _BlockIndex, Iteration, _Prev, Acc) when Iteration > Iterations -> + Acc; +pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, 1, _Prev, _Acc) -> + InitialBlock = MacFunc(Password, <>), + pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, 2, InitialBlock, InitialBlock); +pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, Iteration, Prev, Acc) -> + Next = MacFunc(Password, Prev), + pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, Iteration + 1, Next, crypto:exor(Next, Acc)). + +resolve_mac_func({hmac, DigestFunc}) -> + fun(Key, Data) -> + HMAC = crypto:hmac_init(DigestFunc, Key), + HMAC1 = crypto:hmac_update(HMAC, Data), + crypto:hmac_final(HMAC1) + end; + +resolve_mac_func(MacFunc) when is_function(MacFunc) -> + MacFunc; + +resolve_mac_func(md4) -> resolve_mac_func({hmac, md4}); +resolve_mac_func(md5) -> resolve_mac_func({hmac, md5}); +resolve_mac_func(ripemd160) -> resolve_mac_func({hmac, ripemd160}); +resolve_mac_func(sha) -> resolve_mac_func({hmac, sha}); +resolve_mac_func(sha224) -> resolve_mac_func({hmac, sha224}); +resolve_mac_func(sha256) -> resolve_mac_func({hmac, sha256}); +resolve_mac_func(sha384) -> resolve_mac_func({hmac, sha384}); +resolve_mac_func(sha512) -> resolve_mac_func({hmac, sha512}). + +%% Compare two strings or binaries for equality without short-circuits to avoid timing attacks. + +-spec(compare_secure(First, Second) -> boolean() when + First :: binary() | string(), + Second :: binary() | string()). +compare_secure(<>, <>) -> + compare_secure(binary_to_list(X), binary_to_list(Y)); +compare_secure(X, Y) when is_list(X) and is_list(Y) -> + case length(X) == length(Y) of + true -> compare_secure(X, Y, 0); + false -> false + end; +compare_secure(_X, _Y) -> false. + +-spec(compare_secure(First, Second, Accum) -> boolean() when + First :: string(), + Second :: string(), + Accum :: integer()). +compare_secure([X|RestX], [Y|RestY], Result) -> + compare_secure(RestX, RestY, (X bxor Y) bor Result); +compare_secure([], [], Result) -> + Result == 0. + +-spec(to_hex_digit(Nyble :: 0 .. 15) -> hex_char()). +to_hex_digit(N) when N < 10 -> + $0 + N; +to_hex_digit(N) -> + $a + N - 10. From b54fba2a5dd0947308cff759f734100d0ccc83de Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Fri, 24 Mar 2017 12:35:39 +0800 Subject: [PATCH 6/7] Depend on emqtt/pbkdf2 to resovle the building errors of Travis CI --- Makefile | 3 ++- rebar.config | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 276b383eb..88710ea09 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ PROJECT = emqttd PROJECT_DESCRIPTION = Erlang MQTT Broker PROJECT_VERSION = 2.1.0 -DEPS = goldrush gproc lager esockd mochiweb lager_syslog pbkdf2 +DEPS = goldrush gproc lager esockd mochiweb pbkdf2 lager_syslog dep_goldrush = git https://github.com/basho/goldrush 0.1.9 dep_gproc = git https://github.com/uwiger/gproc @@ -10,6 +10,7 @@ dep_getopt = git https://github.com/jcomellas/getopt v0.8.2 dep_lager = git https://github.com/basho/lager master dep_esockd = git https://github.com/emqtt/esockd emq20 dep_mochiweb = git https://github.com/emqtt/mochiweb +dep_pbkdf2 = git https://github.com/emqtt/pbkdf2 2.0.1 dep_lager_syslog = git https://github.com/basho/lager_syslog ERLC_OPTS += +'{parse_transform, lager_transform}' diff --git a/rebar.config b/rebar.config index a37fed199..3e4afc5d7 100644 --- a/rebar.config +++ b/rebar.config @@ -1,4 +1,4 @@ {deps, [ -{goldrush,".*",{git,"https://github.com/basho/goldrush","0.1.9"}},{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager","master"}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}},{lager_syslog,".*",{git,"https://github.com/basho/lager_syslog",""}},{pbkdf2,".*",{git,"",""}} +{goldrush,".*",{git,"https://github.com/basho/goldrush","0.1.9"}},{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager","master"}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}},{pbkdf2,".*",{git,"https://github.com/emqtt/pbkdf2","2.0.1"}},{lager_syslog,".*",{git,"https://github.com/basho/lager_syslog",""}} ]}. {erl_opts, [{parse_transform,lager_transform}]}. From a1984d857a5a345f2a6605c5158191035d2e9b85 Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Fri, 24 Mar 2017 12:35:54 +0800 Subject: [PATCH 7/7] Remove src/pbkdf2.erl --- src/pbkdf2.erl | 157 ------------------------------------------------- 1 file changed, 157 deletions(-) delete mode 100644 src/pbkdf2.erl diff --git a/src/pbkdf2.erl b/src/pbkdf2.erl deleted file mode 100644 index 34b7b5652..000000000 --- a/src/pbkdf2.erl +++ /dev/null @@ -1,157 +0,0 @@ -% Licensed under the Apache License, Version 2.0 (the "License"); you may not -% use this file except in compliance with the License. You may obtain a copy of -% the License at -% -% http://www.apache.org/licenses/LICENSE-2.0 -% -% Unless required by applicable law or agreed to in writing, software -% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -% License for the specific language governing permissions and limitations under -% the License. - --module(pbkdf2). - --export([pbkdf2/4, pbkdf2/5, compare_secure/2, to_hex/1]). - --type(hex_char() :: 48 .. 57 | 97 .. 102). --type(hex_list() :: [hex_char()]). - --type(digest_func_info() :: md4 | md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512). - --type(mac_func_info() :: {hmac, digest_func_info()} | digest_func_info()). - --define(MAX_DERIVED_KEY_LENGTH, (1 bsl 32 - 1)). - -%%-------------------------------------------------------------------- -%% Public API -%%-------------------------------------------------------------------- - --spec(pbkdf2(MacFunc, Password, Salt, Iterations) -> {ok, Key} | {error, derived_key_too_long} when - MacFunc :: mac_func_info(), - Password :: binary(), - Salt :: binary(), - Iterations :: integer(), - Key :: binary()). -pbkdf2(MacFunc, Password, Salt, Iterations) -> - MacFunc1 = resolve_mac_func(MacFunc), - DerivedLength = byte_size(MacFunc1(<<"test key">>, <<"test data">>)), - Bin = pbkdf2(MacFunc1, Password, Salt, Iterations, DerivedLength, 1, []), - {ok, Bin}. - --spec(pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength) -> {ok, Key} | {error, derived_key_too_long} when - MacFunc :: mac_func_info(), - Password :: binary(), - Salt :: binary(), - Iterations :: integer(), - DerivedLength :: integer(), - Key :: binary()). -pbkdf2(_MacFunc, _Password, _Salt, _Iterations, DerivedLength) when DerivedLength > ?MAX_DERIVED_KEY_LENGTH -> - {error, derived_key_too_long}; -pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength) -> - MacFunc1 = resolve_mac_func(MacFunc), - Bin = pbkdf2(MacFunc1, Password, Salt, Iterations, DerivedLength, 1, []), - {ok, Bin}. - --spec(to_hex(Data) -> HexData when - Data :: iolist(), - HexData :: binary() | hex_list()). -to_hex(<<>>) -> - <<>>; -to_hex(<>) -> - CharHex1 = to_hex_digit(Char div 16), - CharHex2 = to_hex_digit(Char rem 16), - RestHex = to_hex(Rest), - <>; -to_hex([]) -> - []; -to_hex([Char | Rest]) -> - [to_hex_digit(Char div 16), to_hex_digit(Char rem 16) | to_hex(Rest)]. - -%%-------------------------------------------------------------------- -%% Internal Functions -%%-------------------------------------------------------------------- - --spec(pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength, BlockIndex, Acc) -> Key when - MacFunc :: fun((binary(), binary()) -> binary()), - Password :: binary(), - Salt :: binary(), - Iterations :: integer(), - DerivedLength :: integer(), - BlockIndex :: integer(), - Acc :: iolist(), - Key :: binary()). -pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength, BlockIndex, Acc) -> - case iolist_size(Acc) > DerivedLength of - true -> <> = iolist_to_binary(lists:reverse(Acc)), - Bin; - false -> Block = pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, 1, <<>>, <<>>), - pbkdf2(MacFunc, Password, Salt, Iterations, DerivedLength, BlockIndex + 1, [Block | Acc]) - end. - --spec(pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, Iteration, Prev, Acc) -> Key when - MacFunc :: fun((binary(), binary()) -> binary()), - Password :: binary(), - Salt :: binary(), - Iterations :: integer(), - BlockIndex :: integer(), - Iteration :: integer(), - Prev :: binary(), - Acc :: binary(), - Key :: binary()). -pbkdf2(_MacFunc, _Password, _Salt, Iterations, _BlockIndex, Iteration, _Prev, Acc) when Iteration > Iterations -> - Acc; -pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, 1, _Prev, _Acc) -> - InitialBlock = MacFunc(Password, <>), - pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, 2, InitialBlock, InitialBlock); -pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, Iteration, Prev, Acc) -> - Next = MacFunc(Password, Prev), - pbkdf2(MacFunc, Password, Salt, Iterations, BlockIndex, Iteration + 1, Next, crypto:exor(Next, Acc)). - -resolve_mac_func({hmac, DigestFunc}) -> - fun(Key, Data) -> - HMAC = crypto:hmac_init(DigestFunc, Key), - HMAC1 = crypto:hmac_update(HMAC, Data), - crypto:hmac_final(HMAC1) - end; - -resolve_mac_func(MacFunc) when is_function(MacFunc) -> - MacFunc; - -resolve_mac_func(md4) -> resolve_mac_func({hmac, md4}); -resolve_mac_func(md5) -> resolve_mac_func({hmac, md5}); -resolve_mac_func(ripemd160) -> resolve_mac_func({hmac, ripemd160}); -resolve_mac_func(sha) -> resolve_mac_func({hmac, sha}); -resolve_mac_func(sha224) -> resolve_mac_func({hmac, sha224}); -resolve_mac_func(sha256) -> resolve_mac_func({hmac, sha256}); -resolve_mac_func(sha384) -> resolve_mac_func({hmac, sha384}); -resolve_mac_func(sha512) -> resolve_mac_func({hmac, sha512}). - -%% Compare two strings or binaries for equality without short-circuits to avoid timing attacks. - --spec(compare_secure(First, Second) -> boolean() when - First :: binary() | string(), - Second :: binary() | string()). -compare_secure(<>, <>) -> - compare_secure(binary_to_list(X), binary_to_list(Y)); -compare_secure(X, Y) when is_list(X) and is_list(Y) -> - case length(X) == length(Y) of - true -> compare_secure(X, Y, 0); - false -> false - end; -compare_secure(_X, _Y) -> false. - --spec(compare_secure(First, Second, Accum) -> boolean() when - First :: string(), - Second :: string(), - Accum :: integer()). -compare_secure([X|RestX], [Y|RestY], Result) -> - compare_secure(RestX, RestY, (X bxor Y) bor Result); -compare_secure([], [], Result) -> - Result == 0. - --spec(to_hex_digit(Nyble :: 0 .. 15) -> hex_char()). -to_hex_digit(N) when N < 10 -> - $0 + N; -to_hex_digit(N) -> - $a + N - 10.