@@ -31,15 +31,20 @@ defmodule Plug.Crypto.KeyGenerator do
3131
3232 """
3333 def generate ( secret , salt , opts \\ [ ] ) do
34+ force_legacy_mode = Keyword . get ( opts , :force_legacy_mode , false )
3435 iterations = Keyword . get ( opts , :iterations , 1000 )
3536 length = Keyword . get ( opts , :length , 32 )
3637 digest = Keyword . get ( opts , :digest , :sha256 )
3738 cache = Keyword . get ( opts , :cache )
38- generate ( secret , salt , iterations , length , digest , cache )
39+ generate ( secret , salt , iterations , length , digest , force_legacy_mode , cache )
3940 end
4041
4142 @ doc false
4243 def generate ( secret , salt , iterations , length , digest , cache ) do
44+ generate ( secret , salt , iterations , length , digest , false , cache )
45+ end
46+
47+ defp generate ( secret , salt , iterations , length , digest , force_legacy_mode , cache ) do
4348 cond do
4449 not is_integer ( iterations ) or iterations < 1 ->
4550 raise ArgumentError , "iterations must be an integer >= 1"
@@ -49,13 +54,23 @@ defmodule Plug.Crypto.KeyGenerator do
4954
5055 true ->
5156 with_cache ( cache , { secret , salt , iterations , length , digest } , fn ->
52- generate ( hmac_fun ( digest , secret ) , salt , iterations , length , 1 , [ ] , 0 )
57+ pbkdf2_hmac ( digest , secret , salt , iterations , length , force_legacy_mode )
5358 end )
5459 end
5560 rescue
5661 e -> reraise e , Plug.Crypto . prune_args_from_stacktrace ( __STACKTRACE__ )
5762 end
5863
64+ defp pbkdf2_hmac ( digest , secret , salt , iterations , length , force_legacy_mode ) do
65+ # TODO: remove when we require OTP 24.2
66+ if not force_legacy_mode and Code . ensure_loaded? ( :crypto ) and
67+ function_exported? ( :crypto , :pbkdf2_hmac , 5 ) do
68+ :crypto . pbkdf2_hmac ( digest , secret , salt , iterations , length )
69+ else
70+ legacy_pbkdf2_hmac ( hmac_fun ( digest , secret ) , salt , iterations , length , 1 , [ ] , 0 )
71+ end
72+ end
73+
5974 defp with_cache ( nil , _key , fun ) , do: fun . ( )
6075
6176 defp with_cache ( ets , key , fun ) do
@@ -70,19 +85,19 @@ defmodule Plug.Crypto.KeyGenerator do
7085 end
7186 end
7287
73- defp generate ( _fun , _salt , _iterations , max_length , _block_index , acc , length )
88+ defp legacy_pbkdf2_hmac ( _fun , _salt , _iterations , max_length , _block_index , acc , length )
7489 when length >= max_length do
7590 acc
7691 |> IO . iodata_to_binary ( )
7792 |> binary_part ( 0 , max_length )
7893 end
7994
80- defp generate ( fun , salt , iterations , max_length , block_index , acc , length ) do
95+ defp legacy_pbkdf2_hmac ( fun , salt , iterations , max_length , block_index , acc , length ) do
8196 initial = fun . ( << salt :: binary , block_index :: integer - size ( 32 ) >> )
8297 block = iterate ( fun , iterations - 1 , initial , initial )
8398 length = byte_size ( block ) + length
8499
85- generate ( fun , salt , iterations , max_length , block_index + 1 , [ acc | block ] , length )
100+ legacy_pbkdf2_hmac ( fun , salt , iterations , max_length , block_index + 1 , [ acc | block ] , length )
86101 end
87102
88103 defp iterate ( _fun , 0 , _prev , acc ) , do: acc
0 commit comments