[Feature Suggestion] Wrap :rand.seed with Elixir

270 views
Skip to first unread message

Dorian Karter

unread,
Sep 21, 2016, 2:47:38 PM9/21/16
to elixir-lang-core
I recently wrote a blog post about my explorations into random number generation from Elixir and Erlang. You can find it here:

This led me to question why `:rand.seed` is not exposed from Elixir without hitting Erlang directly. I think every time we send a user to learn something about the intricacies of Erlang we are introducing a mental overhead.

I would be happy to submit a pull request that will attempt to wrap `:rand.seed` but figured I'd check with the core team first. My questions:

1. Why is `:rand.seed` not exposed from Elixir? is that by design?
2. If it should be exposed by Elixir where do you imagine it living? `Kernel.seed`? or should we create a new `Random` module.
3. Would it make sense to provide a method that will just securly seed rand like so
<< i1 :: unsigned-integer-32, i2 :: unsigned-integer-32, i3 :: unsigned-integer-32>> = :crypto.strong_rand_bytes(12)
:rand.seed(:exsplus, {i1, i2, i3})
4. Anything else I should consider if I submit a pull request other than obvious testing and documentation


Thanks so much for your attention and feedback!

Dorian

José Valim

unread,
Sep 21, 2016, 3:01:56 PM9/21/16
to elixir-l...@googlegroups.com
We typically avoid only wrapping Erlang functions because in the long term we will just end-up duplicating all the efforts already done in the Erlang community. For example, even for a simple case such as Kernel.seed, we need to document the tuple format, the meaning of exsplus, etc. And unless we wrap all the functionality in rand, at some point you will still need to use rand directly.

So I would like to propose other initiatives:

* We should continue to focus on better documenting those entry points, which we already do in places such as the Getting Started guides. In fact, your article is a great exploration of the rand module and, if you send a pull request to the guides linking to your article in the rand section, we would love to merge it!

* Send a pull request to Erlang/OTP that improves their documentation. For example, including an example of using the crypto module for a cryptographically secure example would probably be very welcome.

* Send a pull request to Erlang/OTP that adds the functionality you would like to see Elixir wrapping.

If you or anyone else need help in contributing to Erlang, please ping me any time, either on IRC or by e-mail and I would love to provide guidance. Improving Erlang is our responsibility too! :D


José Valim
Skype: jv.ptec
Founder and Director of R&D

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/577910ae-2a52-49f4-9e77-670639106a3c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

OvermindDL1

unread,
Sep 21, 2016, 3:12:47 PM9/21/16
to elixir-lang-core
Google Now just popped up your article for me to read while I was at lunch a half-hour ago, I did not think that was so fast.  o.O

But yes, PR for docs, but no need to wrap existing things if there is no functionality changes.

eksperimental

unread,
Sep 21, 2016, 3:39:13 PM9/21/16
to elixir-l...@googlegroups.com
there is a single particularity in this proposal, and it could solve something I have been bitten
by some time ago when improving *.random functions in Elixir core.
I couldn't figure out why all tests related to random functions were not working, and that's becuase
when creating Integer.random (a function that never made it to core) I used :random.seed instead
of :rand.seed.
Believe me it took me a while and a lot of head scratches to figure out what was going on.

Having two modules so similar it's a source of confusion, and being this function a critical
function when generating randon values could be a source of security bugs: so I don't think it
would be a bad idea to have a Kernel.seed funcion


On Wed, 21 Sep 2016 21:01:23 +0200
José Valim <jose....@plataformatec.com.br> wrote:

> We typically avoid only wrapping Erlang functions because in the long term
> we will just end-up duplicating all the efforts already done in the Erlang
> community. For example, even for a simple case such as Kernel.seed, we need
> to document the tuple format, the meaning of exsplus, etc. And unless we
> wrap all the functionality in rand, at some point you will still need to
> use rand directly.
>
> So I would like to propose other initiatives:
>
> * We should continue to focus on better documenting those entry points,
> which we already do in places such as the Getting Started guides
> <http://elixir-lang.org/getting-started/erlang-libraries.html>. In fact,
> your article is a great exploration of the rand module and, if you send a
> pull request to the guides linking to your article in the rand section, we
> would love to merge it!
>
> * Send a pull request to Erlang/OTP that improves their documentation. For
> example, including an example of using the crypto module for a
> cryptographically secure example would probably be very welcome.
>
> * Send a pull request to Erlang/OTP that adds the functionality you would
> like to see Elixir wrapping.
>
> If you or anyone else need help in contributing to Erlang, please ping me
> any time, either on IRC or by e-mail and I would love to provide guidance.
> Improving Erlang is our responsibility too! :D
>
>
> *José Valim*
> > email to elixir-lang-co...@googlegroups.com.
> > To view this discussion on the web visit https://groups.google.com/d/
> > msgid/elixir-lang-core/577910ae-2a52-49f4-9e77-
> > 670639106a3c%40googlegroups.com
> > <https://groups.google.com/d/msgid/elixir-lang-core/577910ae-2a52-49f4-9e77-670639106a3c%40googlegroups.com?utm_medium=email&utm_source=footer>
> > .

Dorian Karter

unread,
Sep 21, 2016, 10:39:49 PM9/21/16
to elixir-lang-core, eksper...@autistici.org
Thanks @josevalim, I'll definetly send a PR to the Elixir guide as you suggested. I had no idea this page existed.

I tend to agree with @eksperimental.

The other point I have (oops had) in favor of implementing Kernel.seed is that @josevalim recently implemented Kernel.rand.

Regardless, I think there should be a more idiomatic way to seed rand that does not involve sending the user down the path I've gone down in my blog post.

<< i1 :: unsigned-integer-32, i2 :: unsigned-integer-32, i3 :: unsigned-integer-32>> = :crypto.strong_rand_bytes(12)
:rand.seed(:exsplus, {i1, i2, i3})

This code above just doesn't seem like the spirit of Elixir which focuses on developer productivity and happiness by simplicity.
It sends people to learn the intricacies of erlang for something that should be simple and is simple in a lot of other languages.

I think we can take a hint from Ruby and Java and their SecureRandom libraries:


Particularly I like Ruby's SecureRandom because it provides helpful methods such as `urlsafe_base64`, `uuid`, `random_bytes` and `hex`. I remember this being the first thing I looked for when I was building my first Elixir application (url shortener) and was surprised at how many hoops I had to jump through as a beginner to get something so simple done.

Paul Schoenfelder

unread,
Sep 21, 2016, 10:59:28 PM9/21/16
to elixir-l...@googlegroups.com, eksper...@autistici.org
This code above just doesn't seem like the spirit of Elixir which focuses on developer productivity and happiness by simplicity.
It sends people to learn the intricacies of erlang for something that should be simple and is simple in a lot of other languages.

The first thing that pops out to me about that code is that it's odd that you are providing a constant seed, the typical use of the :rand API for me is usually just a call like so `:rand.seed(:exsplus)` (or whatever algorithm you choose). Basically, your example is complicated because you are doing something extra to seed the random number generator in a particular way.

I have to add my +1 to disliking wrapping Erlang standard library functions when there is no clear benefit to doing so. Adding `Kernel.rand` or whatever would still have to expose more or less the same complexity, so there is little benefit to wrapping it. Erlang has a rich standard library, and if Elixir tried to wrap all of it to avoid making people dip into the Erlang APIs, it would be a huge effort, and a wasted one for the most part. I don't think one has to learn the intricacies of Erlang to use the vast majority of the APIs, they are generally well documented, and if you know Elixir, you can use the Erlang APIs with little understanding of Erlang itself - in my opinion, if you know Elixir, there isn't much of a leap to knowing Erlang anyway, other than learning the syntax. The biggest pain point of course is that the Elixir and Erlang documentation is separated, and one can't access the Erlang docs in the shell, etc - but I don't think the solution to that is wrapping everything.

Just my two cents,

Paul


To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/5607dd04-eaf2-499e-8182-3789a44ebded%40googlegroups.com.

Dorian Karter

unread,
Sep 22, 2016, 10:40:11 AM9/22/16
to elixir-lang-core, eksper...@autistici.org
Thanks for contributing your thoughts @paul! :)

I don't think I'm doing anything weird with this code per se. The official documentation for rand says this:

This random number generator is not cryptographically strong. If a strong cryptographic random number generator is needed, use one of functions in the crypto module, for example, crypto:strong_rand_bytes/1.

And perhaps by extension we should include this type of message in `Enum.random` which is, as far as I know, the only place using `:rand`.

I could not find any additional official documentation on the matter and that's the only way I found to seed rand with `crypto:strong_rand_bytes/1` as suggested.

Paul Schoenfelder

unread,
Sep 22, 2016, 11:41:48 AM9/22/16
to elixir-l...@googlegroups.com, eksper...@autistici.org
It's much less common that one requires cryptographically strong random numbers than not, which is of course part of the reason why :rand does not just generate cryptographically strong random numbers for you by default. For a great many things, one doesn't need that guarantee. If you do need that guarantee, for instance you are doing something crypto-related, then you probably both want the fine control over the parameters, and in my opinion, should be forced to understand them, because if you don't, you shouldn't be doing crypto.

That said, I didn't mean to imply that your code was bad or anything, just that it was a variant which I don't think is useful for illustrating the point (though maybe your post required cryptographically strong random numbers, I don't recall). I do think there are some Erlang APIs that would benefit from wrapping, just for better errors alone (:crypto I'm looking at you), but generally I think it's a bad idea.

Paul


To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/d7a71dc1-0fce-47e7-836f-291e7c1ca415%40googlegroups.com.

Levi Aul

unread,
Dec 18, 2016, 5:39:06 PM12/18/16
to elixir-lang-core, eksper...@autistici.org
Note that that warning in the documentation for :rand is trying to say that the PRNG algorithms :rand supports are not cryptographically strong. If you need strong randomness, you have to not only use a high-entropy seed, but also a cryptographically-secure PRNG (CSPRNG), which none of the algorithms in :rand are.

Seeding the :rand PRNG using :crypto is not sufficient to give you a CSPRNG (i.e. a PRNG which can produce an indefinite stream of bytes which cannot be used to recover the original key/seed.) If you need strong randomness, the docs meant to say that you should just use :crypto directly as your CSPRNG, because that's what it is: crypto:strong_rand_bytes/1 calls OpenSSL's RAND_bytes, which is a CSPRNG algorithm seeded using system entropy.
Reply all
Reply to author
Forward
0 new messages