aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto/src/crypto.erl
diff options
context:
space:
mode:
authorRaimo Niskanen <[email protected]>2017-04-04 10:53:00 +0200
committerRaimo Niskanen <[email protected]>2017-04-04 10:53:00 +0200
commit39c12050644c27883d679f11bb83142e6c1824ad (patch)
tree64b13a9a9c878d3ac2803d375287f70faf08b6ab /lib/crypto/src/crypto.erl
parenteeb8957e485c27ab70f4ba056cfebfff412ec055 (diff)
parente1a74e3077ca870520a748f29dd7c4b9115ce090 (diff)
downloadotp-39c12050644c27883d679f11bb83142e6c1824ad.tar.gz
otp-39c12050644c27883d679f11bb83142e6c1824ad.tar.bz2
otp-39c12050644c27883d679f11bb83142e6c1824ad.zip
Merge branch 'g-andrade/strong-random-numbers/PR-1367/OTP-14317'
* g-andrade/strong-random-numbers/PR-1367/OTP-14317: Clean up documentation and test cases Attempt faster approach to strong random floats Allow for crypto upgrades when using rand plugin fixup! Support cryptographically strong rand plugin fixup! Support cryptographically strong rand plugin fixup! Support cryptographically strong rand plugin fixup! Support cryptographically strong rand plugin No longer expose strong_rand_(range|float) Support cryptographically strong rand plugin Restyle crypto strong numeric generators for usage in rand Support generation of strong random numbers
Diffstat (limited to 'lib/crypto/src/crypto.erl')
-rw-r--r--lib/crypto/src/crypto.erl54
1 files changed, 53 insertions, 1 deletions
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index d322765dff..1287ec6176 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -30,6 +30,12 @@
-export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([cmac/3, cmac/4]).
-export([exor/2, strong_rand_bytes/1, mod_pow/3]).
+-export([rand_seed/0]).
+-export([rand_seed_s/0]).
+-export([rand_plugin_next/1]).
+-export([rand_plugin_uniform/1]).
+-export([rand_plugin_uniform/2]).
+-export([rand_plugin_jump/1]).
-export([rand_uniform/2]).
-export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]).
-export([next_iv/2, next_iv/3]).
@@ -45,6 +51,9 @@
%% This should correspond to the similar macro in crypto.c
-define(MAX_BYTES_TO_NIF, 20000). %% Current value is: erlang:system_info(context_reductions) * 10
+%% Used by strong_rand_float/0
+-define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53)
+
%%-type ecdsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'.
-type crypto_integer() :: binary() | integer().
%%-type ec_named_curve() :: atom().
@@ -286,9 +295,11 @@ stream_decrypt(State, Data0) ->
stream_crypt(fun do_stream_decrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
%%
-%% RAND - pseudo random numbers using RN_ functions in crypto lib
+%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
%%
-spec strong_rand_bytes(non_neg_integer()) -> binary().
+-spec rand_seed() -> rand:state().
+-spec rand_seed_s() -> rand:state().
-spec rand_uniform(crypto_integer(), crypto_integer()) ->
crypto_integer().
@@ -300,6 +311,46 @@ strong_rand_bytes(Bytes) ->
strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+rand_seed() ->
+ rand:seed(rand_seed_s()).
+
+rand_seed_s() ->
+ {#{ type => ?MODULE,
+ max => infinity,
+ next => fun ?MODULE:rand_plugin_next/1,
+ uniform => fun ?MODULE:rand_plugin_uniform/1,
+ uniform_n => fun ?MODULE:rand_plugin_uniform/2,
+ jump => fun ?MODULE:rand_plugin_jump/1},
+ no_seed}.
+
+rand_plugin_next(Seed) ->
+ {bytes_to_integer(strong_rand_range(1 bsl 64)), Seed}.
+
+rand_plugin_uniform(State) ->
+ {strong_rand_float(), State}.
+
+rand_plugin_uniform(Max, State) ->
+ {bytes_to_integer(strong_rand_range(Max)) + 1, State}.
+
+rand_plugin_jump(State) ->
+ State.
+
+strong_rand_range(Range) when is_integer(Range), Range > 0 ->
+ BinRange = int_to_bin(Range),
+ strong_rand_range(BinRange);
+strong_rand_range(BinRange) when is_binary(BinRange) ->
+ case strong_rand_range_nif(BinRange) of
+ false ->
+ erlang:error(low_entropy);
+ <<BinResult/binary>> ->
+ BinResult
+ end.
+strong_rand_range_nif(_BinRange) -> ?nif_stub.
+
+strong_rand_float() ->
+ WholeRange = strong_rand_range(1 bsl 53),
+ ?HALF_DBL_EPSILON * bytes_to_integer(WholeRange).
+
rand_uniform(From,To) when is_binary(From), is_binary(To) ->
case rand_uniform_nif(From,To) of
<<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
@@ -328,6 +379,7 @@ rand_uniform_pos(_,_) ->
rand_uniform_nif(_From,_To) -> ?nif_stub.
+
-spec rand_seed(binary()) -> ok.
rand_seed(Seed) ->
rand_seed_nif(Seed).