This is an automated email from the ASF dual-hosted git repository. rnewson pushed a commit to branch decouple_offline_hash_strength_from_online in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 2f443ea262cfe413c32a812dc911355d174d78f9 Author: Robert Newson <[email protected]> AuthorDate: Wed Oct 18 16:58:32 2023 +0100 switch PBKDF2 to fast_pbkdf2 --- rebar.config.script | 3 +- rel/reltool.config | 6 ++-- src/couch/src/couch.app.src | 1 + src/couch/src/couch_passwords.erl | 72 +++++---------------------------------- 4 files changed, 16 insertions(+), 66 deletions(-) diff --git a/rebar.config.script b/rebar.config.script index 60bad79b2..1707bfad4 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -157,7 +157,8 @@ DepDescs = [ {jiffy, "jiffy", {tag, "CouchDB-1.0.9-2"}}, {mochiweb, "mochiweb", {tag, "v3.2.0"}}, {meck, "meck", {tag, "0.9.2"}}, -{recon, "recon", {tag, "2.5.3"}} +{recon, "recon", {tag, "2.5.3"}}, +{fast_pbkdf2, {url, "https://github.com/esl/fast_pbkdf2"}, {tag, "1.0.2"}} ]. WithProper = lists:keyfind(with_proper, 1, CouchConfig) == {with_proper, true}. diff --git a/rel/reltool.config b/rel/reltool.config index 1dca6ff85..392d5c62c 100644 --- a/rel/reltool.config +++ b/rel/reltool.config @@ -66,7 +66,8 @@ %% extra nouveau, - recon + recon, + fast_pbkdf2 ]}, {rel, "start_clean", "", [kernel, stdlib]}, {boot_rel, "couchdb"}, @@ -129,7 +130,8 @@ %% extra {app, nouveau, [{incl_cond, include}]}, - {app, recon, [{incl_cond, include}]} + {app, recon, [{incl_cond, include}]}, + {app, fast_pbkdf2, [{incl_cond, include}]} ]}. {overlay_vars, "couchdb.config"}. diff --git a/src/couch/src/couch.app.src b/src/couch/src/couch.app.src index 6fc293ac1..2cd14ea14 100644 --- a/src/couch/src/couch.app.src +++ b/src/couch/src/couch.app.src @@ -38,6 +38,7 @@ % Upstream deps ibrowse, mochiweb, + fast_pbkdf2, % ASF deps couch_epi, diff --git a/src/couch/src/couch_passwords.erl b/src/couch/src/couch_passwords.erl index b89104603..ac8990861 100644 --- a/src/couch/src/couch_passwords.erl +++ b/src/couch/src/couch_passwords.erl @@ -113,62 +113,16 @@ pbkdf2(Password, Salt, Iterations, DerivedLength) when Iterations > 0, is_integer(DerivedLength) -> - L = ceiling(DerivedLength / ?SHA1_OUTPUT_LENGTH), - <<Bin:DerivedLength/binary, _/binary>> = - iolist_to_binary(pbkdf2(Password, Salt, Iterations, L, 1, [])), - {ok, couch_util:to_hex_bin(Bin)}. - --spec pbkdf2(binary(), binary(), integer(), integer(), integer(), iolist()) -> - iolist(). -pbkdf2(_Password, _Salt, _Iterations, BlockCount, BlockIndex, Acc) when - BlockIndex > BlockCount --> - lists:reverse(Acc); -pbkdf2(Password, Salt, Iterations, BlockCount, BlockIndex, Acc) -> - Block = pbkdf2(Password, Salt, Iterations, BlockIndex, 1, <<>>, <<>>), - pbkdf2(Password, Salt, Iterations, BlockCount, BlockIndex + 1, [Block | Acc]). - --spec pbkdf2( - binary(), - binary(), - integer(), - integer(), - integer(), - binary(), - binary() -) -> binary(). -pbkdf2(_Password, _Salt, Iterations, _BlockIndex, Iteration, _Prev, Acc) when - Iteration > Iterations --> - Acc; -pbkdf2(Password, Salt, Iterations, BlockIndex, 1, _Prev, _Acc) -> - InitialBlock = couch_util:hmac( - sha, - Password, - <<Salt/binary, BlockIndex:32/integer>> - ), - pbkdf2( - Password, - Salt, - Iterations, - BlockIndex, - 2, - InitialBlock, - InitialBlock - ); -pbkdf2(Password, Salt, Iterations, BlockIndex, Iteration, Prev, Acc) -> - Next = couch_util:hmac(sha, Password, Prev), - pbkdf2( - Password, - Salt, - Iterations, - BlockIndex, - Iteration + 1, - Next, - crypto:exor(Next, Acc) - ). + DerivedKey = fast_pbkdf2:pbkdf2(sha, Password, Salt, Iterations, DerivedLength), + {ok, couch_util:to_hex_bin(DerivedKey)}. %% verify two lists for equality without short-circuits to avoid timing attacks. +-if((?OTP_RELEASE) >= 25). +verify(BinA, BinB) when is_binary(BinA), is_binary(BinB), byte_size(BinA) == byte_size(BinB) -> + crypto:hash_equals(BinA, BinB); +verify(BinA, BinB) when is_binary(BinA), is_binary(BinB) -> + false. +-else. -spec verify(string(), string(), integer()) -> boolean(). verify([X | RestX], [Y | RestY], Result) -> verify(RestX, RestY, (X bxor Y) bor Result); @@ -189,12 +143,4 @@ verify(X, Y) when is_list(X) and is_list(Y) -> end; verify(_X, _Y) -> false. - --spec ceiling(number()) -> integer(). -ceiling(X) -> - T = erlang:trunc(X), - case (X - T) of - Neg when Neg < 0 -> T; - Pos when Pos > 0 -> T + 1; - _ -> T - end. +-endif.
