(主に)ゆぞさん

 OpenSSL::Digest::Digest クラスに、新設の Digest::Class を継承
させてみました。基本的にインターフェースの非互換はなく、純粋に
実装の共有を行うものです。

 唯一、 == で文字列を与えられた際は常に to_s (hexdigest) の値と
比較され、長さを見て digest() または hexdigest() の値と比較する
機能はなくなっています。Digest オブジェクトが与えられた場合は
digest() の結果同士を比較します。

 そのほかはすべて機能追加です。改めて検討をお願いします。

-- 
                     /
                    /__  __            Akinori.org / MUSHA.org
                   / )  )  ) )  /     FreeBSD.org / Ruby-lang.org
Akinori MUSHA aka / (_ /  ( (__(  @ iDaemons.org / and.or.jp

"Different eyes see different things,
    Different hearts beat on different strings --
       But there are times for you and me when all such things agree"

M ext/openssl/ossl_digest.c M ext/openssl/lib/openssl/digest.rb Index: ext/openssl/ossl_digest.c =================================================================== RCS file: /src/ruby/ext/openssl/ossl_digest.c,v retrieving revision 1.7 diff -u -r1.7 ossl_digest.c --- ext/openssl/ossl_digest.c 31 Aug 2006 10:27:46 -0000 1.7 +++ ext/openssl/ossl_digest.c 1 Nov 2006 05:02:34 -0000 @@ -141,24 +141,8 @@ return self; } -static void -digest_final(EVP_MD_CTX *ctx, char **buf, int *buf_len) -{ - EVP_MD_CTX final; - - if (!EVP_MD_CTX_copy(&final, ctx)) { - ossl_raise(eDigestError, NULL); - } - if (!(*buf = OPENSSL_malloc(EVP_MD_CTX_size(&final)))) { - EVP_MD_CTX_cleanup(&final); - ossl_raise(eDigestError, "Cannot allocate mem for digest"); - } - EVP_DigestFinal_ex(&final, *buf, buf_len); - EVP_MD_CTX_cleanup(&final); -} - static VALUE -ossl_digest_digest(VALUE self) +ossl_digest_finish(VALUE self) { EVP_MD_CTX *ctx; char *buf; @@ -166,96 +150,47 @@ VALUE digest; GetDigest(self, ctx); - digest_final(ctx, &buf, &buf_len); - digest = ossl_buf2str(buf, buf_len); - - return digest; -} - -static VALUE -ossl_digest_hexdigest(VALUE self) -{ - EVP_MD_CTX *ctx; - char *buf, *hexbuf; - int buf_len; - VALUE hexdigest; - GetDigest(self, ctx); - digest_final(ctx, &buf, &buf_len); - if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) { - OPENSSL_free(buf); - ossl_raise(eDigestError, "Memory alloc error"); + if (!(buf = OPENSSL_malloc(EVP_MD_CTX_size(ctx)))) { + ossl_raise(eDigestError, "Cannot allocate mem for digest"); } - OPENSSL_free(buf); - hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); - - return hexdigest; -} - -static VALUE -ossl_digest_s_digest(VALUE klass, VALUE str, VALUE data) -{ - VALUE obj = rb_class_new_instance(1, &str, klass); - - ossl_digest_update(obj, data); - return ossl_digest_digest(obj); -} - -static VALUE -ossl_digest_s_hexdigest(VALUE klass, VALUE str, VALUE data) -{ - VALUE obj = rb_class_new_instance(1, &str, klass); - - ossl_digest_update(obj, data); + EVP_DigestFinal_ex(ctx, buf, &buf_len); + EVP_MD_CTX_cleanup(ctx); - return ossl_digest_hexdigest(obj); + digest = ossl_buf2str(buf, buf_len); + + return digest; } static VALUE -ossl_digest_equal(VALUE self, VALUE other) +ossl_digest_name(VALUE self) { EVP_MD_CTX *ctx; - VALUE str1, str2; - if (rb_obj_is_kind_of(other, cDigest) == Qtrue) { - str2 = ossl_digest_digest(other); - } else { - StringValue(other); - str2 = other; - } GetDigest(self, ctx); - if (RSTRING_LEN(str2) == EVP_MD_CTX_size(ctx)) { - str1 = ossl_digest_digest(self); - } else { - str1 = ossl_digest_hexdigest(self); - } - if (RSTRING_LEN(str1) == RSTRING_LEN(str2) - && rb_str_cmp(str1, str2) == 0) { - return Qtrue; - } - return Qfalse; + return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx))); } static VALUE -ossl_digest_name(VALUE self) +ossl_digest_size(VALUE self) { EVP_MD_CTX *ctx; GetDigest(self, ctx); - return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx))); + return INT2NUM(EVP_MD_CTX_size(ctx)); } static VALUE -ossl_digest_size(VALUE self) +ossl_digest_block_length(VALUE self) { EVP_MD_CTX *ctx; GetDigest(self, ctx); - return INT2NUM(EVP_MD_CTX_size(ctx)); + return INT2NUM(EVP_MD_CTX_block_size(ctx)); } /* @@ -264,31 +199,24 @@ void Init_ossl_digest() { + rb_require("digest"); + mDigest = rb_define_module_under(mOSSL, "Digest"); eDigestError = rb_define_class_under(mDigest, "DigestError", eOSSLError); - - cDigest = rb_define_class_under(mDigest, "Digest", rb_cObject); + + cDigest = rb_define_class_under(mDigest, "Digest", rb_path2class("Digest::Class")); rb_define_alloc_func(cDigest, ossl_digest_alloc); - rb_define_singleton_method(cDigest, "digest", ossl_digest_s_digest, 2); - rb_define_singleton_method(cDigest, "hexdigest", ossl_digest_s_hexdigest, 2); rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1); - rb_define_method(cDigest, "reset", ossl_digest_reset, 0); - rb_define_copy_func(cDigest, ossl_digest_copy); - - rb_define_method(cDigest, "digest", ossl_digest_digest, 0); - rb_define_method(cDigest, "hexdigest", ossl_digest_hexdigest, 0); - rb_define_alias(cDigest, "inspect", "hexdigest"); - rb_define_alias(cDigest, "to_s", "hexdigest"); - + rb_define_method(cDigest, "reset", ossl_digest_reset, 0); rb_define_method(cDigest, "update", ossl_digest_update, 1); rb_define_alias(cDigest, "<<", "update"); - - rb_define_method(cDigest, "==", ossl_digest_equal, 1); - + rb_define_private_method(cDigest, "finish", ossl_digest_finish, 0); + rb_define_method(cDigest, "digest_length", ossl_digest_size, 0); + rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0); + rb_define_method(cDigest, "name", ossl_digest_name, 0); - rb_define_method(cDigest, "size", ossl_digest_size, 0); } Index: ext/openssl/lib/openssl/digest.rb =================================================================== RCS file: /src/ruby/ext/openssl/lib/openssl/digest.rb,v retrieving revision 1.3 diff -u -r1.3 digest.rb --- ext/openssl/lib/openssl/digest.rb 8 May 2006 00:11:59 -0000 1.3 +++ ext/openssl/lib/openssl/digest.rb 1 Nov 2006 05:02:34 -0000 @@ -36,11 +36,6 @@ super(name, data.first) } } - singleton = (class <<klass; self; end) - singleton.class_eval{ - define_method(:digest){|data| Digest.digest(name, data) } - define_method(:hexdigest){|data| Digest.hexdigest(name, data) } - } const_set(name, klass) }