switch to fast_pbkdf2 for hashing
diff --git a/.gitignore b/.gitignore
index 30aed77..fe9341b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,7 @@
src/proper/
src/rebar/
src/recon/
+src/fast_pbkdf2/
src/snappy/
src/ssl_verify_fun/
src/triq/
diff --git a/rebar.config.script b/rebar.config.script
index 9098e6d..ad8787b 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -157,7 +157,8 @@
{jiffy, "jiffy", {tag, "CouchDB-1.0.9-2"}},
{mochiweb, "mochiweb", {tag, "v3.1.1"}},
{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 1dca6ff..392d5c6 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 6fc293a..bf58a7c 100644
--- a/src/couch/src/couch.app.src
+++ b/src/couch/src/couch.app.src
@@ -49,7 +49,8 @@
ioq,
couch_stats,
hyper,
- couch_dist
+ couch_dist,
+ fast_pbkdf2
]},
{env, [
{httpd_global_handlers, [
diff --git a/src/couch/src/couch_passwords.erl b/src/couch/src/couch_passwords.erl
index b891046..0f3083c 100644
--- a/src/couch/src/couch_passwords.erl
+++ b/src/couch/src/couch_passwords.erl
@@ -83,8 +83,8 @@
is_integer(Iterations),
Iterations > 0
->
- {ok, Result} = pbkdf2(Password, Salt, Iterations, ?SHA1_OUTPUT_LENGTH),
- Result;
+ DerivedKey = fast_pbkdf2:pbkdf2(sha, Password, Salt, Iterations),
+ couch_util:to_hex_bin(DerivedKey);
pbkdf2(Password, Salt, Iterations) when
is_binary(Salt),
is_integer(Iterations),
@@ -113,60 +113,8 @@
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.
-spec verify(string(), string(), integer()) -> boolean().
@@ -189,12 +137,3 @@
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.