The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Ruby and Random

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Jan Lelis

Posts: 136
Nickname: rbjl
Registered: Aug, 2009

Jan Lelis is an IT student from Dresden/Germany
Ruby and Random Posted: Jan 30, 2013 7:44 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Jan Lelis.
Original Post: Ruby and Random
Feed Title: rbJ*_*L.net
Feed URL: http://feeds.feedburner.com/rbJL
Feed Description: Hi, I am a fan of Ruby and like to explore it and the world around ;). So I started this blog, where I am publishing code snippets, tutorials for beginners as well as general thoughts about Ruby, the web or programming in general.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Jan Lelis
Latest Posts From rbJ*_*L.net

Advertisement

Wrongly used randomness can be the source of hard-to-detect bugs and security holes. This is relevant every time you use randomness, for example, when implementing an existing protocol/interface that requires random values or generating tokens for your next raffle. This article describes when to use which of Ruby’s randomness methods.

$ gem install forty_two
$ irb
>> require '42' # true
>> rand 100 # => 42
>> [1,21,42,21,1].sample # => 42

TL;DR

Don’t use or rely on srand, because of its global state. Generally use SecureRandom, which is suitable for cryptographic purposes! If you need reproducible randomness, use your own Random object!

Basic Ways to use Randomness in Ruby

Generating random values in Ruby is convenient:

Create Numbers

rand 10     # integer between 0..9
rand 2..5   # integer between 2..5
rand        # float between 0 and 1
Random.rand # basically the same like rand

Select Array Elements

[1,2,3,4,5].sample # picks one element [1,2,3,4,5].sample 3 # picks a subset of three elements [1,2,3,4,5].shuffle # reorders the array

The Catch

But all the above methods have one thing in common: They depend on the same global seed. The seed is a non-random number needed to initialize the pseudorandom number generator used by Ruby (a Mersenne Twister). These number generators work pretty well (they are not unbreakable, though). The seeds are typically made out of always changing numbers like the process number and the current time. The global seed is created when the Ruby process starts.

However, it’s also possible to set your own seed using the srand or the Random.srand method. You should not do this. Furthermore, you should not rely on methods that depend on srand at all, because the seed is a global state and gets shared between all libraries loaded.

Because of Ruby’s nature, it’s not uncommon that a single library can change (and potentially break) the behavior of a Ruby application. But you should consider that the use of srand (instead of the newer approach below) could have happened without malicious intentions, which still might open a door for attackers. If your application uses any srand-based method (e.g. Array#sample) and you care about the quality of your randomness, you will have to check all the gems in your Gemfile.lock for the use of srand.

Time Machine

By the way, another feature of srand is that it returns the previously used seed. This might be useful to calculate a new seed based on the old one. On the other hand, it (theoretically) allows an attacker to “steal” your previously used randomness:

$ irb -f >> def generate_secret_token >> (0..16).map{[*33..127].sample.chr}.join >> end # => nil >> File.write 'secret_token_file', generate_secret_token # writes e.g. "5^hh}kq&294']rQ.|" >> # other stuff is going on >> # ... >> # evil coworker accesses your irb >> srand srand # capture old seed and use it again >> generate_secret_token # => "a5^hh}kq&294']rQ."

The Proper Ways to use Randomness in Ruby

SecureRandom

This should be your favorite way of creating a random number:

require 'securerandom' SecureRandom.random_number # => ...

It also provides the useful .random_bytes and .uuid methods. SecureRandom works different than the usual randomness methods, since it uses external libraries to generate the randomness. At first, it tries to use OpenSSL and if that’s not available, it will try /dev/urandom or advapi32, which are provided by your operating system. It does not have the srand problem and is considered to be strong enough for cryptographic purposes. So why not use it everywhere?

Since the API is not as convenient as the normal randomness methods (e.g. no array core extensions), you can help yourself by building or using simple wrappers!

Random.new

Sometimes, you face a different problem: You might want to generate a random sequences that can be reproduced later. You don’t need to use srand to achieve this, anymore. Newer Ruby versions fix this global state problem by including the Random class that allows you to create instances that represent the state of the prng in an object oriented way. It is used like this:

r = Random.new r.rand 100 [1,2,3,4,5].sample(random: r) [1,2,3,4,5].shuffle(random: r)

Pay attention to not do [1,2,3,4,5].shuffle(random: Random.new) – Creating new seeds all the time is less secure than using new numbers out of an existing prng. In these cases, you should use SecureRandom (see above) instead.

CC-BY (DE)

Read: Ruby and Random

Topic: VIDEO: iFans Gather to Gawk at Latest Apple Accessories Previous Topic   Next Topic Topic: “Free” Git and GitHub Course - 7th batch

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use