webget-securerandom 1.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.
Files changed (2) hide show
  1. data/lib/securerandom.rb +142 -0
  2. metadata +53 -0
@@ -0,0 +1,142 @@
1
+ # = Secure random number generator interface.
2
+ #
3
+ # This library is an interface for secure random number generator which is
4
+ # suitable for generating session key in HTTP cookies, etc.
5
+ #
6
+ # It supports following secure random number generators.
7
+ #
8
+ # * openssl
9
+ # * /dev/urandom
10
+ #
11
+ # Examples
12
+ # SecureRandom.hex(10) => "52750b30ffbc7de3b362"
13
+ # SecureRandom.hex(10) => "92b15d6c8dc4beb5f559"
14
+ # SecureRandom.hex(11) => "6aca1b5c58e4863e6b81b8"
15
+ # SecureRandom.hex(12) => "94b2fff3e7fd9b9c391a2306"
16
+ # SecureRandom.hex(13) => "39b290146bea6ce975c37cfc23"
17
+ #
18
+ # Examples
19
+ # SecureRandom.base64(10) => "EcmTPZwWRAozdA=="
20
+ # SecureRandom.base64(10) => "9b0nsevdwNuM/w=="
21
+ # SecureRandom.base64(10) => "KO1nIU+p9DKxGg=="
22
+ # SecureRandom.base64(11) => "l7XEiFja+8EKEtY="
23
+ # SecureRandom.base64(12) => "7kJSM/MzBJI+75j8"
24
+ # SecureRandom.base64(13) => "vKLJ0tXBHqQOuIcSIg=="
25
+ #
26
+ # Examples
27
+ # SecureRandom.random_bytes(10) => "\016\t{\370g\310pbr\301"
28
+ # SecureRandom.random_bytes(10) => "\323U\030TO\234\357\020\a\337"
29
+ #
30
+ ##
31
+
32
+ begin
33
+ require 'openssl'
34
+ rescue LoadError
35
+ end
36
+
37
+ module SecureRandom
38
+ # SecureRandom.random_bytes generates a random binary string.
39
+ #
40
+ # The argument n specifies the length of the result string.
41
+ #
42
+ # If n is not specified, 16 is assumed.
43
+ # It may be larger in future.
44
+ #
45
+ # If secure random number generator is not available,
46
+ # NotImplementedError is raised.
47
+ def self.random_bytes(n=nil)
48
+ n ||= 16
49
+ if defined? OpenSSL::Random
50
+ return OpenSSL::Random.random_bytes(n)
51
+ end
52
+ if !defined?(@has_urandom) || @has_urandom
53
+ @has_urandom = false
54
+ flags = File::RDONLY
55
+ flags |= File::NONBLOCK if defined? File::NONBLOCK
56
+ flags |= File::NOCTTY if defined? File::NOCTTY
57
+ flags |= File::NOFOLLOW if defined? File::NOFOLLOW
58
+ begin
59
+ File.open("/dev/urandom", flags) {|f|
60
+ unless f.stat.chardev?
61
+ raise Errno::ENOENT
62
+ end
63
+ @has_urandom = true
64
+ ret = f.readpartial(n)
65
+ if ret.length != n
66
+ raise NotImplementedError, "Unexpected partial read from random device"
67
+ end
68
+ return ret
69
+ }
70
+ rescue Errno::ENOENT
71
+ raise NotImplementedError, "No random device"
72
+ end
73
+ end
74
+ raise NotImplementedError, "No random device"
75
+ end
76
+
77
+ # SecureRandom.hex generates a random hex string.
78
+ #
79
+ # The argument n specifies the length of the random length.
80
+ # The length of the result string is twice of n.
81
+ #
82
+ # If n is not specified, 16 is assumed.
83
+ # It may be larger in future.
84
+ #
85
+ # If secure random number generator is not available,
86
+ # NotImplementedError is raised.
87
+ def self.hex(n=nil)
88
+ random_bytes(n).unpack("H*")[0]
89
+ end
90
+
91
+ # SecureRandom.base64 generates a random base64 string.
92
+ #
93
+ # The argument n specifies the length of the random length.
94
+ # The length of the result string is about 4/3 of n.
95
+ #
96
+ # If n is not specified, 16 is assumed.
97
+ # It may be larger in future.
98
+ #
99
+ # If secure random number generator is not available,
100
+ # NotImplementedError is raised.
101
+ def self.base64(n=nil)
102
+ [random_bytes(n)].pack("m*").delete("\n")
103
+ end
104
+
105
+ # SecureRandom.random_number generates a random number.
106
+ #
107
+ # If an positive integer is given as n,
108
+ # SecureRandom.random_number returns an integer:
109
+ # 0 <= SecureRandom.random_number(n) < n.
110
+ #
111
+ # If 0 is given or an argument is not given,
112
+ # SecureRandom.random_number returns an float:
113
+ # 0.0 <= SecureRandom.random_number() < 1.0.
114
+ def self.random_number(n=0)
115
+ if 0 < n
116
+ hex = n.to_s(16)
117
+ hex = '0' + hex if (hex.length & 1) == 1
118
+ bin = [hex].pack("H*")
119
+ mask = bin[0].ord
120
+ mask |= mask >> 1
121
+ mask |= mask >> 2
122
+ mask |= mask >> 4
123
+ begin
124
+ rnd = SecureRandom.random_bytes(bin.length)
125
+ rnd[0] = (rnd[0].ord & mask).chr
126
+ end until rnd < bin
127
+ rnd.unpack("H*")[0].hex
128
+ else
129
+ # assumption: Float::MANT_DIG <= 64
130
+ i64 = SecureRandom.random_bytes(8).unpack("Q")[0]
131
+ Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG)
132
+ end
133
+ end
134
+
135
+ end
136
+
137
+ # Added by joelparkerhenderson@gmail.com for backwards compatibility with Ruby 1.8
138
+ class Fixnum
139
+ def ord
140
+ return self
141
+ end
142
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: webget-securerandom
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - WebGet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-05 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: webget@webget.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/securerandom.rb
26
+ has_rdoc: true
27
+ homepage: http://webget.com/
28
+ post_install_message:
29
+ rdoc_options: []
30
+
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: "0"
38
+ version:
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ requirements: []
46
+
47
+ rubyforge_project:
48
+ rubygems_version: 1.2.0
49
+ signing_key:
50
+ specification_version: 2
51
+ summary: Ruby securerandom.rb as a gem for people who use earlier ruby versions
52
+ test_files:
53
+ - test/unit/securerandom_test.rb