diff --git a/rebar.config b/rebar.config index df7425f..d651212 100644 --- a/rebar.config +++ b/rebar.config @@ -3,6 +3,7 @@ %% %% Copyright (c) 2007-2017 Basho Technologies, Inc. %% Copyright (c) 2019-2025 Workday, Inc. +%% Copyright (c) 2026 TI Tokyo. %% %% This file is provided to you under the Apache License, %% Version 2.0 (the "License"); you may not use this file @@ -49,7 +50,6 @@ {clique, {git, "https://github.com/OpenRiak/clique.git", {branch, "openriak-3.4"}}}, {eleveldb, {git, "https://github.com/OpenRiak/eleveldb.git", {branch, "openriak-3.4"}}}, {riak_ensemble, {git, "https://github.com/OpenRiak/riak_ensemble", {branch, "openriak-3.4"}}}, - {pbkdf2, {git, "https://github.com/OpenRiak/erlang-pbkdf2.git", {branch, "openriak-3.4"}}}, {cluster_info, {git, "https://github.com/OpenRiak/cluster_info.git", {branch, "openriak-3.4"}}}, {exometer_core, {git, "https://github.com/OpenRiak/exometer_core.git", {branch, "openriak-3.4"}}}, {basho_stats, {git, "https://github.com/OpenRiak/basho_stats.git", {branch, "openriak-3.4"}}} diff --git a/src/riak_core.app.src b/src/riak_core.app.src index ca2776d..d9b8daf 100644 --- a/src/riak_core.app.src +++ b/src/riak_core.app.src @@ -18,7 +18,6 @@ riak_sysmon, os_mon, eleveldb, - pbkdf2, poolboy, exometer_core, clique, diff --git a/src/riak_core_pw_auth.erl b/src/riak_core_pw_auth.erl index 523bd67..dbbb9ea 100644 --- a/src/riak_core_pw_auth.erl +++ b/src/riak_core_pw_auth.erl @@ -1,6 +1,7 @@ %% ------------------------------------------------------------------- %% %% Copyright (c) 2013 Basho Technologies, Inc. +%% Copyright (c) 2026 TI Tokyo. %% %% This file is provided to you under the Apache License, %% Version 2.0 (the "License"); you may not use this file @@ -27,24 +28,49 @@ -define(HASH_ITERATIONS, 65536). %% TODO this should call a default_hash_func() function to get default based on erlang version -define(HASH_FUNCTION, sha). +-define(KEY_LENGTH, 20). %% the value used in pbkdf2 for sha -define(AUTH_NAME, pbkdf2). %% @doc Hash a plaintext password, returning hashed password and algorithm details +-spec hash_password(binary()) -> + {ok, binary(), ?AUTH_NAME, ?HASH_FUNCTION, binary(), pos_integer()}. hash_password(BinaryPass) when is_binary(BinaryPass) -> % TODO: Do something more with the salt? % Generate salt the simple way Salt = crypto:strong_rand_bytes(?SALT_LENGTH), % Hash the original password and store as hex - {ok, HashedPass} = pbkdf2:pbkdf2(?HASH_FUNCTION, BinaryPass, Salt, ?HASH_ITERATIONS), - HexPass = pbkdf2:to_hex(HashedPass), + HashedPass = crypto:pbkdf2_hmac( + ?HASH_FUNCTION, BinaryPass, Salt, ?HASH_ITERATIONS, ?KEY_LENGTH), + HexPass = to_hex(HashedPass), {ok, HexPass, ?AUTH_NAME, ?HASH_FUNCTION, Salt, ?HASH_ITERATIONS}. %% @doc Check a plaintext password with a hashed password -check_password(BinaryPass, HashedPassword, HashFunction, Salt, HashIterations) when is_binary(BinaryPass) -> - +-spec check_password(binary(), binary(), ?HASH_FUNCTION, binary(), pos_integer()) -> + boolean(). +check_password(BinaryPass, HashedPassword, HashFunction, Salt, HashIterations) + when is_binary(BinaryPass) -> % Hash EnteredPassword to compare to HashedPassword - {ok, HashedPass} = pbkdf2:pbkdf2(HashFunction, BinaryPass, Salt, HashIterations), - HexPass = pbkdf2:to_hex(HashedPass), - pbkdf2:compare_secure(HexPass, HashedPassword). + HashedPass = crypto:pbkdf2_hmac( + HashFunction, BinaryPass, Salt, HashIterations, ?KEY_LENGTH), + HexPass = to_hex(HashedPass), + compare_secure(binary_to_list(HexPass), binary_to_list(HashedPassword)). + + +%% copied, slightly simplified, from erlang-pbkdf2/src/pbkdf2.erl +to_hex(Data) -> + string:lowercase(binary:encode_hex(Data)). + +compare_secure(X, Y) -> + case length(X) == length(Y) of + true -> + compare_secure(X, Y, 0); + false -> + false + end. + +compare_secure([X|RestX], [Y|RestY], Result) -> + compare_secure(RestX, RestY, (X bxor Y) bor Result); +compare_secure([], [], Result) -> + Result == 0.