From d07008a0562d1f83dcab144fdec9fd920deb2b96 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sun, 12 Mar 2017 17:20:00 +0000 Subject: Support generation of strong random numbers --- lib/crypto/src/crypto.erl | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 631af62615..4b386924cb 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -30,6 +30,8 @@ -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([strong_rand_uniform/0]). +-export([strong_rand_uniform/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]). @@ -283,9 +285,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 strong_rand_uniform() -> float(). +-spec strong_rand_uniform(pos_integer()) -> pos_integer(). -spec rand_uniform(crypto_integer(), crypto_integer()) -> crypto_integer(). @@ -297,6 +301,38 @@ strong_rand_bytes(Bytes) -> strong_rand_bytes_nif(_Bytes) -> ?nif_stub. +strong_rand_uniform() -> + Sign = 0, % positive + Exponent = 1023, % on the interval [1.0, 2.0[ + Fraction = strong_rand_uniform(1, 1 bsl 52), % the whole interval above (except 1.0) + <> = <>, + Value - 1.0. + +strong_rand_uniform(N) when is_integer(N), N >= 1 -> + 1 + strong_rand_uniform(0, N). + +strong_rand_uniform(From, To) when is_binary(From), is_binary(To) -> + case strong_rand_uniform_nif(From,To) of + false -> + erlang:error(low_entropy); + <> when MSB > 127 -> + <<(Len + 1):32/integer, 0, MSB, Rest/binary>>; + Whatever -> + Whatever + end; +strong_rand_uniform(From, To) when is_integer(From), is_integer(To), From < To -> + BinFrom = mpint(From), + BinTo = mpint(To), + case strong_rand_uniform(BinFrom, BinTo) of + Result when is_binary(Result) -> + erlint(Result); + Other -> + Other + end. + +strong_rand_uniform_nif(_From, _To) -> ?nif_stub. + + rand_uniform(From,To) when is_binary(From), is_binary(To) -> case rand_uniform_nif(From,To) of <> when MSB > 127 -> @@ -325,6 +361,7 @@ rand_uniform_pos(_,_) -> rand_uniform_nif(_From,_To) -> ?nif_stub. + -spec rand_seed(binary()) -> ok. rand_seed(Seed) -> rand_seed_nif(Seed). -- cgit v1.2.3 From e50f63fbb2c974b4b8ad50095ca0b16a846fc161 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sat, 18 Mar 2017 12:57:19 +0000 Subject: Restyle crypto strong numeric generators for usage in rand --- lib/crypto/src/crypto.erl | 52 ++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 30 deletions(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 4b386924cb..2c3208a3d5 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -30,8 +30,8 @@ -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([strong_rand_uniform/0]). --export([strong_rand_uniform/1]). +-export([strong_rand_range/1]). +-export([strong_rand_float/0]). -export([rand_uniform/2]). -export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]). -export([next_iv/2, next_iv/3]). @@ -288,8 +288,8 @@ stream_decrypt(State, Data0) -> %% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib %% -spec strong_rand_bytes(non_neg_integer()) -> binary(). --spec strong_rand_uniform() -> float(). --spec strong_rand_uniform(pos_integer()) -> pos_integer(). +-spec strong_rand_range(pos_integer() | binary()) -> binary(). +-spec strong_rand_float() -> float(). -spec rand_uniform(crypto_integer(), crypto_integer()) -> crypto_integer(). @@ -301,36 +301,28 @@ strong_rand_bytes(Bytes) -> strong_rand_bytes_nif(_Bytes) -> ?nif_stub. -strong_rand_uniform() -> - Sign = 0, % positive - Exponent = 1023, % on the interval [1.0, 2.0[ - Fraction = strong_rand_uniform(1, 1 bsl 52), % the whole interval above (except 1.0) - <> = <>, - Value - 1.0. - -strong_rand_uniform(N) when is_integer(N), N >= 1 -> - 1 + strong_rand_uniform(0, N). - -strong_rand_uniform(From, To) when is_binary(From), is_binary(To) -> - case strong_rand_uniform_nif(From,To) of +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); - <> when MSB > 127 -> - <<(Len + 1):32/integer, 0, MSB, Rest/binary>>; - Whatever -> - Whatever - end; -strong_rand_uniform(From, To) when is_integer(From), is_integer(To), From < To -> - BinFrom = mpint(From), - BinTo = mpint(To), - case strong_rand_uniform(BinFrom, BinTo) of - Result when is_binary(Result) -> - erlint(Result); - Other -> - Other + <> -> + BinResult end. -strong_rand_uniform_nif(_From, _To) -> ?nif_stub. +strong_rand_range_nif(_BinRange) -> ?nif_stub. + + +strong_rand_float() -> + % This could be optimized by having its own NIF + Sign = 0, % positive + Exponent = 1023, % on the interval [1.0, 2.0[ + BinFraction = strong_rand_range(1 bsl 52), % the whole interval above + Fraction = bin_to_int(BinFraction), + <> = <>, + Value - 1.0. rand_uniform(From,To) when is_binary(From), is_binary(To) -> -- cgit v1.2.3 From 77039e648c8a62bfc4f0242531d5fd4874b29aad Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sat, 18 Mar 2017 17:27:35 +0000 Subject: Support cryptographically strong rand plugin --- lib/crypto/src/crypto.erl | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 2c3208a3d5..4ae7a9cdd6 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -32,6 +32,8 @@ -export([exor/2, strong_rand_bytes/1, mod_pow/3]). -export([strong_rand_range/1]). -export([strong_rand_float/0]). +-export([rand_seed/0]). +-export([rand_seed_s/0]). -export([rand_uniform/2]). -export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]). -export([next_iv/2, next_iv/3]). @@ -290,6 +292,8 @@ stream_decrypt(State, Data0) -> -spec strong_rand_bytes(non_neg_integer()) -> binary(). -spec strong_rand_range(pos_integer() | binary()) -> binary(). -spec strong_rand_float() -> float(). +-spec rand_seed() -> rand:state(). +-spec rand_seed_s() -> rand:state(). -spec rand_uniform(crypto_integer(), crypto_integer()) -> crypto_integer(). @@ -311,7 +315,6 @@ strong_rand_range(BinRange) when is_binary(BinRange) -> <> -> BinResult end. - strong_rand_range_nif(_BinRange) -> ?nif_stub. @@ -325,6 +328,31 @@ strong_rand_float() -> Value - 1.0. +rand_seed() -> + rand:seed(rand_seed_s()). + +rand_seed_s() -> + {#{ type => crypto, + max => infinity, + next => fun rand_plugin_next/1, + uniform => fun rand_plugin_uniform/1, + uniform_n => fun rand_plugin_uniform/2, + jump => fun 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. + + rand_uniform(From,To) when is_binary(From), is_binary(To) -> case rand_uniform_nif(From,To) of <> when MSB > 127 -> -- cgit v1.2.3 From 5eae0dacf40ec60b09f0fdf761987e39320c4db0 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sat, 18 Mar 2017 17:32:23 +0000 Subject: No longer expose strong_rand_(range|float) --- lib/crypto/src/crypto.erl | 48 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 4ae7a9cdd6..ad9245f8f2 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -30,8 +30,6 @@ -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([strong_rand_range/1]). --export([strong_rand_float/0]). -export([rand_seed/0]). -export([rand_seed_s/0]). -export([rand_uniform/2]). @@ -290,8 +288,6 @@ stream_decrypt(State, Data0) -> %% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib %% -spec strong_rand_bytes(non_neg_integer()) -> binary(). --spec strong_rand_range(pos_integer() | binary()) -> binary(). --spec strong_rand_float() -> float(). -spec rand_seed() -> rand:state(). -spec rand_seed_s() -> rand:state(). -spec rand_uniform(crypto_integer(), crypto_integer()) -> @@ -305,29 +301,6 @@ strong_rand_bytes(Bytes) -> strong_rand_bytes_nif(_Bytes) -> ?nif_stub. -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 - end. -strong_rand_range_nif(_BinRange) -> ?nif_stub. - - -strong_rand_float() -> - % This could be optimized by having its own NIF - Sign = 0, % positive - Exponent = 1023, % on the interval [1.0, 2.0[ - BinFraction = strong_rand_range(1 bsl 52), % the whole interval above - Fraction = bin_to_int(BinFraction), - <> = <>, - Value - 1.0. - - rand_seed() -> rand:seed(rand_seed_s()). @@ -352,6 +325,27 @@ rand_plugin_uniform(Max, 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 + end. +strong_rand_range_nif(_BinRange) -> ?nif_stub. + +strong_rand_float() -> + % This could be optimized by having its own NIF + Sign = 0, % positive + Exponent = 1023, % on the interval [1.0, 2.0[ + BinFraction = strong_rand_range(1 bsl 52), % the whole interval above + Fraction = bin_to_int(BinFraction), + <> = <>, + Value - 1.0. + rand_uniform(From,To) when is_binary(From), is_binary(To) -> case rand_uniform_nif(From,To) of -- cgit v1.2.3 From ec1e5bc7ff8101b7db4fa5d67bbbed652a9238c8 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Wed, 22 Mar 2017 21:56:28 +0000 Subject: Allow for crypto upgrades when using rand plugin --- lib/crypto/src/crypto.erl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index ad9245f8f2..777b5cd1c6 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -32,6 +32,10 @@ -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]). @@ -305,12 +309,12 @@ rand_seed() -> rand:seed(rand_seed_s()). rand_seed_s() -> - {#{ type => crypto, + {#{ type => ?MODULE, max => infinity, - next => fun rand_plugin_next/1, - uniform => fun rand_plugin_uniform/1, - uniform_n => fun rand_plugin_uniform/2, - jump => fun rand_plugin_jump/1}, + 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) -> -- cgit v1.2.3 From c84e541b78cb9ee63a02db2240903ddd6131793a Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Wed, 22 Mar 2017 22:15:15 +0000 Subject: Attempt faster approach to strong random floats --- lib/crypto/src/crypto.erl | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 777b5cd1c6..d8bc13b537 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -49,6 +49,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(). @@ -342,14 +345,8 @@ strong_rand_range(BinRange) when is_binary(BinRange) -> strong_rand_range_nif(_BinRange) -> ?nif_stub. strong_rand_float() -> - % This could be optimized by having its own NIF - Sign = 0, % positive - Exponent = 1023, % on the interval [1.0, 2.0[ - BinFraction = strong_rand_range(1 bsl 52), % the whole interval above - Fraction = bin_to_int(BinFraction), - <> = <>, - Value - 1.0. - + 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 -- cgit v1.2.3