rubysl-securerandom 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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.