securerandom 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5369e43862e4524d9261f2c50b175c1bb99958cb2abfba54bae9fec715556133
4
+ data.tar.gz: cbe246fd3da662ace60c0ffe53a5175227611a4ed74d5c4ac84fde64c44d9ebb
5
+ SHA512:
6
+ metadata.gz: b416a144b9d4a134212b215ad45d03a80a1cc07d866ea7714363250d6f5f665bbf09410b37856ced86ebc2a7b5e16b3b04f4cab64b1b5ff05c1b4a223f3fcc7a
7
+ data.tar.gz: 174eb8f33e98f66f61c8792d512f04feedb9881ff4a79a39040da625b7b973f4c4796857cd1c132d16435df57ad74a229a1f7ec959cb66aac969d084496ee691
@@ -0,0 +1,24 @@
1
+ name: build
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ name: build (${{ matrix.ruby }} / ${{ matrix.os }})
8
+ strategy:
9
+ matrix:
10
+ ruby: [ 2.7, 2.6, 2.5, head ]
11
+ os: [ ubuntu-latest, macos-latest ]
12
+ runs-on: ${{ matrix.os }}
13
+ steps:
14
+ - uses: actions/checkout@master
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby }}
19
+ - name: Install dependencies
20
+ run: |
21
+ gem install bundler --no-document
22
+ bundle install
23
+ - name: Run test
24
+ run: rake compile test
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rake"
4
+ gem "test-unit"
@@ -0,0 +1,22 @@
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
@@ -0,0 +1,72 @@
1
+ # Securerandom
2
+
3
+ This library is an interface to secure random number generators which are
4
+ suitable for generating session keys in HTTP cookies, etc.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'securerandom'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle install
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install securerandom
21
+
22
+ ## Usage
23
+
24
+ Generate random hexadecimal strings:
25
+
26
+ ```ruby
27
+ require 'securerandom'
28
+
29
+ SecureRandom.hex(10) #=> "52750b30ffbc7de3b362"
30
+ SecureRandom.hex(10) #=> "92b15d6c8dc4beb5f559"
31
+ SecureRandom.hex(13) #=> "39b290146bea6ce975c37cfc23"
32
+ ```
33
+
34
+ Generate random base64 strings:
35
+
36
+ ```ruby
37
+ SecureRandom.base64(10) #=> "EcmTPZwWRAozdA=="
38
+ SecureRandom.base64(10) #=> "KO1nIU+p9DKxGg=="
39
+ SecureRandom.base64(12) #=> "7kJSM/MzBJI+75j8"
40
+ ```
41
+
42
+ Generate random binary strings:
43
+
44
+ ```ruby
45
+ SecureRandom.random_bytes(10) #=> "\016\t{\370g\310pbr\301"
46
+ SecureRandom.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337"
47
+ ```
48
+
49
+ Generate alphanumeric strings:
50
+
51
+ ```ruby
52
+ SecureRandom.alphanumeric(10) #=> "S8baxMJnPl"
53
+ SecureRandom.alphanumeric(10) #=> "aOxAg8BAJe"
54
+ ```
55
+
56
+ Generate UUIDs:
57
+
58
+ ```ruby
59
+ SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"
60
+ SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab"
61
+ ```
62
+
63
+ ## Development
64
+
65
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
66
+
67
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
68
+
69
+ ## Contributing
70
+
71
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/securerandom.
72
+
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "securerandom"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,317 @@
1
+ # -*- coding: us-ascii -*-
2
+ # frozen_string_literal: true
3
+
4
+ # == Secure random number generator interface.
5
+ #
6
+ # This library is an interface to secure random number generators which are
7
+ # suitable for generating session keys in HTTP cookies, etc.
8
+ #
9
+ # You can use this library in your application by requiring it:
10
+ #
11
+ # require 'securerandom'
12
+ #
13
+ # It supports the following secure random number generators:
14
+ #
15
+ # * openssl
16
+ # * /dev/urandom
17
+ # * Win32
18
+ #
19
+ # SecureRandom is extended by the Random::Formatter module which
20
+ # defines the following methods:
21
+ #
22
+ # * alphanumeric
23
+ # * base64
24
+ # * choose
25
+ # * gen_random
26
+ # * hex
27
+ # * rand
28
+ # * random_bytes
29
+ # * random_number
30
+ # * urlsafe_base64
31
+ # * uuid
32
+ #
33
+ # These methods are usable as class methods of SecureRandom such as
34
+ # `SecureRandom.hex`.
35
+ #
36
+ # === Examples
37
+ #
38
+ # Generate random hexadecimal strings:
39
+ #
40
+ # require 'securerandom'
41
+ #
42
+ # SecureRandom.hex(10) #=> "52750b30ffbc7de3b362"
43
+ # SecureRandom.hex(10) #=> "92b15d6c8dc4beb5f559"
44
+ # SecureRandom.hex(13) #=> "39b290146bea6ce975c37cfc23"
45
+ #
46
+ # Generate random base64 strings:
47
+ #
48
+ # SecureRandom.base64(10) #=> "EcmTPZwWRAozdA=="
49
+ # SecureRandom.base64(10) #=> "KO1nIU+p9DKxGg=="
50
+ # SecureRandom.base64(12) #=> "7kJSM/MzBJI+75j8"
51
+ #
52
+ # Generate random binary strings:
53
+ #
54
+ # SecureRandom.random_bytes(10) #=> "\016\t{\370g\310pbr\301"
55
+ # SecureRandom.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337"
56
+ #
57
+ # Generate alphanumeric strings:
58
+ #
59
+ # SecureRandom.alphanumeric(10) #=> "S8baxMJnPl"
60
+ # SecureRandom.alphanumeric(10) #=> "aOxAg8BAJe"
61
+ #
62
+ # Generate UUIDs:
63
+ #
64
+ # SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"
65
+ # SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab"
66
+ #
67
+
68
+ module SecureRandom
69
+ class << self
70
+ def bytes(n)
71
+ return gen_random(n)
72
+ end
73
+
74
+ private
75
+
76
+ def gen_random_openssl(n)
77
+ @pid = 0 unless defined?(@pid)
78
+ pid = $$
79
+ unless @pid == pid
80
+ now = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond)
81
+ OpenSSL::Random.random_add([now, @pid, pid].join(""), 0.0)
82
+ seed = Random.urandom(16)
83
+ if (seed)
84
+ OpenSSL::Random.random_add(seed, 16)
85
+ end
86
+ @pid = pid
87
+ end
88
+ return OpenSSL::Random.random_bytes(n)
89
+ end
90
+
91
+ def gen_random_urandom(n)
92
+ ret = Random.urandom(n)
93
+ unless ret
94
+ raise NotImplementedError, "No random device"
95
+ end
96
+ unless ret.length == n
97
+ raise NotImplementedError, "Unexpected partial read from random device: only #{ret.length} for #{n} bytes"
98
+ end
99
+ ret
100
+ end
101
+
102
+ ret = Random.urandom(1)
103
+ if ret.nil?
104
+ begin
105
+ require 'openssl'
106
+ rescue NoMethodError
107
+ raise NotImplementedError, "No random device"
108
+ else
109
+ alias gen_random gen_random_openssl
110
+ end
111
+ else
112
+ alias gen_random gen_random_urandom
113
+ end
114
+
115
+ public :gen_random
116
+ end
117
+ end
118
+
119
+ module Random::Formatter
120
+
121
+ # SecureRandom.random_bytes generates a random binary string.
122
+ #
123
+ # The argument _n_ specifies the length of the result string.
124
+ #
125
+ # If _n_ is not specified or is nil, 16 is assumed.
126
+ # It may be larger in future.
127
+ #
128
+ # The result may contain any byte: "\x00" - "\xff".
129
+ #
130
+ # require 'securerandom'
131
+ #
132
+ # SecureRandom.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6"
133
+ # SecureRandom.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97"
134
+ #
135
+ # If a secure random number generator is not available,
136
+ # +NotImplementedError+ is raised.
137
+ def random_bytes(n=nil)
138
+ n = n ? n.to_int : 16
139
+ gen_random(n)
140
+ end
141
+
142
+ # SecureRandom.hex generates a random hexadecimal string.
143
+ #
144
+ # The argument _n_ specifies the length, in bytes, of the random number to be generated.
145
+ # The length of the resulting hexadecimal string is twice of _n_.
146
+ #
147
+ # If _n_ is not specified or is nil, 16 is assumed.
148
+ # It may be larger in the future.
149
+ #
150
+ # The result may contain 0-9 and a-f.
151
+ #
152
+ # require 'securerandom'
153
+ #
154
+ # SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485"
155
+ # SecureRandom.hex #=> "91dc3bfb4de5b11d029d376634589b61"
156
+ #
157
+ # If a secure random number generator is not available,
158
+ # +NotImplementedError+ is raised.
159
+ def hex(n=nil)
160
+ random_bytes(n).unpack("H*")[0]
161
+ end
162
+
163
+ # SecureRandom.base64 generates a random base64 string.
164
+ #
165
+ # The argument _n_ specifies the length, in bytes, of the random number
166
+ # to be generated. The length of the result string is about 4/3 of _n_.
167
+ #
168
+ # If _n_ is not specified or is nil, 16 is assumed.
169
+ # It may be larger in the future.
170
+ #
171
+ # The result may contain A-Z, a-z, 0-9, "+", "/" and "=".
172
+ #
173
+ # require 'securerandom'
174
+ #
175
+ # SecureRandom.base64 #=> "/2BuBuLf3+WfSKyQbRcc/A=="
176
+ # SecureRandom.base64 #=> "6BbW0pxO0YENxn38HMUbcQ=="
177
+ #
178
+ # If a secure random number generator is not available,
179
+ # +NotImplementedError+ is raised.
180
+ #
181
+ # See RFC 3548 for the definition of base64.
182
+ def base64(n=nil)
183
+ [random_bytes(n)].pack("m0")
184
+ end
185
+
186
+ # SecureRandom.urlsafe_base64 generates a random URL-safe base64 string.
187
+ #
188
+ # The argument _n_ specifies the length, in bytes, of the random number
189
+ # to be generated. The length of the result string is about 4/3 of _n_.
190
+ #
191
+ # If _n_ is not specified or is nil, 16 is assumed.
192
+ # It may be larger in the future.
193
+ #
194
+ # The boolean argument _padding_ specifies the padding.
195
+ # If it is false or nil, padding is not generated.
196
+ # Otherwise padding is generated.
197
+ # By default, padding is not generated because "=" may be used as a URL delimiter.
198
+ #
199
+ # The result may contain A-Z, a-z, 0-9, "-" and "_".
200
+ # "=" is also used if _padding_ is true.
201
+ #
202
+ # require 'securerandom'
203
+ #
204
+ # SecureRandom.urlsafe_base64 #=> "b4GOKm4pOYU_-BOXcrUGDg"
205
+ # SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
206
+ #
207
+ # SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="
208
+ # SecureRandom.urlsafe_base64(nil, true) #=> "-M8rLhr7JEpJlqFGUMmOxg=="
209
+ #
210
+ # If a secure random number generator is not available,
211
+ # +NotImplementedError+ is raised.
212
+ #
213
+ # See RFC 3548 for the definition of URL-safe base64.
214
+ def urlsafe_base64(n=nil, padding=false)
215
+ s = [random_bytes(n)].pack("m0")
216
+ s.tr!("+/", "-_")
217
+ s.delete!("=") unless padding
218
+ s
219
+ end
220
+
221
+ # SecureRandom.uuid generates a random v4 UUID (Universally Unique IDentifier).
222
+ #
223
+ # require 'securerandom'
224
+ #
225
+ # SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"
226
+ # SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab"
227
+ # SecureRandom.uuid #=> "62936e70-1815-439b-bf89-8492855a7e6b"
228
+ #
229
+ # The version 4 UUID is purely random (except the version).
230
+ # It doesn't contain meaningful information such as MAC addresses, timestamps, etc.
231
+ #
232
+ # The result contains 122 random bits (15.25 random bytes).
233
+ #
234
+ # See RFC 4122 for details of UUID.
235
+ #
236
+ def uuid
237
+ ary = random_bytes(16).unpack("NnnnnN")
238
+ ary[2] = (ary[2] & 0x0fff) | 0x4000
239
+ ary[3] = (ary[3] & 0x3fff) | 0x8000
240
+ "%08x-%04x-%04x-%04x-%04x%08x" % ary
241
+ end
242
+
243
+ private def gen_random(n)
244
+ self.bytes(n)
245
+ end
246
+
247
+ # SecureRandom.choose generates a string that randomly draws from a
248
+ # source array of characters.
249
+ #
250
+ # The argument _source_ specifies the array of characters from which
251
+ # to generate the string.
252
+ # The argument _n_ specifies the length, in characters, of the string to be
253
+ # generated.
254
+ #
255
+ # The result may contain whatever characters are in the source array.
256
+ #
257
+ # require 'securerandom'
258
+ #
259
+ # SecureRandom.choose([*'l'..'r'], 16) #=> "lmrqpoonmmlqlron"
260
+ # SecureRandom.choose([*'0'..'9'], 5) #=> "27309"
261
+ #
262
+ # If a secure random number generator is not available,
263
+ # +NotImplementedError+ is raised.
264
+ private def choose(source, n)
265
+ size = source.size
266
+ m = 1
267
+ limit = size
268
+ while limit * size <= 0x100000000
269
+ limit *= size
270
+ m += 1
271
+ end
272
+ result = ''.dup
273
+ while m <= n
274
+ rs = random_number(limit)
275
+ is = rs.digits(size)
276
+ (m-is.length).times { is << 0 }
277
+ result << source.values_at(*is).join('')
278
+ n -= m
279
+ end
280
+ if 0 < n
281
+ rs = random_number(limit)
282
+ is = rs.digits(size)
283
+ if is.length < n
284
+ (n-is.length).times { is << 0 }
285
+ else
286
+ is.pop while n < is.length
287
+ end
288
+ result.concat source.values_at(*is).join('')
289
+ end
290
+ result
291
+ end
292
+
293
+ ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9']
294
+ # SecureRandom.alphanumeric generates a random alphanumeric string.
295
+ #
296
+ # The argument _n_ specifies the length, in characters, of the alphanumeric
297
+ # string to be generated.
298
+ #
299
+ # If _n_ is not specified or is nil, 16 is assumed.
300
+ # It may be larger in the future.
301
+ #
302
+ # The result may contain A-Z, a-z and 0-9.
303
+ #
304
+ # require 'securerandom'
305
+ #
306
+ # SecureRandom.alphanumeric #=> "2BuBuLf3WfSKyQbR"
307
+ # SecureRandom.alphanumeric(10) #=> "i6K93NdqiH"
308
+ #
309
+ # If a secure random number generator is not available,
310
+ # +NotImplementedError+ is raised.
311
+ def alphanumeric(n=nil)
312
+ n = 16 if n.nil?
313
+ choose(ALPHANUMERIC, n)
314
+ end
315
+ end
316
+
317
+ SecureRandom.extend(Random::Formatter)
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "securerandom"
3
+ spec.version = "0.1.0"
4
+ spec.authors = ["Tanaka Akira"]
5
+ spec.email = ["akr@fsij.org"]
6
+
7
+ spec.summary = %q{Interface for secure random number generator.}
8
+ spec.description = %q{Interface for secure random number generator.}
9
+ spec.homepage = "https://github.com/ruby/securerandom"
10
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
11
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
12
+
13
+ spec.metadata["homepage_uri"] = spec.homepage
14
+ spec.metadata["source_code_uri"] = spec.homepage
15
+
16
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: securerandom
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tanaka Akira
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-09-18 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Interface for secure random number generator.
14
+ email:
15
+ - akr@fsij.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".github/workflows/test.yml"
21
+ - ".gitignore"
22
+ - Gemfile
23
+ - LICENSE.txt
24
+ - README.md
25
+ - Rakefile
26
+ - bin/console
27
+ - bin/setup
28
+ - lib/securerandom.rb
29
+ - securerandom.gemspec
30
+ homepage: https://github.com/ruby/securerandom
31
+ licenses:
32
+ - Ruby
33
+ - BSD-2-Clause
34
+ metadata:
35
+ homepage_uri: https://github.com/ruby/securerandom
36
+ source_code_uri: https://github.com/ruby/securerandom
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 2.3.0
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubygems_version: 3.2.0.rc.1
53
+ signing_key:
54
+ specification_version: 4
55
+ summary: Interface for secure random number generator.
56
+ test_files: []