[#31927] Re: Problem with Ruby 1.8.6-p110 on DragonFly (was [PATCH] Problem with ruby 1.8.6-p36 (and p39) on Tiger) — Takahiro Kambe <taca@...>
こんばんは。
[#31928] securerandom.rb for 1.8 — Tanaka Akira <akr@...>
securerandom.rb を 1.8 に追加し、cgi/session.rb に使わせたい
At Wed, 3 Oct 2007 12:49:20 +0900,
In article <86k5pwinco.knu@iDaemons.org>,
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
[#31936] Rake添付 — Yukihiro Matsumoto <matz@...>
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
Yukihiro Matsumoto さんは書きました:
-----BEGIN PGP SIGNED MESSAGE-----
NAKAMURA, Hiroshi さんは書きました:
At Wed, 10 Oct 2007 16:46:01 +0900,
-----BEGIN PGP SIGNED MESSAGE-----
[#31941] Re: [ruby-list:44071] Re: Ruby 1.8.6-p111 / 1.8.5-p114 released (Security Fix) — Shugo Maeda <shugo@...>
前田です。
-----BEGIN PGP SIGNED MESSAGE-----
前田です。
-----BEGIN PGP SIGNED MESSAGE-----
前田です。
In message <47063403.3070402@ruby-lang.org>,
In message <20071006.101915.596518898.gotoyuzo@sawara.priv.tokyo.netlab.jp>,
前田です。
In message <4709852A.1020606@ruby-lang.org>,
-----BEGIN PGP SIGNED MESSAGE-----
In message <470D9227.9090008@sarion.co.jp>,
-----BEGIN PGP SIGNED MESSAGE-----
[#31959] pcc: constant too big for cross-compiler — "NARUSE, Yui" <naruse@...>
成瀬です。
In article <470884D1.9040401@airemix.com>,
[#31980] multibyte string/regex literal with escape sequence — "U.Nakamura" <usa@...>
こんにちは、なかむら(う)です。
まつもと ゆきひろです
こんにちは、なかむら(う)です。
まつもと ゆきひろです
こんにちは、なかむら(う)です。
まつもと ゆきひろです
成瀬です。
こんにちは、なかむら(う)です。
In article <20071010091006.1988.USA@garbagecollect.jp>,
成瀬です。
In article <471003CB.7060701@airemix.com>,
成瀬です。
[#32049] Re: iconv enhancement in Ruby 1.9 — Nobuyoshi Nakada <nobu@...>
なかだです。
[#32133] undefined method `now' for DateTime:Class (NoMethodError) — "NAKAMURA, Hiroshi" <nakahiro@...>
-----BEGIN PGP SIGNED MESSAGE-----
どういう状況かよくわかってないのですが、いっそ必ず date 丸ごと読むようにするか、
-----BEGIN PGP SIGNED MESSAGE-----
> もしかして、単にtime.rbの「require 'parsedate'」を削ればいいだけだったり
-----BEGIN PGP SIGNED MESSAGE-----
> 確かに。で、1.9でparsedate.rbがなくなることを考えると、とりあえずtime.rb
In article <4b1598ce0710231835p1a0b3040kcc89bf0017a60c21@mail.gmail.com>,
[ruby-dev:31928] securerandom.rb for 1.8
securerandom.rb を 1.8 に追加し、cgi/session.rb に使わせたい
のですが、どうでしょうか。
cgi/session.rb に限りませんが、session cookie の生成には暗号
学的にそれなりに安全な乱数が必要です。
しかし、現状の Ruby ではそのような安全な乱数を得る簡単な API
が用意されていないため、安全なんかどうなのかよくわからない怪
しげなコードで session cookie を生成することがあります。
やはり、そういう難しい暗号の話は、餅は餅屋ということで外部
(OpenSSL や /dev/urandom) にまかせるのがいいのではないでしょ
うか。
Index: lib/securerandom.rb
===================================================================
--- lib/securerandom.rb (リビジョン 0)
+++ lib/securerandom.rb (リビジョン 0)
@@ -0,0 +1,137 @@
+# = Secure random number generator interface.
+#
+# This library is an interface for secure random number generator which is
+# suitable for generating session key in HTTP cookies, etc.
+#
+# It supports following secure random number generators.
+#
+# * openssl
+# * /dev/urandom
+#
+# == Example
+#
+# # random hexadecimal string.
+# p SecureRandom.hex(10) #=> "52750b30ffbc7de3b362"
+# p SecureRandom.hex(10) #=> "92b15d6c8dc4beb5f559"
+# p SecureRandom.hex(11) #=> "6aca1b5c58e4863e6b81b8"
+# p SecureRandom.hex(12) #=> "94b2fff3e7fd9b9c391a2306"
+# p SecureRandom.hex(13) #=> "39b290146bea6ce975c37cfc23"
+# ...
+#
+# # random base64 string.
+# p SecureRandom.base64(10) #=> "EcmTPZwWRAozdA=="
+# p SecureRandom.base64(10) #=> "9b0nsevdwNuM/w=="
+# p SecureRandom.base64(10) #=> "KO1nIU+p9DKxGg=="
+# p SecureRandom.base64(11) #=> "l7XEiFja+8EKEtY="
+# p SecureRandom.base64(12) #=> "7kJSM/MzBJI+75j8"
+# p SecureRandom.base64(13) #=> "vKLJ0tXBHqQOuIcSIg=="
+# ...
+#
+# # random binary string.
+# p SecureRandom.random_bytes(10) #=> "\016\t{\370g\310pbr\301"
+# p SecureRandom.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337"
+# ...
+
+begin
+ require 'openssl'
+rescue LoadError
+end
+
+module SecureRandom
+ # SecureRandom.random_bytes generates a random binary string.
+ #
+ # The argument n specifies the length of the result string.
+ #
+ # If n is not specified, 16 is assumed.
+ # It may be larger in future.
+ #
+ # If secure random number generator is not available,
+ # NotImplementedError is raised.
+ 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
+
+ # SecureRandom.hex generates a random hex string.
+ #
+ # The argument n specifies the length of the random length.
+ # The length of the result string is twice of n.
+ #
+ # If n is not specified, 16 is assumed.
+ # It may be larger in future.
+ #
+ # If secure random number generator is not available,
+ # NotImplementedError is raised.
+ def self.hex(n=nil)
+ random_bytes(n).unpack("H*")[0]
+ end
+
+ # SecureRandom.base64 generates a random base64 string.
+ #
+ # The argument n specifies the length of the random length.
+ # The length of the result string is about 4/3 of n.
+ #
+ # If n is not specified, 16 is assumed.
+ # It may be larger in future.
+ #
+ # If secure random number generator is not available,
+ # NotImplementedError is raised.
+ def self.base64(n=nil)
+ [random_bytes(n)].pack("m*").delete("\n")
+ end
+
+ # SecureRandom.random_number generates a random number.
+ #
+ # If an positive integer is given as n,
+ # SecureRandom.random_number returns an integer:
+ # 0 <= SecureRandom.random_number(n) < n.
+ #
+ # If 0 is given or an argument is not given,
+ # SecureRandom.random_number returns an float:
+ # 0.0 <= SecureRandom.random_number() < 1.0.
+ def self.random_number(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]
+ mask |= mask >> 1
+ mask |= mask >> 2
+ mask |= mask >> 4
+ begin
+ rnd = SecureRandom.random_bytes(bin.length)
+ rnd[0] = (rnd[0] & mask).chr
+ end until rnd < bin
+ rnd.unpack("H*")[0].hex
+ else
+ # assumption: Float::MANT_DIG <= 64
+ i64 = SecureRandom.random_bytes(8).unpack("Q")[0]
+ Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG)
+ end
+ end
+end
Index: lib/cgi/session.rb
===================================================================
--- lib/cgi/session.rb (リビジョン 13603)
+++ lib/cgi/session.rb (作業コピー)
@@ -174,16 +174,22 @@
# is used internally for automatically generated
# session ids.
def create_new_id
- require 'digest/md5'
- md5 = Digest::MD5::new
- now = Time::now
- md5.update(now.to_s)
- md5.update(String(now.usec))
- md5.update(String(rand(0)))
- md5.update(String($$))
- md5.update('foobar')
+ require 'securerandom'
+ begin
+ session_id = SecureRandom.hex(16)
+ rescue NotImplementedError
+ require 'digest/md5'
+ md5 = Digest::MD5::new
+ now = Time::now
+ md5.update(now.to_s)
+ md5.update(String(now.usec))
+ md5.update(String(rand(0)))
+ md5.update(String($$))
+ md5.update('foobar')
+ session_id = md5.hexdigest
+ end
@new_session = true
- md5.hexdigest
+ session_id
end
private :create_new_id
--
[田中 哲][たなか あきら][Tanaka Akira]