rubysl-securerandom 1.0.0 → 2.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ff8c11aa9809bb98128b216ad032db00d45ce48
4
- data.tar.gz: 3198625bdd325fbc434ddbfcfe23ecc90b73fde3
3
+ metadata.gz: 302f7210b19637415ffe3f827bc725db6f2a8d3b
4
+ data.tar.gz: 5e670c291b50e6940b6e95bf402f820ebeb1fa34
5
5
  SHA512:
6
- metadata.gz: bcfff7a007ad01f43da4e111ff1bd1f083866cbc980efbd17e197aefafff02f681948177b16052292d06a49f95d13d208609712c96355600e3f9122c3e0ec713
7
- data.tar.gz: 2149708075a815621b504f9ba3abfebda5bd11bfb50b7fc89e83975274680c9cc16fce35a249f407fcd3fbb2e2ee31de1d327eb8bd176d5b741a3dde1691d224
6
+ metadata.gz: 3343644b5873052e43005122004a2af504bfa8fcfe8ec2e16e0a236decf6c58d3c298a7f3b6285a9157cf6c2a5a7e7944d02171b8940af7fdb55026a3c5dbe6a
7
+ data.tar.gz: 00d66d2dd39b8fc47e66ec7bbc8d2aa164676f2e1fdf6866d1aca68f27eaf7219f6473d852ad99b57dd01626d1b66b8011fbce17367a58dc2248c6e33f9c9cf6
@@ -1,14 +1,7 @@
1
1
  language: ruby
2
2
  env:
3
3
  - RUBYLIB=lib
4
- - RUBYLIB=
5
- script: mspec spec
4
+ script: bundle exec mspec
6
5
  rvm:
7
- - 2.0.0
8
- - rbx-2.2.1
9
- matrix:
10
- exclude:
11
- - rvm: 2.0.0
12
- env: RUBYLIB=lib
13
- - rvm: rbx-2.2.1
14
- env: RUBYLIB=
6
+ - 1.9.3
7
+ - rbx-nightly-19mode
@@ -7,6 +7,7 @@
7
7
  #
8
8
  # * openssl
9
9
  # * /dev/urandom
10
+ # * Win32
10
11
  #
11
12
  # == Example
12
13
  #
@@ -40,32 +41,37 @@ end
40
41
  module SecureRandom
41
42
  # SecureRandom.random_bytes generates a random binary string.
42
43
  #
43
- # The argument n specifies the length of the result string.
44
+ # The argument _n_ specifies the length of the result string.
44
45
  #
45
- # If n is not specified, 16 is assumed.
46
+ # If _n_ is not specified, 16 is assumed.
46
47
  # It may be larger in future.
47
48
  #
49
+ # The result may contain any byte: "\x00" - "\xff".
50
+ #
51
+ # p SecureRandom.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6"
52
+ # p SecureRandom.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97"
53
+ #
48
54
  # If secure random number generator is not available,
49
55
  # NotImplementedError is raised.
50
56
  def self.random_bytes(n=nil)
51
57
  n ||= 16
58
+
52
59
  if defined? OpenSSL::Random
53
60
  @pid = 0 if !defined?(@pid)
54
61
  pid = $$
55
62
  if @pid != pid
56
63
  now = Time.now
57
- ary = [now.to_i, now.usec, @pid, pid]
58
- OpenSSL::Random.seed(ary.join('.'))
64
+ ary = [now.to_i, now.nsec, @pid, pid]
65
+ OpenSSL::Random.seed(ary.to_s)
59
66
  @pid = pid
60
67
  end
61
68
  return OpenSSL::Random.random_bytes(n)
62
69
  end
70
+
63
71
  if !defined?(@has_urandom) || @has_urandom
64
- @has_urandom = false
65
72
  flags = File::RDONLY
66
73
  flags |= File::NONBLOCK if defined? File::NONBLOCK
67
74
  flags |= File::NOCTTY if defined? File::NOCTTY
68
- flags |= File::NOFOLLOW if defined? File::NOFOLLOW
69
75
  begin
70
76
  File.open("/dev/urandom", flags) {|f|
71
77
  unless f.stat.chardev?
@@ -79,20 +85,55 @@ module SecureRandom
79
85
  return ret
80
86
  }
81
87
  rescue Errno::ENOENT
82
- raise NotImplementedError, "No random device"
88
+ @has_urandom = false
89
+ end
90
+ end
91
+
92
+ if !defined?(@has_win32)
93
+ begin
94
+ require 'Win32API'
95
+
96
+ crypt_acquire_context = Win32API.new("advapi32", "CryptAcquireContext", 'PPPII', 'L')
97
+ @crypt_gen_random = Win32API.new("advapi32", "CryptGenRandom", 'LIP', 'L')
98
+
99
+ hProvStr = " " * 4
100
+ prov_rsa_full = 1
101
+ crypt_verifycontext = 0xF0000000
102
+
103
+ if crypt_acquire_context.call(hProvStr, nil, nil, prov_rsa_full, crypt_verifycontext) == 0
104
+ raise SystemCallError, "CryptAcquireContext failed: #{lastWin32ErrorMessage}"
105
+ end
106
+ @hProv, = hProvStr.unpack('L')
107
+
108
+ @has_win32 = true
109
+ rescue LoadError
110
+ @has_win32 = false
83
111
  end
84
112
  end
113
+ if @has_win32
114
+ bytes = " ".force_encoding("ASCII-8BIT") * n
115
+ if @crypt_gen_random.call(@hProv, bytes.size, bytes) == 0
116
+ raise SystemCallError, "CryptGenRandom failed: #{lastWin32ErrorMessage}"
117
+ end
118
+ return bytes
119
+ end
120
+
85
121
  raise NotImplementedError, "No random device"
86
122
  end
87
123
 
88
124
  # SecureRandom.hex generates a random hex string.
89
125
  #
90
- # The argument n specifies the length of the random length.
91
- # The length of the result string is twice of n.
126
+ # The argument _n_ specifies the length of the random length.
127
+ # The length of the result string is twice of _n_.
92
128
  #
93
- # If n is not specified, 16 is assumed.
129
+ # If _n_ is not specified, 16 is assumed.
94
130
  # It may be larger in future.
95
131
  #
132
+ # The result may contain 0-9 and a-f.
133
+ #
134
+ # p SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485"
135
+ # p SecureRandom.hex #=> "91dc3bfb4de5b11d029d376634589b61"
136
+ #
96
137
  # If secure random number generator is not available,
97
138
  # NotImplementedError is raised.
98
139
  def self.hex(n=nil)
@@ -101,39 +142,87 @@ module SecureRandom
101
142
 
102
143
  # SecureRandom.base64 generates a random base64 string.
103
144
  #
104
- # The argument n specifies the length of the random length.
105
- # The length of the result string is about 4/3 of n.
145
+ # The argument _n_ specifies the length of the random length.
146
+ # The length of the result string is about 4/3 of _n_.
106
147
  #
107
- # If n is not specified, 16 is assumed.
148
+ # If _n_ is not specified, 16 is assumed.
108
149
  # It may be larger in future.
109
150
  #
151
+ # The result may contain A-Z, a-z, 0-9, "+", "/" and "=".
152
+ #
153
+ # p SecureRandom.base64 #=> "/2BuBuLf3+WfSKyQbRcc/A=="
154
+ # p SecureRandom.base64 #=> "6BbW0pxO0YENxn38HMUbcQ=="
155
+ #
110
156
  # If secure random number generator is not available,
111
157
  # NotImplementedError is raised.
158
+ #
159
+ # See RFC 3548 for the definition of base64.
112
160
  def self.base64(n=nil)
113
161
  [random_bytes(n)].pack("m*").delete("\n")
114
162
  end
115
163
 
164
+ # SecureRandom.urlsafe_base64 generates a random URL-safe base64 string.
165
+ #
166
+ # The argument _n_ specifies the length of the random length.
167
+ # The length of the result string is about 4/3 of _n_.
168
+ #
169
+ # If _n_ is not specified, 16 is assumed.
170
+ # It may be larger in future.
171
+ #
172
+ # The boolean argument _padding_ specifies the padding.
173
+ # If it is false or nil, padding is not generated.
174
+ # Otherwise padding is generated.
175
+ # By default, padding is not generated because "=" may be used as a URL delimiter.
176
+ #
177
+ # The result may contain A-Z, a-z, 0-9, "-" and "_".
178
+ # "=" is also used if _padding_ is true.
179
+ #
180
+ # p SecureRandom.urlsafe_base64 #=> "b4GOKm4pOYU_-BOXcrUGDg"
181
+ # p SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
182
+ #
183
+ # p SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="
184
+ # p SecureRandom.urlsafe_base64(nil, true) #=> "-M8rLhr7JEpJlqFGUMmOxg=="
185
+ #
186
+ # If secure random number generator is not available,
187
+ # NotImplementedError is raised.
188
+ #
189
+ # See RFC 3548 for the definition of URL-safe base64.
190
+ def self.urlsafe_base64(n=nil, padding=false)
191
+ s = [random_bytes(n)].pack("m*")
192
+ s.delete!("\n")
193
+ s.tr!("+/", "-_")
194
+ s.delete!("=") if !padding
195
+ s
196
+ end
197
+
116
198
  # SecureRandom.random_number generates a random number.
117
199
  #
118
- # If an positive integer is given as n,
200
+ # If a positive integer is given as _n_,
119
201
  # SecureRandom.random_number returns an integer:
120
202
  # 0 <= SecureRandom.random_number(n) < n.
121
203
  #
204
+ # p SecureRandom.random_number(100) #=> 15
205
+ # p SecureRandom.random_number(100) #=> 88
206
+ #
122
207
  # If 0 is given or an argument is not given,
123
- # SecureRandom.random_number returns an float:
208
+ # SecureRandom.random_number returns a float:
124
209
  # 0.0 <= SecureRandom.random_number() < 1.0.
210
+ #
211
+ # p SecureRandom.random_number #=> 0.596506046187744
212
+ # p SecureRandom.random_number #=> 0.350621695741409
213
+ #
125
214
  def self.random_number(n=0)
126
215
  if 0 < n
127
216
  hex = n.to_s(16)
128
217
  hex = '0' + hex if (hex.length & 1) == 1
129
218
  bin = [hex].pack("H*")
130
- mask = bin[0]
219
+ mask = bin[0].ord
131
220
  mask |= mask >> 1
132
221
  mask |= mask >> 2
133
222
  mask |= mask >> 4
134
223
  begin
135
224
  rnd = SecureRandom.random_bytes(bin.length)
136
- rnd[0] = (rnd[0] & mask).chr
225
+ rnd[0] = (rnd[0].ord & mask).chr
137
226
  end until rnd < bin
138
227
  rnd.unpack("H*")[0].hex
139
228
  else
@@ -142,4 +231,35 @@ module SecureRandom
142
231
  Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG)
143
232
  end
144
233
  end
234
+
235
+ # SecureRandom.uuid generates a v4 random UUID (Universally Unique IDentifier).
236
+ #
237
+ # p SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"
238
+ # p SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab"
239
+ # p SecureRandom.uuid #=> "62936e70-1815-439b-bf89-8492855a7e6b"
240
+ #
241
+ # The version 4 UUID is purely random (except the version).
242
+ # It doesn't contain meaningful information such as MAC address, time, etc.
243
+ #
244
+ # See RFC 4122 for details of UUID.
245
+ #
246
+ def self.uuid
247
+ ary = self.random_bytes(16).unpack("NnnnnN")
248
+ ary[2] = (ary[2] & 0x0fff) | 0x4000
249
+ ary[3] = (ary[3] & 0x3fff) | 0x8000
250
+ "%08x-%04x-%04x-%04x-%04x%08x" % ary
251
+ end
252
+
253
+ # Following code is based on David Garamond's GUID library for Ruby.
254
+ def self.lastWin32ErrorMessage # :nodoc:
255
+ get_last_error = Win32API.new("kernel32", "GetLastError", '', 'L')
256
+ format_message = Win32API.new("kernel32", "FormatMessageA", 'LPLLPLPPPPPPPP', 'L')
257
+ format_message_ignore_inserts = 0x00000200
258
+ format_message_from_system = 0x00001000
259
+
260
+ code = get_last_error.call
261
+ msg = "\0" * 1024
262
+ len = format_message.call(format_message_ignore_inserts + format_message_from_system, 0, code, 0, msg, 1024, nil, nil, nil, nil, nil, nil, nil, nil)
263
+ msg[0, len].tr("\r", '').chomp
264
+ end
145
265
  end
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module SecureRandom
3
- VERSION = "1.0.0"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
@@ -16,10 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ["lib"]
18
18
 
19
- spec.required_ruby_version = "~> 1.8.7"
20
-
21
19
  spec.add_development_dependency "bundler", "~> 1.3"
22
20
  spec.add_development_dependency "rake", "~> 10.0"
23
21
  spec.add_development_dependency "mspec", "~> 1.5"
24
- spec.add_development_dependency "rubysl-prettyprint", "~> 1.0"
25
22
  end
metadata CHANGED
@@ -1,71 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubysl-securerandom
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-16 00:00:00.000000000 Z
11
+ date: 2013-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.5'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.5'
55
- - !ruby/object:Gem::Dependency
56
- name: rubysl-prettyprint
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
55
  description: Ruby standard lib securerandom.
70
56
  email:
71
57
  - brixen@gmail.com
@@ -73,8 +59,8 @@ executables: []
73
59
  extensions: []
74
60
  extra_rdoc_files: []
75
61
  files:
76
- - ".gitignore"
77
- - ".travis.yml"
62
+ - .gitignore
63
+ - .travis.yml
78
64
  - Gemfile
79
65
  - LICENSE
80
66
  - README.md
@@ -98,17 +84,17 @@ require_paths:
98
84
  - lib
99
85
  required_ruby_version: !ruby/object:Gem::Requirement
100
86
  requirements:
101
- - - "~>"
87
+ - - '>='
102
88
  - !ruby/object:Gem::Version
103
- version: 1.8.7
89
+ version: '0'
104
90
  required_rubygems_version: !ruby/object:Gem::Requirement
105
91
  requirements:
106
- - - ">="
92
+ - - '>='
107
93
  - !ruby/object:Gem::Version
108
94
  version: '0'
109
95
  requirements: []
110
96
  rubyforge_project:
111
- rubygems_version: 2.2.2
97
+ rubygems_version: 2.0.7
112
98
  signing_key:
113
99
  specification_version: 4
114
100
  summary: Ruby standard lib securerandom.