diff --git a/CHANGELOG.md b/CHANGELOG.md index b9f22d7..d515df8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v3.0.0 (2022-01-20) + +* Changes + * moved `gen_salt` to the `Base` module + ## v2.3.1 (2022-01-19) * Changes diff --git a/README.md b/README.md index c3afc2d..14f1b6f 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ the `$2y$` prefix, see [this issue](https://github.com/riverrun/comeonin/issues/ ```elixir def deps do [ - {:bcrypt_elixir, "~> 2.0"} + {:bcrypt_elixir, "~> 3.0"} ] end ``` diff --git a/lib/bcrypt.ex b/lib/bcrypt.ex index d597c5e..942376f 100644 --- a/lib/bcrypt.ex +++ b/lib/bcrypt.ex @@ -2,9 +2,6 @@ defmodule Bcrypt do @moduledoc """ Elixir wrapper for the Bcrypt password hashing function. - Most applications will just need to use the `add_hash/2` and `check_pass/3` - convenience functions in this module. - For a lower-level API, see `Bcrypt.Base`. ## Configuration @@ -36,7 +33,7 @@ defmodule Bcrypt do It is also possible to generate hashes with the `$2a$` prefix by running the following command: - Bcrypt.Base.hash_password("hard to guess", Bcrypt.gen_salt(12, true)) + Bcrypt.Base.hash_password("hard to guess", Bcrypt.Base.gen_salt(12, true)) This option should only be used if you need to generate hashes that are then checked by older libraries. @@ -50,21 +47,6 @@ defmodule Bcrypt do alias Bcrypt.Base - @doc """ - Generate a salt for use with the `Bcrypt.Base.hash_password` function. - - The `:log_rounds` parameter determines the computational complexity - of the generation of the password hash. Its default is 12, the minimum is 4, - and the maximum is 31. - - The `:legacy` option is for generating salts with the old `$2a$` prefix. - Only use this option if you need to generate hashes that are then checked - by older libraries. - """ - def gen_salt(log_rounds \\ 12, legacy \\ false) do - Base.gensalt_nif(:crypto.strong_rand_bytes(16), log_rounds, (legacy and 97) || 98) - end - @doc """ Hashes a password with a randomly generated salt. @@ -92,7 +74,7 @@ defmodule Bcrypt do def hash_pwd_salt(password, opts \\ []) do Base.hash_password( password, - gen_salt( + Base.gen_salt( Keyword.get(opts, :log_rounds, Application.get_env(:bcrypt_elixir, :log_rounds, 12)), Keyword.get(opts, :legacy, false) ) diff --git a/lib/bcrypt/base.ex b/lib/bcrypt/base.ex index 0944de2..8746a25 100644 --- a/lib/bcrypt/base.ex +++ b/lib/bcrypt/base.ex @@ -24,6 +24,21 @@ defmodule Bcrypt.Base do end end + @doc """ + Generate a salt for use with the `hash_password` function. + + The `:log_rounds` parameter determines the computational complexity + of the generation of the password hash. Its default is 12, the minimum is 4, + and the maximum is 31. + + The `:legacy` option is for generating salts with the old `$2a$` prefix. + Only use this option if you need to generate hashes that are then checked + by older libraries. + """ + def gen_salt(log_rounds \\ 12, legacy \\ false) do + gensalt_nif(:crypto.strong_rand_bytes(16), log_rounds, (legacy and 97) || 98) + end + @doc """ Hash a password using Bcrypt. """ diff --git a/lib/bcrypt/stats.ex b/lib/bcrypt/stats.ex index a2fd88a..2aa2a88 100644 --- a/lib/bcrypt/stats.ex +++ b/lib/bcrypt/stats.ex @@ -23,6 +23,8 @@ defmodule Bcrypt.Stats do less than 12. """ + alias Bcrypt.Base + @doc """ Hash a password with Bcrypt and print out a report. @@ -39,16 +41,15 @@ defmodule Bcrypt.Stats do * `:password` - the password used * the default is "password" * `:salt` - the salt used - * the default is the output of Bcrypt.gen_salt + * the default is the output of `Bcrypt.Base.gen_salt` """ def report(opts \\ []) do password = Keyword.get(opts, :password, "password") log_rounds = Keyword.get(opts, :log_rounds, 12) - salt = Keyword.get(opts, :salt, Bcrypt.gen_salt(log_rounds)) - {exec_time, encoded} = :timer.tc(Bcrypt.Base, :hash_password, [password, salt]) + salt = Keyword.get(opts, :salt, Base.gen_salt(log_rounds)) + {exec_time, encoded} = :timer.tc(Base, :hash_password, [password, salt]) - Bcrypt.verify_pass(password, encoded) - |> format_result(encoded, exec_time) + password |> Bcrypt.verify_pass(encoded) |> format_result(encoded, exec_time) end defp format_result(check, encoded, exec_time) do diff --git a/mix.exs b/mix.exs index c2a9cc4..283bad3 100644 --- a/mix.exs +++ b/mix.exs @@ -2,11 +2,8 @@ defmodule BcryptElixir.Mixfile do use Mix.Project @source_url "https://github.com/riverrun/bcrypt_elixir" - @version "2.3.1" - - @description """ - Bcrypt password hashing algorithm for Elixir - """ + @version "3.0.0" + @description "Bcrypt password hashing algorithm for Elixir" def project do [ diff --git a/test/base_test.exs b/test/base_test.exs index db428d0..f01666e 100644 --- a/test/base_test.exs +++ b/test/base_test.exs @@ -9,6 +9,27 @@ defmodule Bcrypt.BaseTest do end end + test "gen_salt number of rounds" do + assert String.starts_with?(Base.gen_salt(), "$2b$12$") + assert String.starts_with?(Base.gen_salt(8), "$2b$08$") + assert String.starts_with?(Base.gen_salt(20), "$2b$20$") + end + + test "gen_salt length of salt" do + assert byte_size(Base.gen_salt(8)) == 29 + assert byte_size(Base.gen_salt(20)) == 29 + end + + test "wrong input to gen_salt" do + assert String.starts_with?(Base.gen_salt(3), "$2b$04$") + assert String.starts_with?(Base.gen_salt(32), "$2b$31$") + end + + test "gen_salt with support for $2a$ prefix" do + assert String.starts_with?(Base.gen_salt(8, true), "$2a$08$") + assert String.starts_with?(Base.gen_salt(12, true), "$2a$12$") + end + test "Openwall Bcrypt tests" do [ { diff --git a/test/bcrypt_test.exs b/test/bcrypt_test.exs index 712980b..827e64d 100644 --- a/test/bcrypt_test.exs +++ b/test/bcrypt_test.exs @@ -34,27 +34,6 @@ defmodule BcryptTest do assert String.starts_with?(Bcrypt.hash_pwd_salt("", legacy: false), "$2b$") end - test "gen_salt number of rounds" do - assert String.starts_with?(Bcrypt.gen_salt(), "$2b$12$") - assert String.starts_with?(Bcrypt.gen_salt(8), "$2b$08$") - assert String.starts_with?(Bcrypt.gen_salt(20), "$2b$20$") - end - - test "gen_salt length of salt" do - assert byte_size(Bcrypt.gen_salt(8)) == 29 - assert byte_size(Bcrypt.gen_salt(20)) == 29 - end - - test "wrong input to gen_salt" do - assert String.starts_with?(Bcrypt.gen_salt(3), "$2b$04$") - assert String.starts_with?(Bcrypt.gen_salt(32), "$2b$31$") - end - - test "gen_salt with support for $2a$ prefix" do - assert String.starts_with?(Bcrypt.gen_salt(8, true), "$2a$08$") - assert String.starts_with?(Bcrypt.gen_salt(12, true), "$2a$12$") - end - test "add_hash and check_pass" do assert {:ok, user} = Bcrypt.add_hash("password") |> Bcrypt.check_pass("password") assert {:error, "invalid password"} = Bcrypt.add_hash("pass") |> Bcrypt.check_pass("password")