@@ -31,20 +31,15 @@ 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 )
3534 iterations = Keyword . get ( opts , :iterations , 1000 )
3635 length = Keyword . get ( opts , :length , 32 )
3736 digest = Keyword . get ( opts , :digest , :sha256 )
3837 cache = Keyword . get ( opts , :cache )
39- generate ( secret , salt , iterations , length , digest , force_legacy_mode , cache )
38+ generate ( secret , salt , iterations , length , digest , cache )
4039 end
4140
4241 @ doc false
4342 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
4843 cond do
4944 not is_integer ( iterations ) or iterations < 1 ->
5045 raise ArgumentError , "iterations must be an integer >= 1"
@@ -54,23 +49,13 @@ defmodule Plug.Crypto.KeyGenerator do
5449
5550 true ->
5651 with_cache ( cache , { secret , salt , iterations , length , digest } , fn ->
57- pbkdf2_hmac ( digest , secret , salt , iterations , length , force_legacy_mode )
52+ pbkdf2_hmac ( digest , secret , salt , iterations , length )
5853 end )
5954 end
6055 rescue
6156 e -> reraise e , Plug.Crypto . prune_args_from_stacktrace ( __STACKTRACE__ )
6257 end
6358
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-
7459 defp with_cache ( nil , _key , fun ) , do: fun . ( )
7560
7661 defp with_cache ( ets , key , fun ) do
@@ -85,27 +70,46 @@ defmodule Plug.Crypto.KeyGenerator do
8570 end
8671 end
8772
88- defp legacy_pbkdf2_hmac ( _fun , _salt , _iterations , max_length , _block_index , acc , length )
89- when length >= max_length do
90- acc
91- |> IO . iodata_to_binary ( )
92- |> binary_part ( 0 , max_length )
93- end
73+ # TODO: remove when we require OTP 24.2
74+ if Code . ensure_loaded? ( :crypto ) and function_exported? ( :crypto , :pbkdf2_hmac , 5 ) do
75+ defp pbkdf2_hmac ( digest , secret , salt , iterations , length ) do
76+ :crypto . pbkdf2_hmac ( digest , secret , salt , iterations , length )
77+ end
78+ else
79+ defp pbkdf2_hmac ( digest , secret , salt , iterations , length ) do
80+ legacy_pbkdf2_hmac ( hmac_fun ( digest , secret ) , salt , iterations , length , 1 , [ ] , 0 )
81+ end
9482
95- defp legacy_pbkdf2_hmac ( fun , salt , iterations , max_length , block_index , acc , length ) do
96- initial = fun . ( << salt :: binary , block_index :: integer - size ( 32 ) >> )
97- block = iterate ( fun , iterations - 1 , initial , initial )
98- length = byte_size ( block ) + length
83+ defp legacy_pbkdf2_hmac ( _fun , _salt , _iterations , max_length , _block_index , acc , length )
84+ when length >= max_length do
85+ acc
86+ |> IO . iodata_to_binary ( )
87+ |> binary_part ( 0 , max_length )
88+ end
9989
100- legacy_pbkdf2_hmac ( fun , salt , iterations , max_length , block_index + 1 , [ acc | block ] , length )
101- end
90+ defp legacy_pbkdf2_hmac ( fun , salt , iterations , max_length , block_index , acc , length ) do
91+ initial = fun . ( << salt :: binary , block_index :: integer - size ( 32 ) >> )
92+ block = iterate ( fun , iterations - 1 , initial , initial )
93+ length = byte_size ( block ) + length
94+
95+ legacy_pbkdf2_hmac (
96+ fun ,
97+ salt ,
98+ iterations ,
99+ max_length ,
100+ block_index + 1 ,
101+ [ acc | block ] ,
102+ length
103+ )
104+ end
102105
103- defp iterate ( _fun , 0 , _prev , acc ) , do: acc
106+ defp iterate ( _fun , 0 , _prev , acc ) , do: acc
104107
105- defp iterate ( fun , iteration , prev , acc ) do
106- next = fun . ( prev )
107- iterate ( fun , iteration - 1 , next , :crypto . exor ( next , acc ) )
108- end
108+ defp iterate ( fun , iteration , prev , acc ) do
109+ next = fun . ( prev )
110+ iterate ( fun , iteration - 1 , next , :crypto . exor ( next , acc ) )
111+ end
109112
110- defp hmac_fun ( digest , key ) , do: & :crypto . mac ( :hmac , digest , key , & 1 )
113+ defp hmac_fun ( digest , key ) , do: & :crypto . mac ( :hmac , digest , key , & 1 )
114+ end
111115end
0 commit comments