aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
authorGuilherme Andrade <[email protected]>2017-03-18 17:27:35 +0000
committerGuilherme Andrade <[email protected]>2017-03-18 18:06:36 +0000
commit77039e648c8a62bfc4f0242531d5fd4874b29aad (patch)
tree3ed70566ce80b0feac00a0b36c2cb070c4e5a1b6 /lib/stdlib
parente50f63fbb2c974b4b8ad50095ca0b16a846fc161 (diff)
downloadotp-77039e648c8a62bfc4f0242531d5fd4874b29aad.tar.gz
otp-77039e648c8a62bfc4f0242531d5fd4874b29aad.tar.bz2
otp-77039e648c8a62bfc4f0242531d5fd4874b29aad.zip
Support cryptographically strong rand plugin
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/doc/src/rand.xml24
-rw-r--r--lib/stdlib/src/rand.erl36
2 files changed, 36 insertions, 24 deletions
diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml
index 8745e16908..e7a5fb7fab 100644
--- a/lib/stdlib/doc/src/rand.xml
+++ b/lib/stdlib/doc/src/rand.xml
@@ -120,20 +120,28 @@ S0 = rand:seed_s(exsplus),
{SND0, S2} = rand:normal_s(S1),</pre>
<note>
- <p>This random number generator is not cryptographically
- strong. If a strong cryptographic random number generator is
- needed, use one of functions in the
- <seealso marker="crypto:crypto"><c>crypto</c></seealso>
- module, for example, <seealso marker="crypto:crypto">
- <c>crypto:strong_rand_bytes/1</c></seealso>.</p>
+ <p>The builtin random number generator algorithms are not
+ cryptographically strong. If a cryptographically strong
+ random number generator is needed, use something like
+ <seealso marker="crypto:crypto#rand_seed-0"><c>crypto:rand_seed/0</c></seealso>.
+ </p>
</note>
</description>
<datatypes>
<datatype>
+ <name name="builtin_alg"/>
+ </datatype>
+ <datatype>
<name name="alg"/>
</datatype>
<datatype>
+ <name name="alg_handler"/>
+ </datatype>
+ <datatype>
+ <name name="alg_seed"/>
+ </datatype>
+ <datatype>
<name name="state"/>
<desc><p>Algorithm-dependent state.</p></desc>
</datatype>
@@ -216,7 +224,7 @@ S0 = rand:seed_s(exsplus),
<desc>
<marker id="seed-1"/>
<p>Seeds random number generation with the specifed algorithm and
- time-dependent data if <anno>AlgOrExpState</anno> is an algorithm.</p>
+ time-dependent data if <anno>AlgOrStateOrExpState</anno> is an algorithm.</p>
<p>Otherwise recreates the exported seed in the process dictionary,
and returns the state. See also
<seealso marker="#export_seed-0"><c>export_seed/0</c></seealso>.</p>
@@ -237,7 +245,7 @@ S0 = rand:seed_s(exsplus),
<fsummary>Seed random number generator.</fsummary>
<desc>
<p>Seeds random number generation with the specifed algorithm and
- time-dependent data if <anno>AlgOrExpState</anno> is an algorithm.</p>
+ time-dependent data if <anno>AlgOrStateOrExpState</anno> is an algorithm.</p>
<p>Otherwise recreates the exported seed and returns the state.
See also <seealso marker="#export_seed-0">
<c>export_seed/0</c></seealso>.</p>
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index 1f457b9e0e..3ff7aaf15f 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -45,20 +45,22 @@
%% =====================================================================
%% This depends on the algorithm handler function
--type alg_seed() :: exs64_state() | exsplus_state() | exs1024_state().
+-type alg_seed() :: exs64_state() | exsplus_state() | exs1024_state() | term().
+
%% This is the algorithm handler function within this module
-type alg_handler() :: #{type := alg(),
- max := integer(),
- next := fun(),
- uniform := fun(),
- uniform_n := fun(),
- jump := fun()}.
-
-%% Internal state
--opaque state() :: {alg_handler(), alg_seed()}.
--type alg() :: exs64 | exsplus | exs1024.
--opaque export_state() :: {alg(), alg_seed()}.
--export_type([alg/0, state/0, export_state/0]).
+ max := integer() | infinity,
+ next := fun((alg_seed()) -> {uint64(), alg_seed()}),
+ uniform := fun((state()) -> {float(), state()}),
+ uniform_n := fun((pos_integer(), state()) -> {pos_integer(), state()}),
+ jump := fun((state()) -> state())}.
+
+%% Algorithm state
+-type state() :: {alg_handler(), alg_seed()}.
+-type builtin_alg() :: exs64 | exsplus | exs1024.
+-type alg() :: builtin_alg() | term().
+-type export_state() :: {alg(), alg_seed()}.
+-export_type([builtin_alg/0, alg/0, alg_handler/0, alg_seed/0, state/0, export_state/0]).
%% =====================================================================
%% API
@@ -81,15 +83,17 @@ export_seed_s({#{type:=Alg}, Seed}) -> {Alg, Seed}.
%% seed({Alg,Seed}) setup RNG with a previously exported seed
%% and return the NEW state
--spec seed(AlgOrExpState::alg() | export_state()) -> state().
+-spec seed(AlgOrStateOrExpState::builtin_alg() | state() | export_state()) -> state().
seed(Alg) ->
seed_put(seed_s(Alg)).
--spec seed_s(AlgOrExpState::alg() | export_state()) -> state().
+-spec seed_s(AlgOrStateOrExpState::builtin_alg() | state() | export_state()) -> state().
seed_s(Alg) when is_atom(Alg) ->
seed_s(Alg, {erlang:phash2([{node(),self()}]),
erlang:system_time(),
erlang:unique_integer()});
+seed_s({AlgHandler, _Seed} = State) when is_map(AlgHandler) ->
+ State;
seed_s({Alg0, Seed}) ->
{Alg,_SeedFun} = mk_alg(Alg0),
{Alg, Seed}.
@@ -97,11 +101,11 @@ seed_s({Alg0, Seed}) ->
%% seed/2: seeds RNG with the algorithm and given values
%% and returns the NEW state.
--spec seed(Alg :: alg(), {integer(), integer(), integer()}) -> state().
+-spec seed(Alg :: builtin_alg(), {integer(), integer(), integer()}) -> state().
seed(Alg0, S0) ->
seed_put(seed_s(Alg0, S0)).
--spec seed_s(Alg :: alg(), {integer(), integer(), integer()}) -> state().
+-spec seed_s(Alg :: builtin_alg(), {integer(), integer(), integer()}) -> state().
seed_s(Alg0, S0 = {_, _, _}) ->
{Alg, Seed} = mk_alg(Alg0),
AS = Seed(S0),