libsalty icon indicating copy to clipboard operation
libsalty copied to clipboard

Pwhash implementation

Open daveed-al opened this issue 7 years ago • 6 comments

daveed-al avatar Jan 23 '18 09:01 daveed-al

work in progress for pwhash implementation. the libsodium crypto_pwhash function https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_pwhash/crypto_pwhash.c#L129 has a switch / case for the algorithm, values can either be can either be pwhash_ALG_ARGON2ID13 or pwhash_ALG_ARGON2I13 when I call the Elixir function using Salty.Nif.pwhash_ALG_ARGON2ID13 it works when I use Salty.Nif.pwhash_ALG_ARGON2I13 it errors.

here is the code I use to test:

require Salty.Nif

### pwhash
outlen = 16
password = "thepassword"
{:ok, password_salt} = Salty.Nif.randombytes_buf(16)
opslimit = 2
memlimit = Salty.Nif.pwhash_argon2id_MEMLIMIT_INTERACTIVE
# alg can either be pwhash_ALG_ARGON2ID13 or pwhash_ALG_ARGON2I13
alg = Salty.Nif.pwhash_ALG_ARGON2ID13
# alg = Salty.Nif.pwhash_ALG_ARGON2I13
{:ok, pwhash} = Salty.Nif.pwhash(outlen, password, password_salt, opslimit, memlimit, alg)

also the code for str_verify and needs_rehash is in progress as well - I pull request to reach out for help and get feedback and understand what I am missing. thanks

daveed-al avatar Jan 23 '18 09:01 daveed-al

Hi there, and thanks for taking the time to work on this!

The approach to high level APIs in this library is to not bind them directly, but provide a method "primitive()" that returns the module that implements the default (high level) primitive. Take the secretbox API as an example.

In case of Salty.PwHash, that would lead to exposing the pwhash/pwhash_str/str_verify/str_needs_rehash methods in the modules that implement the primitives (Salty.PwHash.Scrypt, Salty.PwHash.Argon2i, Salty.PwHash.Argon2id), and returning the Argon2id module from the Salty.PwHash.primitive() method. This removes the requirement to work with algorithm identifiers altogether, and lets you call the primitives' implementations directly in salty_nif.c instead.

As a special case, the str_verify/str_needs_rehash methods could be implemented in the Salty.PwHash module as well, as they do not need any algorithm specific input parameters.

That aside, what is the error message that you're getting? Also, which version of libsodium are you using, and on which system are you testing?

On another note, in order to use pwhash within Elixir (or Erlang's VM for that matter), the methods for pwhash, str and str_verify will need to use the dirty scheduler in order for applications to be able to use it without messing up the scheduler.

I hope this answers some of your questions, let me know if there is anything else.

ArteMisc avatar Jan 25 '18 02:01 ArteMisc

Hi @ArteMisc - I apologize for the delay and thanks a lot for your detailed explanation. I am still going through it. The error I am getting (when alg == Salty.Nif.pwhash_ALG_ARGON2I13 == 1) is ** (MatchError) no match of right hand side value: {:error, :salty_error_unknown}

If I try a few more times I have a segmentation fault:

iex(18)> {:ok, pwhash} = Salty.Nif.pwhash(outlen, password, password_salt, opslimit, memlimit, 1)
** (MatchError) no match of right hand side value: {:error, :salty_error_unknown}

iex(18)> {:ok, pwhash} = Salty.Nif.pwhash(outlen, password, password_salt, opslimit, memlimit, 1)
** (MatchError) got FunctionClauseError with message "no function clause matching in Inspect.Any.inspect/2" while retrieving Exception.message/1 for %Inspect.Error{message: "got FunctionClauseError with message \"no function clause matching in Inspect.Any.inspect/2\" while inspecting %{__exception__: true, __struct__: MatchError, term: {:error, :salty_error_unknown}}"}

iex(18)> {:ok, pwhash} = Salty.Nif.pwhash(outlen, password, password_salt, opslimit, memlimit, 1)
[1]    29426 segmentation fault  iex -S mix

I am using libsodium 1.0.16 on macOS High Sierra 10.13.2 I was using Elixir 1.7.0 but have the same issue when now using Elixir 1.6.0.

Hopefully that helps troubleshooting. Thanks

daveed-al avatar Jan 29 '18 07:01 daveed-al

Implementing primitives now @ArteMisc to respect high level API approach.

daveed-al avatar Jan 30 '18 03:01 daveed-al

updated the pull request - the seg fault no longer happens. Now using the following code to test:

outlen = 16
password = "thepassword"
{:ok, password_salt} = Salty.Nif.randombytes_buf(16)
opslimit = Salty.PwHash.Argon2i.opslimit_interactive
memlimit = Salty.PwHash.Argon2i.memlimit_interactive
alg = Salty.PwHash.Argon2i.alg
{:ok, pwhash} = Salty.PwHash.Argon2i.pwhash(outlen, password, password_salt, opslimit, memlimit, alg)

daveed-al avatar Jan 30 '18 10:01 daveed-al

any updates @ArteMisc ? thanks

daveed-al avatar Feb 06 '18 10:02 daveed-al