1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* ext/openssl/extconf.rb: add check for OBJ_NAME_do_all_sorted.

* ext/openssl/ossl_cipher.c (ossl_s_ciphers): new method
  OpenSSL::Cipher.ciphers. it returns all the cipher names.

* ext/openssl/ossl_cipher.c (ossl_cipher_init): refine warning message.

* ext/openssl/lib/openssl/cipher.rb: reimplement without eval() and
  add constants AES128, AES192, AES256. [ruby-dev:28610]

* ext/openssl/lib/openssl/digest.rb: reimplement without eval().

* test/openssl/test_cipher.rb, test_digest: fix about reimplemented               features.

* sample/openssl/cipher.rb: rewrite all.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10137 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
gotoyuzo 2006-05-08 00:12:00 +00:00
parent 911655fd17
commit 55ef220fe0
8 changed files with 182 additions and 64 deletions

View file

@ -1,3 +1,22 @@
Mon May 8 09:10:31 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/extconf.rb: add check for OBJ_NAME_do_all_sorted.
* ext/openssl/ossl_cipher.c (ossl_s_ciphers): new method
OpenSSL::Cipher.ciphers. it returns all the cipher names.
* ext/openssl/ossl_cipher.c (ossl_cipher_init): refine warning message.
* ext/openssl/lib/openssl/cipher.rb: reimplement without eval() and
add constants AES128, AES192, AES256. [ruby-dev:28610]
* ext/openssl/lib/openssl/digest.rb: reimplement without eval().
* test/openssl/test_cipher.rb, test_digest: fix about reimplemented
features.
* sample/openssl/cipher.rb: rewrite all.
Sun May 7 03:09:51 2006 Stephan Maka <stephan@spaceboyz.net> Sun May 7 03:09:51 2006 Stephan Maka <stephan@spaceboyz.net>
* lib/resolv.rb (Resolv::DNS::Requester::ConnectedUDP#initialize): * lib/resolv.rb (Resolv::DNS::Requester::ConnectedUDP#initialize):

View file

@ -91,6 +91,7 @@ have_func("X509_CRL_set_version")
have_func("X509_CRL_sort") have_func("X509_CRL_sort")
have_func("X509_STORE_get_ex_data") have_func("X509_STORE_get_ex_data")
have_func("X509_STORE_set_ex_data") have_func("X509_STORE_set_ex_data")
have_func("OBJ_NAME_do_all_sorted")
have_func("OPENSSL_cleanse") have_func("OPENSSL_cleanse")
if try_compile("#define FOO(a, ...) foo(a, ##__VA_ARGS__)\n int x(){FOO(1);FOO(1,2);FOO(1,2,3);}\n") if try_compile("#define FOO(a, ...) foo(a, ##__VA_ARGS__)\n int x(){FOO(1);FOO(1,2);FOO(1,2,3);}\n")
$defs.push("-DHAVE_VA_ARGS_MACRO") $defs.push("-DHAVE_VA_ARGS_MACRO")

View file

@ -20,19 +20,25 @@
module OpenSSL module OpenSSL
module Cipher module Cipher
%w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|cipher| %w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
eval(<<-EOD) klass = Class.new(Cipher){
class #{cipher} < Cipher define_method(:initialize){|*args|
def initialize(*args) cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" }
args = args.join('-') super(cipher_name)
if args.size == 0 }
super(\"#{cipher}\") }
else const_set(name, klass)
super(\"#{cipher}-#\{args\}\") }
end
end %w(128 192 256).each{|keylen|
end klass = Class.new(Cipher){
EOD define_method(:initialize){|mode|
mode ||= "CBC"
cipher_name = "AES-#{keylen}-#{mode}"
super(cipher_name)
}
}
const_set("AES#{keylen}", klass)
} }
class Cipher class Cipher

View file

@ -26,22 +26,22 @@ module OpenSSL
alg += %w(SHA224 SHA256 SHA384 SHA512) alg += %w(SHA224 SHA256 SHA384 SHA512)
end end
alg.each{|digest| alg.each{|name|
self.module_eval(<<-EOD) klass = Class.new(Digest){
class #{digest} < Digest define_method(:initialize){|*data|
def initialize(data=nil) if data.length > 1
super(\"#{digest}\", data) raise ArgumentError,
"wrong number of arguments (#{data.length} for 1)"
end end
super(name, data.first)
def #{digest}::digest(data) }
Digest::digest(\"#{digest}\", data) }
end singleton = (class <<klass; self; end)
singleton.class_eval{
def #{digest}::hexdigest(data) define_method(:digest){|data| Digest.digest(name, data) }
Digest::hexdigest(\"#{digest}\", data) define_method(:hexdigest){|data| Digest.hexdigest(name, data) }
end }
end const_set(name, klass)
EOD
} }
end # Digest end # Digest

View file

@ -117,6 +117,29 @@ ossl_cipher_copy(VALUE self, VALUE other)
return self; return self;
} }
static void*
add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
{
rb_ary_push(ary, rb_str_new2(name->name));
}
static VALUE
ossl_s_ciphers(VALUE self)
{
#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
VALUE ary;
ary = rb_ary_new();
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
(void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary,
(void*)ary);
return ary;
#else
rb_notimplement();
#endif
}
static VALUE static VALUE
ossl_cipher_reset(VALUE self) ossl_cipher_reset(VALUE self)
{ {
@ -143,13 +166,14 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
* We deprecated the arguments for this method, but we decided * We deprecated the arguments for this method, but we decided
* keeping this behaviour for backward compatibility. * keeping this behaviour for backward compatibility.
*/ */
char *cname = rb_class2name(rb_obj_class(self));
rb_warn("argumtents for %s#encrypt and %s#decrypt were deprecated; "
"use %s#pkcs5_keyivgen to derive key and IV",
cname, cname, cname);
StringValue(pass); StringValue(pass);
GetCipher(self, ctx); GetCipher(self, ctx);
if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv)); if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
else{ else{
char *cname = rb_class2name(rb_obj_class(self));
rb_warning("key derivation by %s#encrypt is deprecated; "
"use %s::pkcs5_keyivgen instead", cname, cname);
StringValue(init_v); StringValue(init_v);
if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) { if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) {
memset(iv, 0, EVP_MAX_IV_LENGTH); memset(iv, 0, EVP_MAX_IV_LENGTH);
@ -352,6 +376,7 @@ Init_ossl_cipher(void)
rb_define_alloc_func(cCipher, ossl_cipher_alloc); rb_define_alloc_func(cCipher, ossl_cipher_alloc);
rb_define_copy_func(cCipher, ossl_cipher_copy); rb_define_copy_func(cCipher, ossl_cipher_copy);
rb_define_module_function(mCipher, "ciphers", ossl_s_ciphers, 0);
rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1); rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
rb_define_method(cCipher, "reset", ossl_cipher_reset, 0); rb_define_method(cCipher, "reset", ossl_cipher_reset, 0);
rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1); rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1);

View file

@ -1,29 +1,54 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require 'openssl' require 'openssl'
def crypt_by_password(alg, pass, salt, text)
puts "--Setup--"
puts %(cipher alg: "#{alg}")
puts %(plain text: "#{text}")
puts %(password: "#{pass}")
puts %(salt: "#{salt}")
puts
puts "--Encrypting--"
enc = OpenSSL::Cipher::Cipher.new(alg)
enc.encrypt
enc.pkcs5_keyivgen(pass, salt)
cipher = enc.update(text)
cipher << enc.final
puts %(encrypted text: #{cipher.inspect})
puts
puts "--Decrypting--"
dec = OpenSSL::Cipher::Cipher.new(alg)
dec.decrypt
dec.pkcs5_keyivgen(pass, salt)
plain = dec.update(cipher)
plain << dec.final
puts %(decrypted text: "#{plain}")
puts
end
def ciphers
ciphers = OpenSSL::Cipher.ciphers.sort
ciphers.each{|i|
if i.upcase != i && ciphers.include?(i.upcase)
ciphers.delete(i)
end
}
return ciphers
end
puts "Supported ciphers in #{OpenSSL::OPENSSL_VERSION}:"
ciphers.each_with_index{|name, i|
printf("%-15s", name)
puts if (i + 1) % 5 == 0
}
puts
puts
alg = ARGV.shift || ciphers.first
pass = "secret password"
salt = "8 octets" # or nil
text = "abcdefghijklmnopqrstuvwxyz" text = "abcdefghijklmnopqrstuvwxyz"
key = "key"
alg = "DES-EDE3-CBC"
#alg = "AES-128-CBC"
puts "--Setup--" crypt_by_password(alg, pass, salt, text)
puts %(clear text: "#{text}")
puts %(symmetric key: "#{key}")
puts %(cipher alg: "#{alg}")
puts
puts "--Encrypting--"
des = OpenSSL::Cipher::Cipher.new(alg)
des.encrypt(key) #, "iv12345678")
cipher = des.update(text)
cipher << des.final
puts %(encrypted text: #{cipher.inspect})
puts
puts "--Decrypting--"
des = OpenSSL::Cipher::Cipher.new(alg)
des.decrypt(key) #, "iv12345678")
out = des.update(cipher)
out << des.final
puts %(decrypted text: "#{out}")
puts

View file

@ -11,7 +11,7 @@ class OpenSSL::TestCipher < Test::Unit::TestCase
@c1 = OpenSSL::Cipher::Cipher.new("DES-EDE3-CBC") @c1 = OpenSSL::Cipher::Cipher.new("DES-EDE3-CBC")
@c2 = OpenSSL::Cipher::DES.new(:EDE3, "CBC") @c2 = OpenSSL::Cipher::DES.new(:EDE3, "CBC")
@key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" @key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
@iv = @key @iv = "\0\0\0\0\0\0\0\0"
@hexkey = "0000000000000000000000000000000000000000000000" @hexkey = "0000000000000000000000000000000000000000000000"
@hexiv = "0000000000000000" @hexiv = "0000000000000000"
@data = "DATA" @data = "DATA"
@ -22,11 +22,16 @@ class OpenSSL::TestCipher < Test::Unit::TestCase
end end
def test_crypt def test_crypt
s1 = @c1.encrypt(@key, @iv).update(@data) + @c1.final @c1.encrypt.pkcs5_keyivgen(@key, @iv)
s2 = @c2.encrypt(@key, @iv).update(@data) + @c2.final @c2.encrypt.pkcs5_keyivgen(@key, @iv)
s1 = @c1.update(@data) + @c1.final
s2 = @c2.update(@data) + @c2.final
assert_equal(s1, s2, "encrypt") assert_equal(s1, s2, "encrypt")
assert_equal(@data, @c1.decrypt(@key, @iv).update(s2)+@c1.final, "decrypt")
assert_equal(@data, @c2.decrypt(@key, @iv).update(s1)+@c2.final, "decrypt") @c1.decrypt.pkcs5_keyivgen(@key, @iv)
@c2.decrypt.pkcs5_keyivgen(@key, @iv)
assert_equal(@data, @c1.update(s1)+@c1.final, "decrypt")
assert_equal(@data, @c2.update(s2)+@c2.final, "decrypt")
end end
def test_info def test_info
@ -62,6 +67,29 @@ class OpenSSL::TestCipher < Test::Unit::TestCase
@c1.encrypt @c1.encrypt
assert_raises(ArgumentError){ @c1.update("") } assert_raises(ArgumentError){ @c1.update("") }
end end
if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00907000
def test_ciphers
OpenSSL::Cipher.ciphers.each{|name|
assert(OpenSSL::Cipher::Cipher.new(name).is_a?(OpenSSL::Cipher::Cipher))
}
end
def test_AES
pt = File.read(__FILE__)
%w(ECB CBC CFB OFB).each{|mode|
c1 = OpenSSL::Cipher::AES256.new(mode)
c1.encrypt
c1.pkcs5_keyivgen("passwd")
ct = c1.update(pt) + c1.final
c2 = OpenSSL::Cipher::AES256.new(mode)
c2.decrypt
c2.pkcs5_keyivgen("passwd")
assert_equal(pt, c2.update(ct) + c2.final)
}
end
end
end end
end end

View file

@ -62,11 +62,25 @@ class OpenSSL::TestDigest < Test::Unit::TestCase
end end
if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000 if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000
def encode16(str)
str.unpack("H*").first
end
def test_098_features def test_098_features
assert_equal("abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5", OpenSSL::Digest::SHA224.hexdigest("a")) sha224_a = "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5"
assert_equal("ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", OpenSSL::Digest::SHA256.hexdigest("a")) sha256_a = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
assert_equal("54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31", OpenSSL::Digest::SHA384.hexdigest("a")) sha384_a = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31"
assert_equal("1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75", OpenSSL::Digest::SHA512.hexdigest("a")) sha512_a = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"
assert_equal(sha224_a, OpenSSL::Digest::SHA224.hexdigest("a"))
assert_equal(sha256_a, OpenSSL::Digest::SHA256.hexdigest("a"))
assert_equal(sha384_a, OpenSSL::Digest::SHA384.hexdigest("a"))
assert_equal(sha512_a, OpenSSL::Digest::SHA512.hexdigest("a"))
assert_equal(sha224_a, encode16(OpenSSL::Digest::SHA224.digest("a")))
assert_equal(sha256_a, encode16(OpenSSL::Digest::SHA256.digest("a")))
assert_equal(sha384_a, encode16(OpenSSL::Digest::SHA384.digest("a")))
assert_equal(sha512_a, encode16(OpenSSL::Digest::SHA512.digest("a")))
end end
end end
end end