refactor(authn): restore pbkdf2 password hashing functionality
This commit is contained in:
parent
2b0a3e8ba3
commit
708d9cfc6c
|
@ -34,18 +34,34 @@
|
||||||
-type(password_hash() :: binary()).
|
-type(password_hash() :: binary()).
|
||||||
|
|
||||||
-type(hash_type_simple() :: plain | md5 | sha | sha256 | sha512).
|
-type(hash_type_simple() :: plain | md5 | sha | sha256 | sha512).
|
||||||
-type(hash_type() :: hash_type_simple() | bcrypt).
|
-type(hash_type() :: hash_type_simple() | bcrypt | pbkdf2).
|
||||||
|
|
||||||
-type(salt_position() :: prefix | suffix).
|
-type(salt_position() :: prefix | suffix).
|
||||||
-type(salt() :: binary()).
|
-type(salt() :: binary()).
|
||||||
|
|
||||||
-type(hash_params() :: {bcrypt, salt()} | {hash_type_simple(), salt(), salt_position()}).
|
-type(pbkdf2_mac_fun() :: md4 | md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512).
|
||||||
|
-type(pbkdf2_iterations() :: pos_integer()).
|
||||||
|
-type(pbkdf2_dk_length() :: pos_integer() | undefined).
|
||||||
|
|
||||||
|
-type(hash_params() ::
|
||||||
|
{bcrypt, salt()} |
|
||||||
|
{pbkdf2, pbkdf2_mac_fun(), salt(), pbkdf2_iterations(), pbkdf2_dk_length()} |
|
||||||
|
{hash_type_simple(), salt(), salt_position()}).
|
||||||
|
|
||||||
|
-export_type([pbkdf2_mac_fun/0]).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% APIs
|
%% APIs
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
-spec(check_pass(hash_params(), password_hash(), password()) -> boolean()).
|
-spec(check_pass(hash_params(), password_hash(), password()) -> boolean()).
|
||||||
|
check_pass({pbkdf2, MacFun, Salt, Iterations, DKLength}, PasswordHash, Password) ->
|
||||||
|
case pbkdf2(MacFun, Password, Salt, Iterations, DKLength) of
|
||||||
|
{ok, HashPasswd} ->
|
||||||
|
compare_secure(hex(HashPasswd), PasswordHash);
|
||||||
|
{error, _Reason}->
|
||||||
|
false
|
||||||
|
end;
|
||||||
check_pass({bcrypt, Salt}, PasswordHash, Password) ->
|
check_pass({bcrypt, Salt}, PasswordHash, Password) ->
|
||||||
case bcrypt:hashpw(Password, Salt) of
|
case bcrypt:hashpw(Password, Salt) of
|
||||||
{ok, HashPasswd} ->
|
{ok, HashPasswd} ->
|
||||||
|
@ -58,6 +74,13 @@ check_pass({_SimpleHash, _Salt, _SaltPosition} = HashParams, PasswordHash, Passw
|
||||||
compare_secure(Hash, PasswordHash).
|
compare_secure(Hash, PasswordHash).
|
||||||
|
|
||||||
-spec(hash(hash_params(), password()) -> password_hash()).
|
-spec(hash(hash_params(), password()) -> password_hash()).
|
||||||
|
hash({pbkdf2, MacFun, Salt, Iterations, DKLength}, Password) ->
|
||||||
|
case pbkdf2(MacFun, Password, Salt, Iterations, DKLength) of
|
||||||
|
{ok, HashPasswd} ->
|
||||||
|
hex(HashPasswd);
|
||||||
|
{error, Reason}->
|
||||||
|
error(Reason)
|
||||||
|
end;
|
||||||
hash({bcrypt, Salt}, Password) ->
|
hash({bcrypt, Salt}, Password) ->
|
||||||
case bcrypt:hashpw(Password, Salt) of
|
case bcrypt:hashpw(Password, Salt) of
|
||||||
{ok, HashPasswd} ->
|
{ok, HashPasswd} ->
|
||||||
|
@ -75,13 +98,13 @@ hash({SimpleHash, Salt, suffix}, Password) when is_binary(Password), is_binary(S
|
||||||
hash_data(plain, Data) when is_binary(Data) ->
|
hash_data(plain, Data) when is_binary(Data) ->
|
||||||
Data;
|
Data;
|
||||||
hash_data(md5, Data) when is_binary(Data) ->
|
hash_data(md5, Data) when is_binary(Data) ->
|
||||||
hexstring(crypto:hash(md5, Data));
|
hex(crypto:hash(md5, Data));
|
||||||
hash_data(sha, Data) when is_binary(Data) ->
|
hash_data(sha, Data) when is_binary(Data) ->
|
||||||
hexstring(crypto:hash(sha, Data));
|
hex(crypto:hash(sha, Data));
|
||||||
hash_data(sha256, Data) when is_binary(Data) ->
|
hash_data(sha256, Data) when is_binary(Data) ->
|
||||||
hexstring(crypto:hash(sha256, Data));
|
hex(crypto:hash(sha256, Data));
|
||||||
hash_data(sha512, Data) when is_binary(Data) ->
|
hash_data(sha512, Data) when is_binary(Data) ->
|
||||||
hexstring(crypto:hash(sha512, Data)).
|
hex(crypto:hash(sha512, Data)).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Internal functions
|
%% Internal functions
|
||||||
|
@ -103,11 +126,11 @@ compare_secure([], [], Result) ->
|
||||||
Result == 0.
|
Result == 0.
|
||||||
|
|
||||||
|
|
||||||
hexstring(<<X:128/big-unsigned-integer>>) ->
|
pbkdf2(MacFun, Password, Salt, Iterations, undefined) ->
|
||||||
iolist_to_binary(io_lib:format("~32.16.0b", [X]));
|
pbkdf2:pbkdf2(MacFun, Password, Salt, Iterations);
|
||||||
hexstring(<<X:160/big-unsigned-integer>>) ->
|
pbkdf2(MacFun, Password, Salt, Iterations, DKLength) ->
|
||||||
iolist_to_binary(io_lib:format("~40.16.0b", [X]));
|
pbkdf2:pbkdf2(MacFun, Password, Salt, Iterations, DKLength).
|
||||||
hexstring(<<X:256/big-unsigned-integer>>) ->
|
|
||||||
iolist_to_binary(io_lib:format("~64.16.0b", [X]));
|
|
||||||
hexstring(<<X:512/big-unsigned-integer>>) ->
|
hex(X) when is_binary(X) ->
|
||||||
iolist_to_binary(io_lib:format("~128.16.0b", [X])).
|
pbkdf2:to_hex(X).
|
||||||
|
|
|
@ -88,4 +88,16 @@ t_hash(_) ->
|
||||||
false = emqx_passwd:check_pass({bcrypt, <<>>}, <<>>, WrongPassword),
|
false = emqx_passwd:check_pass({bcrypt, <<>>}, <<>>, WrongPassword),
|
||||||
|
|
||||||
%% Invalid salt, bcrypt fails
|
%% Invalid salt, bcrypt fails
|
||||||
?assertException(error, _, emqx_passwd:hash({bcrypt, Salt}, Password)).
|
?assertException(error, _, emqx_passwd:hash({bcrypt, Salt}, Password)),
|
||||||
|
|
||||||
|
BadDKlen = 1 bsl 32,
|
||||||
|
Pbkdf2Salt = <<"ATHENA.MIT.EDUraeburn">>,
|
||||||
|
Pbkdf2 = <<"01dbee7f4a9e243e988b62c73cda935d"
|
||||||
|
"a05378b93244ec8f48a99e61ad799d86">>,
|
||||||
|
Pbkdf2 = emqx_passwd:hash({pbkdf2, sha, Pbkdf2Salt, 2, 32}, Password),
|
||||||
|
true = emqx_passwd:check_pass({pbkdf2, sha, Pbkdf2Salt, 2, 32}, Pbkdf2, Password),
|
||||||
|
false = emqx_passwd:check_pass({pbkdf2, sha, Pbkdf2Salt, 2, 32}, Pbkdf2, WrongPassword),
|
||||||
|
false = emqx_passwd:check_pass({pbkdf2, sha, Pbkdf2Salt, 2, BadDKlen}, Pbkdf2, Password),
|
||||||
|
|
||||||
|
%% Invalid derived_length, pbkdf2 fails
|
||||||
|
?assertException(error, _, emqx_passwd:hash({pbkdf2, sha, Pbkdf2Salt, 2, BadDKlen}, Password)).
|
||||||
|
|
|
@ -27,8 +27,12 @@
|
||||||
-type(bcrypt_algorithm() :: #{name := bcrypt}).
|
-type(bcrypt_algorithm() :: #{name := bcrypt}).
|
||||||
-type(bcrypt_algorithm_rw() :: #{name := bcrypt, salt_rounds := integer()}).
|
-type(bcrypt_algorithm_rw() :: #{name := bcrypt, salt_rounds := integer()}).
|
||||||
|
|
||||||
-type(algorithm() :: simple_algorithm() | bcrypt_algorithm()).
|
-type(pbkdf2_algorithm() :: #{name := pbkdf2,
|
||||||
-type(algorithm_rw() :: simple_algorithm() | bcrypt_algorithm_rw()).
|
mac_fun := emqx_passwd:pbkdf2_mac_fun(),
|
||||||
|
iterations := pos_integer()}).
|
||||||
|
|
||||||
|
-type(algorithm() :: simple_algorithm() | pbkdf2_algorithm() | bcrypt_algorithm()).
|
||||||
|
-type(algorithm_rw() :: simple_algorithm() | pbkdf2_algorithm() | bcrypt_algorithm_rw()).
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
%% Hocon Schema
|
%% Hocon Schema
|
||||||
|
@ -47,7 +51,7 @@
|
||||||
hash/2,
|
hash/2,
|
||||||
check_password/4]).
|
check_password/4]).
|
||||||
|
|
||||||
roots() -> [bcrypt, bcrypt_rw, other_algorithms].
|
roots() -> [pbkdf2, bcrypt, bcrypt_rw, other_algorithms].
|
||||||
|
|
||||||
fields(bcrypt_rw) ->
|
fields(bcrypt_rw) ->
|
||||||
fields(bcrypt) ++
|
fields(bcrypt) ++
|
||||||
|
@ -56,6 +60,12 @@ fields(bcrypt_rw) ->
|
||||||
fields(bcrypt) ->
|
fields(bcrypt) ->
|
||||||
[{name, {enum, [bcrypt]}}];
|
[{name, {enum, [bcrypt]}}];
|
||||||
|
|
||||||
|
fields(pbkdf2) ->
|
||||||
|
[{name, {enum, [pbkdf2]}},
|
||||||
|
{mac_fun, {enum, [md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512]}},
|
||||||
|
{iterations, integer()},
|
||||||
|
{dk_length, fun dk_length/1}];
|
||||||
|
|
||||||
fields(other_algorithms) ->
|
fields(other_algorithms) ->
|
||||||
[{name, {enum, [plain, md5, sha, sha256, sha512]}},
|
[{name, {enum, [plain, md5, sha, sha256, sha512]}},
|
||||||
{salt_position, fun salt_position/1}].
|
{salt_position, fun salt_position/1}].
|
||||||
|
@ -68,6 +78,11 @@ salt_rounds(type) -> integer();
|
||||||
salt_rounds(default) -> 10;
|
salt_rounds(default) -> 10;
|
||||||
salt_rounds(_) -> undefined.
|
salt_rounds(_) -> undefined.
|
||||||
|
|
||||||
|
dk_length(type) -> integer();
|
||||||
|
dk_length(nullable) -> true;
|
||||||
|
dk_length(default) -> undefined;
|
||||||
|
dk_length(_) -> undefined.
|
||||||
|
|
||||||
type_rw(type) ->
|
type_rw(type) ->
|
||||||
hoconsc:union(rw_refs());
|
hoconsc:union(rw_refs());
|
||||||
type_rw(default) -> #{<<"name">> => sha256, <<"salt_position">> => prefix};
|
type_rw(default) -> #{<<"name">> => sha256, <<"salt_position">> => prefix};
|
||||||
|
@ -108,7 +123,13 @@ hash(#{name := bcrypt, salt_rounds := _} = Algorithm, Password) ->
|
||||||
Hash = emqx_passwd:hash({bcrypt, Salt0}, Password),
|
Hash = emqx_passwd:hash({bcrypt, Salt0}, Password),
|
||||||
Salt = Hash,
|
Salt = Hash,
|
||||||
{Hash, Salt};
|
{Hash, Salt};
|
||||||
|
hash(#{name := pbkdf2,
|
||||||
|
mac_fun := MacFun,
|
||||||
|
iterations := Iterations} = Algorithm, Password) ->
|
||||||
|
Salt = gen_salt(Algorithm),
|
||||||
|
DKLength = maps:get(dk_length, Algorithm, undefined),
|
||||||
|
Hash = emqx_passwd:hash({pbkdf2, MacFun, Salt, Iterations, DKLength}, Password),
|
||||||
|
{Hash, Salt};
|
||||||
hash(#{name := Other, salt_position := SaltPosition} = Algorithm, Password) ->
|
hash(#{name := Other, salt_position := SaltPosition} = Algorithm, Password) ->
|
||||||
Salt = gen_salt(Algorithm),
|
Salt = gen_salt(Algorithm),
|
||||||
Hash = emqx_passwd:hash({Other, Salt, SaltPosition}, Password),
|
Hash = emqx_passwd:hash({Other, Salt, SaltPosition}, Password),
|
||||||
|
@ -122,7 +143,12 @@ hash(#{name := Other, salt_position := SaltPosition} = Algorithm, Password) ->
|
||||||
emqx_passwd:password()) -> boolean()).
|
emqx_passwd:password()) -> boolean()).
|
||||||
check_password(#{name := bcrypt}, _Salt, PasswordHash, Password) ->
|
check_password(#{name := bcrypt}, _Salt, PasswordHash, Password) ->
|
||||||
emqx_passwd:check_pass({bcrypt, PasswordHash}, PasswordHash, Password);
|
emqx_passwd:check_pass({bcrypt, PasswordHash}, PasswordHash, Password);
|
||||||
|
check_password(#{name := pbkdf2,
|
||||||
|
mac_fun := MacFun,
|
||||||
|
iterations := Iterations} = Algorithm,
|
||||||
|
Salt, PasswordHash, Password) ->
|
||||||
|
DKLength = maps:get(dk_length, Algorithm, undefined),
|
||||||
|
emqx_passwd:check_pass({pbkdf2, MacFun, Salt, Iterations, DKLength}, PasswordHash, Password);
|
||||||
check_password(#{name := Other, salt_position := SaltPosition}, Salt, PasswordHash, Password) ->
|
check_password(#{name := Other, salt_position := SaltPosition}, Salt, PasswordHash, Password) ->
|
||||||
emqx_passwd:check_pass({Other, Salt, SaltPosition}, PasswordHash, Password).
|
emqx_passwd:check_pass({Other, Salt, SaltPosition}, PasswordHash, Password).
|
||||||
|
|
||||||
|
@ -132,8 +158,10 @@ check_password(#{name := Other, salt_position := SaltPosition}, Salt, PasswordHa
|
||||||
|
|
||||||
rw_refs() ->
|
rw_refs() ->
|
||||||
[hoconsc:ref(?MODULE, bcrypt_rw),
|
[hoconsc:ref(?MODULE, bcrypt_rw),
|
||||||
|
hoconsc:ref(?MODULE, pbkdf2),
|
||||||
hoconsc:ref(?MODULE, other_algorithms)].
|
hoconsc:ref(?MODULE, other_algorithms)].
|
||||||
|
|
||||||
ro_refs() ->
|
ro_refs() ->
|
||||||
[hoconsc:ref(?MODULE, bcrypt),
|
[hoconsc:ref(?MODULE, bcrypt),
|
||||||
|
hoconsc:ref(?MODULE, pbkdf2),
|
||||||
hoconsc:ref(?MODULE, other_algorithms)].
|
hoconsc:ref(?MODULE, other_algorithms)].
|
||||||
|
|
|
@ -116,9 +116,8 @@ hash_examples() ->
|
||||||
salt_position => prefix}
|
salt_position => prefix}
|
||||||
},
|
},
|
||||||
#{
|
#{
|
||||||
password_hash => iolist_to_binary(
|
password_hash => <<"a1509ab67bfacbad020927b5ac9d91e9100a82e33a0ebb01459367ce921c0aa8"
|
||||||
[<<"a1509ab67bfacbad020927b5ac9d91e9100a82e33a0ebb01459367ce921c0aa8">>,
|
"157aa5652f94bc84fa3babc08283e44887d61c48bcf8ad7bcb3259ee7d0eafcd">>,
|
||||||
<<"157aa5652f94bc84fa3babc08283e44887d61c48bcf8ad7bcb3259ee7d0eafcd">>]),
|
|
||||||
salt => <<"salt">>,
|
salt => <<"salt">>,
|
||||||
password => <<"sha512">>,
|
password => <<"sha512">>,
|
||||||
password_hash_algorithm => #{name => sha512,
|
password_hash_algorithm => #{name => sha512,
|
||||||
|
@ -131,5 +130,26 @@ hash_examples() ->
|
||||||
|
|
||||||
password_hash_algorithm => #{name => bcrypt,
|
password_hash_algorithm => #{name => bcrypt,
|
||||||
salt_rounds => 10}
|
salt_rounds => 10}
|
||||||
|
},
|
||||||
|
|
||||||
|
#{
|
||||||
|
password_hash => <<"01dbee7f4a9e243e988b62c73cda935d"
|
||||||
|
"a05378b93244ec8f48a99e61ad799d86">>,
|
||||||
|
salt => <<"ATHENA.MIT.EDUraeburn">>,
|
||||||
|
password => <<"password">>,
|
||||||
|
|
||||||
|
password_hash_algorithm => #{name => pbkdf2,
|
||||||
|
iterations => 2,
|
||||||
|
dk_length => 32,
|
||||||
|
mac_fun => sha}
|
||||||
|
},
|
||||||
|
#{
|
||||||
|
password_hash => <<"01dbee7f4a9e243e988b62c73cda935da05378b9">>,
|
||||||
|
salt => <<"ATHENA.MIT.EDUraeburn">>,
|
||||||
|
password => <<"password">>,
|
||||||
|
|
||||||
|
password_hash_algorithm => #{name => pbkdf2,
|
||||||
|
iterations => 2,
|
||||||
|
mac_fun => sha}
|
||||||
}
|
}
|
||||||
].
|
].
|
||||||
|
|
|
@ -222,28 +222,28 @@ raw_redis_auth_config() ->
|
||||||
|
|
||||||
user_seeds() ->
|
user_seeds() ->
|
||||||
[#{data => #{
|
[#{data => #{
|
||||||
password_hash => "plainsalt",
|
password_hash => <<"plainsalt">>,
|
||||||
salt => "salt",
|
salt => <<"salt">>,
|
||||||
is_superuser => "1"
|
is_superuser => <<"1">>
|
||||||
},
|
},
|
||||||
credentials => #{
|
credentials => #{
|
||||||
username => <<"plain">>,
|
username => <<"plain">>,
|
||||||
password => <<"plain">>},
|
password => <<"plain">>},
|
||||||
key => "mqtt_user:plain",
|
key => <<"mqtt_user:plain">>,
|
||||||
config_params => #{},
|
config_params => #{},
|
||||||
result => {ok,#{is_superuser => true}}
|
result => {ok,#{is_superuser => true}}
|
||||||
},
|
},
|
||||||
|
|
||||||
#{data => #{
|
#{data => #{
|
||||||
password_hash => "9b4d0c43d206d48279e69b9ad7132e22",
|
password_hash => <<"9b4d0c43d206d48279e69b9ad7132e22">>,
|
||||||
salt => "salt",
|
salt => <<"salt">>,
|
||||||
is_superuser => "0"
|
is_superuser => <<"0">>
|
||||||
},
|
},
|
||||||
credentials => #{
|
credentials => #{
|
||||||
username => <<"md5">>,
|
username => <<"md5">>,
|
||||||
password => <<"md5">>
|
password => <<"md5">>
|
||||||
},
|
},
|
||||||
key => "mqtt_user:md5",
|
key => <<"mqtt_user:md5">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{name => <<"md5">>,
|
password_hash_algorithm => #{name => <<"md5">>,
|
||||||
salt_position => <<"suffix">>}
|
salt_position => <<"suffix">>}
|
||||||
|
@ -252,15 +252,15 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
|
|
||||||
#{data => #{
|
#{data => #{
|
||||||
password_hash => "ac63a624e7074776d677dd61a003b8c803eb11db004d0ec6ae032a5d7c9c5caf",
|
password_hash => <<"ac63a624e7074776d677dd61a003b8c803eb11db004d0ec6ae032a5d7c9c5caf">>,
|
||||||
salt => "salt",
|
salt => <<"salt">>,
|
||||||
is_superuser => "1"
|
is_superuser => <<"1">>
|
||||||
},
|
},
|
||||||
credentials => #{
|
credentials => #{
|
||||||
clientid => <<"sha256">>,
|
clientid => <<"sha256">>,
|
||||||
password => <<"sha256">>
|
password => <<"sha256">>
|
||||||
},
|
},
|
||||||
key => "mqtt_user:sha256",
|
key => <<"mqtt_user:sha256">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
cmd => <<"HMGET mqtt_user:${clientid} password_hash salt is_superuser">>,
|
cmd => <<"HMGET mqtt_user:${clientid} password_hash salt is_superuser">>,
|
||||||
password_hash_algorithm => #{name => <<"sha256">>,
|
password_hash_algorithm => #{name => <<"sha256">>,
|
||||||
|
@ -270,31 +270,48 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
|
|
||||||
#{data => #{
|
#{data => #{
|
||||||
password_hash => "$2b$12$wtY3h20mUjjmeaClpqZVveDWGlHzCGsvuThMlneGHA7wVeFYyns2u",
|
password_hash => <<"$2b$12$wtY3h20mUjjmeaClpqZVveDWGlHzCGsvuThMlneGHA7wVeFYyns2u">>,
|
||||||
salt => "$2b$12$wtY3h20mUjjmeaClpqZVve",
|
salt => <<"$2b$12$wtY3h20mUjjmeaClpqZVve">>,
|
||||||
is_superuser => "0"
|
is_superuser => <<"0">>
|
||||||
},
|
},
|
||||||
credentials => #{
|
credentials => #{
|
||||||
username => <<"bcrypt">>,
|
username => <<"bcrypt">>,
|
||||||
password => <<"bcrypt">>
|
password => <<"bcrypt">>
|
||||||
},
|
},
|
||||||
key => "mqtt_user:bcrypt",
|
key => <<"mqtt_user:bcrypt">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
password_hash_algorithm => #{name => <<"bcrypt">>}
|
||||||
},
|
},
|
||||||
result => {ok,#{is_superuser => false}}
|
result => {ok,#{is_superuser => false}}
|
||||||
},
|
},
|
||||||
|
|
||||||
#{data => #{
|
#{data => #{
|
||||||
password_hash => "$2b$12$wtY3h20mUjjmeaClpqZVveDWGlHzCGsvuThMlneGHA7wVeFYyns2u",
|
password_hash => <<"01dbee7f4a9e243e988b62c73cda935da05378b9">>,
|
||||||
salt => "$2b$12$wtY3h20mUjjmeaClpqZVve",
|
salt => <<"ATHENA.MIT.EDUraeburn">>,
|
||||||
is_superuser => "0"
|
is_superuser => <<"0">>
|
||||||
|
},
|
||||||
|
credentials => #{
|
||||||
|
username => <<"pbkdf2">>,
|
||||||
|
password => <<"password">>
|
||||||
|
},
|
||||||
|
key => <<"mqtt_user:pbkdf2">>,
|
||||||
|
config_params => #{
|
||||||
|
password_hash_algorithm => #{name => <<"pbkdf2">>,
|
||||||
|
iterations => 2,
|
||||||
|
mac_fun => sha
|
||||||
|
}
|
||||||
|
},
|
||||||
|
result => {ok,#{is_superuser => false}}
|
||||||
|
},
|
||||||
|
#{data => #{
|
||||||
|
password_hash => <<"$2b$12$wtY3h20mUjjmeaClpqZVveDWGlHzCGsvuThMlneGHA7wVeFYyns2u">>,
|
||||||
|
salt => <<"$2b$12$wtY3h20mUjjmeaClpqZVve">>,
|
||||||
|
is_superuser => <<"0">>
|
||||||
},
|
},
|
||||||
credentials => #{
|
credentials => #{
|
||||||
username => <<"bcrypt0">>,
|
username => <<"bcrypt0">>,
|
||||||
password => <<"bcrypt">>
|
password => <<"bcrypt">>
|
||||||
},
|
},
|
||||||
key => "mqtt_user:bcrypt0",
|
key => <<"mqtt_user:bcrypt0">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
% clientid variable & username credentials
|
% clientid variable & username credentials
|
||||||
cmd => <<"HMGET mqtt_client:${clientid} password_hash salt is_superuser">>,
|
cmd => <<"HMGET mqtt_client:${clientid} password_hash salt is_superuser">>,
|
||||||
|
@ -304,15 +321,15 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
|
|
||||||
#{data => #{
|
#{data => #{
|
||||||
password_hash => "$2b$12$wtY3h20mUjjmeaClpqZVveDWGlHzCGsvuThMlneGHA7wVeFYyns2u",
|
password_hash => <<"$2b$12$wtY3h20mUjjmeaClpqZVveDWGlHzCGsvuThMlneGHA7wVeFYyns2u">>,
|
||||||
salt => "$2b$12$wtY3h20mUjjmeaClpqZVve",
|
salt => <<"$2b$12$wtY3h20mUjjmeaClpqZVve">>,
|
||||||
is_superuser => "0"
|
is_superuser => <<"0">>
|
||||||
},
|
},
|
||||||
credentials => #{
|
credentials => #{
|
||||||
username => <<"bcrypt1">>,
|
username => <<"bcrypt1">>,
|
||||||
password => <<"bcrypt">>
|
password => <<"bcrypt">>
|
||||||
},
|
},
|
||||||
key => "mqtt_user:bcrypt1",
|
key => <<"mqtt_user:bcrypt1">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
% Bad key in cmd
|
% Bad key in cmd
|
||||||
cmd => <<"HMGET badkey:${username} password_hash salt is_superuser">>,
|
cmd => <<"HMGET badkey:${username} password_hash salt is_superuser">>,
|
||||||
|
@ -322,16 +339,16 @@ user_seeds() ->
|
||||||
},
|
},
|
||||||
|
|
||||||
#{data => #{
|
#{data => #{
|
||||||
password_hash => "$2b$12$wtY3h20mUjjmeaClpqZVveDWGlHzCGsvuThMlneGHA7wVeFYyns2u",
|
password_hash => <<"$2b$12$wtY3h20mUjjmeaClpqZVveDWGlHzCGsvuThMlneGHA7wVeFYyns2u">>,
|
||||||
salt => "$2b$12$wtY3h20mUjjmeaClpqZVve",
|
salt => <<"$2b$12$wtY3h20mUjjmeaClpqZVve">>,
|
||||||
is_superuser => "0"
|
is_superuser => <<"0">>
|
||||||
},
|
},
|
||||||
credentials => #{
|
credentials => #{
|
||||||
username => <<"bcrypt2">>,
|
username => <<"bcrypt2">>,
|
||||||
% Wrong password
|
% Wrong password
|
||||||
password => <<"wrongpass">>
|
password => <<"wrongpass">>
|
||||||
},
|
},
|
||||||
key => "mqtt_user:bcrypt2",
|
key => <<"mqtt_user:bcrypt2">>,
|
||||||
config_params => #{
|
config_params => #{
|
||||||
cmd => <<"HMGET mqtt_user:${username} password_hash salt is_superuser">>,
|
cmd => <<"HMGET mqtt_user:${username} password_hash salt is_superuser">>,
|
||||||
password_hash_algorithm => #{name => <<"bcrypt">>}
|
password_hash_algorithm => #{name => <<"bcrypt">>}
|
||||||
|
|
Loading…
Reference in New Issue