mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/secrand.rb: new file for secure random interface.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12475 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
250a29cc6b
commit
94fdd87fdd
2 changed files with 70 additions and 0 deletions
|
@ -1,3 +1,7 @@
|
|||
Fri Jun 8 14:26:18 2007 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* lib/secrand.rb: new file for secure random interface.
|
||||
|
||||
Fri Jun 8 12:44:37 2007 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* {win32,wince}/Makefile.sub: add lex.c rule.
|
||||
|
|
66
lib/secrand.rb
Normal file
66
lib/secrand.rb
Normal file
|
@ -0,0 +1,66 @@
|
|||
begin
|
||||
require 'openssl'
|
||||
rescue LoadError
|
||||
end
|
||||
|
||||
module SecRand
|
||||
def self.random_bytes(n=nil)
|
||||
n ||= 16
|
||||
if defined? OpenSSL::Random
|
||||
return OpenSSL::Random.random_bytes(n)
|
||||
end
|
||||
if !defined?(@has_urandom) || @has_urandom
|
||||
@has_urandom = false
|
||||
flags = File::RDONLY
|
||||
flags |= File::NONBLOCK if defined? File::NONBLOCK
|
||||
flags |= File::NOCTTY if defined? File::NOCTTY
|
||||
flags |= File::NOFOLLOW if defined? File::NOFOLLOW
|
||||
begin
|
||||
File.open("/dev/urandom", flags) {|f|
|
||||
unless f.stat.chardev?
|
||||
raise Errno::ENOENT
|
||||
end
|
||||
@has_urandom = true
|
||||
ret = f.readpartial(n)
|
||||
if ret.length != n
|
||||
raise NotImplementedError, "Unexpected partial read from random device"
|
||||
end
|
||||
return ret
|
||||
}
|
||||
rescue Errno::ENOENT
|
||||
raise NotImplementedError, "No random device"
|
||||
end
|
||||
end
|
||||
raise NotImplementedError, "No random device"
|
||||
end
|
||||
|
||||
def self.hex(n=nil)
|
||||
random_bytes(n).unpack("H*")[0]
|
||||
end
|
||||
|
||||
def self.base64(n=nil)
|
||||
[random_bytes(n)].pack("m*").delete("\n")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def SecRand(n=0)
|
||||
if 0 < n
|
||||
hex = n.to_s(16)
|
||||
hex = '0' + hex if (hex.length & 1) == 1
|
||||
bin = [hex].pack("H*")
|
||||
mask = bin[0].ord
|
||||
mask |= mask >> 1
|
||||
mask |= mask >> 2
|
||||
mask |= mask >> 4
|
||||
begin
|
||||
rnd = SecRand.random_bytes(bin.length)
|
||||
rnd[0] = (rnd[0].ord & mask).chr
|
||||
end until rnd < bin
|
||||
rnd.unpack("H*")[0].hex
|
||||
else
|
||||
# assumption: Float::MANT_DIG <= 64
|
||||
i64 = SecRand.random_bytes(8).unpack("Q")[0]
|
||||
Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG)
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue