* 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
@ -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>
|
Fri Jun 8 12:44:37 2007 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||||
|
|
||||||
* {win32,wince}/Makefile.sub: add lex.c rule.
|
* {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…
x
Reference in New Issue
Block a user