* 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:
akr 2007-06-08 05:26:20 +00:00
Родитель 250a29cc6b
Коммит 94fdd87fdd
2 изменённых файлов: 70 добавлений и 0 удалений

Просмотреть файл

@ -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
Просмотреть файл

@ -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