random_sources 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE.txt +20 -0
- data/README.rdoc +45 -0
- data/lib/providers/hot_bits.rb +49 -0
- data/lib/providers/random_org.rb +168 -0
- data/lib/random_sources.rb +22 -0
- metadata +81 -0
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Juanjo Bazán
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
= Random Sources
|
2
|
+
|
3
|
+
Random Sources is a Ruby gem that provides genuine random numbers, generated by processes fundamentally governed by inherent uncertainty instead of some pseudo-random number algorithm. It uses http services from different online providers.
|
4
|
+
|
5
|
+
== Getting started
|
6
|
+
|
7
|
+
Install the gem:
|
8
|
+
$ [sudo] gem install random_sources
|
9
|
+
|
10
|
+
Then depending on your project you may:
|
11
|
+
|
12
|
+
Require the gem (if a ruby project):
|
13
|
+
require 'random_sources'
|
14
|
+
or add it to your Gemfile (if you're on Rails):
|
15
|
+
gem 'random_sources', :git => 'git://github.com/xuanxu/random_sources.git'
|
16
|
+
|
17
|
+
|
18
|
+
== Usage
|
19
|
+
|
20
|
+
Your entry point is the RandomSources module. With it you can get a list of supported providers and instantiate any of them:
|
21
|
+
|
22
|
+
RandomSources.list #=> "HotBits, RandomOrg"
|
23
|
+
|
24
|
+
RandomSources.generator 'RandomOrg' #=> <RandomSources::RandomOrg>
|
25
|
+
|
26
|
+
Once you have your generator you can ask for the random bytes:
|
27
|
+
|
28
|
+
generator = RandomSources.generator 'RandomOrg'
|
29
|
+
|
30
|
+
# five integers between 1 and 100:
|
31
|
+
generator.integers(:num => 5, :min => 1, :max => 100)
|
32
|
+
# => [45, 61, 22, 96, 70]
|
33
|
+
|
34
|
+
# two strings of 10 unique characters including digits and uppercase letters:
|
35
|
+
generator.strings(:num => 2, :unique => 'on', :digits => 'on', :upperalpha => 'on', :loweralpha =>'off')
|
36
|
+
# => ["6ESR61Y1", "K7520E6L"]
|
37
|
+
|
38
|
+
You can get integers, strings, sequences, bytes, etc... For a list of all the options of any supported source, check the doc in {the wiki}[http://wiki.github.com/xuanxu/random_sources/]
|
39
|
+
|
40
|
+
== Credits
|
41
|
+
|
42
|
+
Author:: Juanjo Bazán
|
43
|
+
Copyright:: Copyright (c) 2010 Juanjo Bazán
|
44
|
+
License:: Released under the MIT license.
|
45
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'rexml/xpath'
|
3
|
+
|
4
|
+
module RandomSources
|
5
|
+
|
6
|
+
# The HotBits class uses the http service provided by http://www.fourmilab.ch/hotbits/
|
7
|
+
#
|
8
|
+
# The service offers genuine random numbers generated by timing successive pairs of radioactive decays detected by a Geiger-Muller tube.
|
9
|
+
#
|
10
|
+
# The service assigns a quota of available random bits per IP.
|
11
|
+
#
|
12
|
+
# Use the service properly and check the website if you need more details about the terms of usage.
|
13
|
+
class HotBits
|
14
|
+
attr_reader :website
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@website = "http://www.fourmilab.ch/hotbits/"
|
18
|
+
end
|
19
|
+
|
20
|
+
# Short info about the online source.
|
21
|
+
def info
|
22
|
+
"HotBits is an Internet resource that brings genuine random numbers, generated by a process fundamentally governed by the inherent uncertainty in the quantum mechanical laws of nature:
|
23
|
+
HotBits are generated by timing successive pairs of radioactive decays detected by a Geiger-Muller tube interfaced to a computer. The website is mantained by John Walker."
|
24
|
+
end
|
25
|
+
|
26
|
+
# Random bytes generator.
|
27
|
+
#
|
28
|
+
# It returns an Array of integers with values between 0 and 255
|
29
|
+
#
|
30
|
+
# It receives the number of random bytes to generate (max 2048, default 10)
|
31
|
+
def bytes(num=10)
|
32
|
+
num = [[2048, num.to_i].min , 0].max
|
33
|
+
numbers = []
|
34
|
+
|
35
|
+
response = REXML::Document.new( open("https://www.fourmilab.ch/cgi-bin/Hotbits?fmt=xml&nbytes=#{num}"))
|
36
|
+
status = REXML::XPath.first( response, "//status")
|
37
|
+
case status.attributes['result'].to_i
|
38
|
+
when 200
|
39
|
+
data = REXML::XPath.first( response, "//random-data" ).text.split
|
40
|
+
data.each{|byte| numbers << byte.hex}
|
41
|
+
when 503
|
42
|
+
raise StandardError.new "#{status.text}"
|
43
|
+
end
|
44
|
+
|
45
|
+
numbers
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
module RandomSources
|
2
|
+
|
3
|
+
# The RandomOrg class uses the http service provided by http://www.random.org.
|
4
|
+
#
|
5
|
+
# RANDOM.ORG offers numbers with randomness coming from atmospheric noise.
|
6
|
+
#
|
7
|
+
# The service assigns a daily quota of available random bits for IP.
|
8
|
+
#
|
9
|
+
# Use the service properly and check the website if you need more details about the terms of usage.
|
10
|
+
class RandomOrg
|
11
|
+
attr_reader :website
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@website = "http://www.random.org/"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Short info about the online source.
|
18
|
+
def info
|
19
|
+
"RANDOM.ORG offers numbers with randomness coming from atmospheric noise.
|
20
|
+
The service was built and is being operated by Mads Haahr of the School of Computer Science and Statistics at Trinity College, Dublin in Ireland."
|
21
|
+
end
|
22
|
+
|
23
|
+
# Random Integers Generator.
|
24
|
+
#
|
25
|
+
# Configuration options:
|
26
|
+
# * <tt>:num</tt> - The number of integers requested. Posibles values: [1,1e4]. Default: 10
|
27
|
+
# * <tt>:min</tt> - The smallest value allowed for each integer. Posibles values: [-1e9,1e9]. Default: 1
|
28
|
+
# * <tt>:max</tt> - The smallest value allowed for each integer. Posibles values: [-1e9,1e9]. Default: 100
|
29
|
+
# * <tt>:base</tt> - The base that will be used to print the numbers. Posibles values: 2, 8, 10, 16 (binary, octal, decimal or hexadecimal). Default: 10
|
30
|
+
#
|
31
|
+
# It returns an Array of integers with the size indicated by <tt>:num</tt>
|
32
|
+
#
|
33
|
+
# integers(:num => 15, :max => 2, :min => 200, base => 8) #=> array of 15 base 8 numbers between 2 and 200
|
34
|
+
# integers(:num => 4, :max => 33) #=> [31, 25, 28, 6]
|
35
|
+
#
|
36
|
+
def integers(options = {})
|
37
|
+
url_params = { :max => clean(options[:max]) || 100,
|
38
|
+
:min => clean(options[:min]) || 1,
|
39
|
+
:num => clean(options[:num]) || 10,
|
40
|
+
:base => clean(options[:base]) || 10,
|
41
|
+
:rnd => 'new',
|
42
|
+
:format => 'plain',
|
43
|
+
:col => 1
|
44
|
+
}
|
45
|
+
|
46
|
+
numbers=[]
|
47
|
+
|
48
|
+
check_for_http_errors{
|
49
|
+
response=open("#{@website}integers/?max=#{url_params[:max]}&min=#{url_params[:min]}&base=#{url_params[:base]}&col=#{url_params[:col]}&rnd=#{url_params[:rnd]}&format=#{url_params[:format]}&num=#{url_params[:num]}")
|
50
|
+
response.each_line{|line| numbers << line.to_i}
|
51
|
+
}
|
52
|
+
|
53
|
+
numbers
|
54
|
+
end
|
55
|
+
|
56
|
+
# The Sequence Generator
|
57
|
+
#
|
58
|
+
# It will randomize a given interval of integers, i.e., arrange them in random order.
|
59
|
+
#
|
60
|
+
# It needs two params:
|
61
|
+
# * <tt>min</tt> - The lower bound of the interval (inclusive). Posibles values: [-1e9,1e9]
|
62
|
+
# * <tt>max</tt> - The upper bound of the interval (inclusive). Posibles values: [-1e9,1e9]
|
63
|
+
#
|
64
|
+
# The length of the sequence (the largest minus the smallest value plus 1) can be no greater than 10,000.
|
65
|
+
#
|
66
|
+
# It returns an Array of all the integers of the given interval arranged randomly
|
67
|
+
#
|
68
|
+
# sequence(2, 15) #=> [13, 2, 10, 4, 9, 15 ,12, 3, 5, 7, 6, 14, 8, 11]
|
69
|
+
def sequence(min, max)
|
70
|
+
url_params = { :max => clean(max) || 10,
|
71
|
+
:min => clean(min) || 1,
|
72
|
+
:rnd => 'new',
|
73
|
+
:format => 'plain',
|
74
|
+
:col => 1
|
75
|
+
}
|
76
|
+
sequence_numbers=[]
|
77
|
+
|
78
|
+
check_for_http_errors{
|
79
|
+
response=open("#{@website}sequences/?max=#{url_params[:max]}&min=#{url_params[:min]}&col=#{url_params[:col]}&rnd=#{url_params[:rnd]}&format=#{url_params[:format]}")
|
80
|
+
response.each_line{|line| sequence_numbers << line.to_i}
|
81
|
+
}
|
82
|
+
|
83
|
+
sequence_numbers
|
84
|
+
end
|
85
|
+
|
86
|
+
# Random Strings Generator.
|
87
|
+
#
|
88
|
+
# It will generate truly random strings of various length and character compositions.
|
89
|
+
#
|
90
|
+
# Configuration options:
|
91
|
+
# * <tt>:num</tt> - The number of strings requested. Posibles values: [1,1e4]. Default: 10
|
92
|
+
# * <tt>:len</tt> - The length of the strings. All the strings produced will have the same length. Posibles values: [1,20]. Default: 8
|
93
|
+
# * <tt>:digits</tt> - Determines whether digits (0-9) are allowed to occur in the strings. Posibles values: ['on', 'off']. Default: on
|
94
|
+
# * <tt>:upperalpha</tt> - Determines whether uppercase alphabetic characters (A-Z) are allowed to occur in the strings. Posibles values: ['on', 'off']. Default: on
|
95
|
+
# * <tt>:loweralpha</tt> - Determines lowercase alphabetic characters (a-z) are allowed to occur in the strings. Posibles values: ['on', 'off']. Default: on
|
96
|
+
# * <tt>:unique</tt> - Determines whether the strings picked should be unique (as a series of raffle tickets drawn from a hat) or not (as a series of die rolls).
|
97
|
+
# If unique is set to on, then there is the additional constraint that the number of strings requested (num) must be less than or equal to the number of strings
|
98
|
+
# that exist with the selected length and characters. Posibles values: ['on', 'off']. Default: on
|
99
|
+
#
|
100
|
+
# It returns an Array of Strings of the size indicated with <tt>:num</tt>
|
101
|
+
#
|
102
|
+
# strings(:num => 15, :len => 2, :digits => 'off', upperalpha => 'off') #=> array of 15 strings of size 2 composed by diggits and lowercase letters with no repetition.
|
103
|
+
# strings(:num => 4, :len => 10) #=> ["iloqQz2nGa", "D2mgs12kD6", "yMe1eDsinJ", "ZQPaEol6xr"]
|
104
|
+
def strings(options = {})
|
105
|
+
url_params = { :num => clean(options[:num]) || 10,
|
106
|
+
:len => clean(options[:len]) || 8,
|
107
|
+
:digits => check_on_off(options[:digits]) || 'on',
|
108
|
+
:unique => check_on_off(options[:unique]) || 'on',
|
109
|
+
:upperalpha => check_on_off(options[:upperalpha]) || 'on',
|
110
|
+
:loweralpha => check_on_off(options[:loweralpha]) || 'on',
|
111
|
+
:rnd => 'new',
|
112
|
+
:format => 'plain'
|
113
|
+
}
|
114
|
+
|
115
|
+
strings=[]
|
116
|
+
|
117
|
+
check_for_http_errors{
|
118
|
+
response=open("#{@website}strings/?num=#{url_params[:num]}&len=#{url_params[:len]}&digits=#{url_params[:digits]}&unique=#{url_params[:unique]}&upperalpha=#{url_params[:upperalpha]}&loweralpha=#{url_params[:loweralpha]}&rnd=#{url_params[:rnd]}&format=#{url_params[:format]}")
|
119
|
+
response.each_line{|line| strings << line.strip}
|
120
|
+
}
|
121
|
+
|
122
|
+
strings
|
123
|
+
end
|
124
|
+
|
125
|
+
# The Quota Checker.
|
126
|
+
#
|
127
|
+
# This method allows you to examine your quota at any point in time.
|
128
|
+
# The quota system of random.org works on the basis of IP addresses.
|
129
|
+
# Each IP address has a base quota of 1,000,000 daily bits.
|
130
|
+
#
|
131
|
+
# If your quota is greater than or equal to zero, the next request for random numbers will be fully completed, even if the request will result in the quota becoming negative.
|
132
|
+
# Hence, no partial responses will be sent as a result of exhausting ehe quota; the server will either return a full response or an error response.
|
133
|
+
#
|
134
|
+
# Every day, shortly after midnight UTC, all quotas with less than 1,000,000 bits receive a free top-up of 200,000 bits.
|
135
|
+
# If the server has spare capacity, you may get an additional free top-up earlier, but you should not count on it.
|
136
|
+
# If you need extra bits urgently (or require many bits) you can purchase once-off top-ups from the Quota Page: http://www.random.org/quota.
|
137
|
+
#
|
138
|
+
# The method returns the number of bits left of your quota as an integer.
|
139
|
+
def quota
|
140
|
+
url_params = { :format => 'plain' }
|
141
|
+
check_for_http_errors{
|
142
|
+
response=open("#{@website}quota/?format=#{url_params[:format]}")
|
143
|
+
return response.to_i
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def clean(p) #:nodoc:
|
150
|
+
(p.nil? || p.to_s=='') ? nil : p.to_i
|
151
|
+
end
|
152
|
+
|
153
|
+
def check_on_off(p) #:nodoc:
|
154
|
+
return nil if p.nil?
|
155
|
+
['ON', 'OFF'].include?(p.upcase) ? p : nil
|
156
|
+
end
|
157
|
+
|
158
|
+
def check_for_http_errors #:nodoc:
|
159
|
+
begin
|
160
|
+
yield
|
161
|
+
rescue OpenURI::HTTPError => boom
|
162
|
+
raise StandardError.new("Error from server: "+boom.io.read.strip)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
providers_dir = File.dirname(__FILE__) + '/../lib/providers'
|
3
|
+
$LOAD_PATH.unshift(providers_dir)
|
4
|
+
Dir[File.join(providers_dir, "*.rb")].each {|file| require File.basename(file)}
|
5
|
+
|
6
|
+
module RandomSources
|
7
|
+
# List of all the random sources providers supported
|
8
|
+
#
|
9
|
+
# It returns a string of names separated by commas. You can use any of the names to instantiate a class with the <tt>generator</tt> method
|
10
|
+
def self.list
|
11
|
+
self.constants*', '
|
12
|
+
end
|
13
|
+
|
14
|
+
# Instantiate and returns the class managing the online provider specified as param.
|
15
|
+
#
|
16
|
+
# If you don't know the names of the providers you can get them via the <tt>list</tt> method.
|
17
|
+
def self.generator(provider)
|
18
|
+
return self.const_get(provider).new if self.constants.include?(provider.to_sym)
|
19
|
+
raise NameError.new("Provider not available or name not recognized. Check the list of supported providers with RandomSources.list", provider.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: random_sources
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
version: "1.0"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- "Juanjo Baz\xC3\xA1n"
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
|
16
|
+
date: 2010-08-18 00:00:00 +02:00
|
17
|
+
default_executable:
|
18
|
+
dependencies:
|
19
|
+
- !ruby/object:Gem::Dependency
|
20
|
+
name: rspec
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :development
|
31
|
+
version_requirements: *id001
|
32
|
+
description: The Random Sources library provides genuine random numbers, generated by processes fundamentally governed by inherent uncertainty instead of some pseudo-random number algorithm. It uses http services from different online providers.
|
33
|
+
email: jjbazan@gmail.com
|
34
|
+
executables: []
|
35
|
+
|
36
|
+
extensions: []
|
37
|
+
|
38
|
+
extra_rdoc_files: []
|
39
|
+
|
40
|
+
files:
|
41
|
+
- MIT-LICENSE.txt
|
42
|
+
- README.rdoc
|
43
|
+
- lib/providers/hot_bits.rb
|
44
|
+
- lib/providers/random_org.rb
|
45
|
+
- lib/random_sources.rb
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: http://github.com/xuanxu/random_sources
|
48
|
+
licenses: []
|
49
|
+
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options:
|
52
|
+
- --main
|
53
|
+
- README.rdoc
|
54
|
+
- --charset=UTF-8
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.7
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Genuine random numbers and strings.
|
80
|
+
test_files: []
|
81
|
+
|