From 51b7d111bc082bc3883bfdab080640fc1d54b365 Mon Sep 17 00:00:00 2001 From: Nelson Vides Date: Thu, 28 Dec 2023 23:19:05 +0100 Subject: [PATCH] Make it possible to use without nifs --- README.md | 14 ++++++++++++++ src/fast_scram.app.src | 1 + src/fast_scram_definitions.erl | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/README.md b/README.md index 70eee0c..9dfdcbb 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,20 @@ and also that other defence mechanisms like IP blacklisting or traffic shaping, It all boils down to the right PBKDF2 implementation, as done in [fast_pbkdf2][fast_pbkdf2], which is on average 10x faster on the machines I've tested it. But while the erlang implementation consumes memory linearly to the iteration count, the NIF implementation does not allocate any more memory. +### Running without NIFs +Note that since OTP24.2, the `crypto` application exposes a native `pbkdf2_hmac` function. However, the NIF implementation from [fast_pbkdf2] is twice as fast, so that one is left as a default. + +If for any particular reason you want to skip compiling and loading custom NIFs, you can override the dependency using `rebar3`'s overrides as below, this way the dependency will not be fetched and code will be compiled to use the `crypto` callback instead. + +```erlang +{overrides, + [ + {override, fast_scram, [{erl_opts, [{d, 'WITHOUT_NIFS'}]}, {deps, []}]}, + ] +}. + +``` + ## Read more: * SCRAM: [RFC5802](https://tools.ietf.org/html/rfc5802) * SCRAM-SHA-256 update: [RFC7677](https://tools.ietf.org/html/rfc7677) diff --git a/src/fast_scram.app.src b/src/fast_scram.app.src index 6b2caf2..b6e6a39 100644 --- a/src/fast_scram.app.src +++ b/src/fast_scram.app.src @@ -8,6 +8,7 @@ crypto, fast_pbkdf2 ]}, + {optional_applications, [fast_pbkdf2]}, {env,[]}, {modules, []}, {licenses, ["Apache 2.0"]}, diff --git a/src/fast_scram_definitions.erl b/src/fast_scram_definitions.erl index e375148..aa8198f 100644 --- a/src/fast_scram_definitions.erl +++ b/src/fast_scram_definitions.erl @@ -31,10 +31,18 @@ %% ServerKey := HMAC(SaltedPassword, "Server Key") %% ServerSignature := HMAC(ServerKey, AuthMessage) +-ifdef(WITHOUT_NIFS). +-spec salted_password(sha_type(), binary(), binary(), non_neg_integer()) -> binary(). +salted_password(Sha, Password, Salt, IterationCount) + when ?is_valid_hash(Sha), is_binary(Password), is_binary(Salt), ?is_positive_integer(IterationCount) -> + #{size := KeyLength} = crypto:hash_info(Sha), + crypto:pbkdf2_hmac(Sha, Password, Salt, IterationCount, KeyLength). +-else. -spec salted_password(sha_type(), binary(), binary(), non_neg_integer()) -> binary(). salted_password(Sha, Password, Salt, IterationCount) when ?is_valid_hash(Sha), is_binary(Password), is_binary(Salt), ?is_positive_integer(IterationCount) -> fast_pbkdf2:pbkdf2(Sha, Password, Salt, IterationCount). +-endif. -spec client_key(sha_type(), binary()) -> binary(). client_key(Sha, SaltedPassword)