Digest'ifying OpenSSL::Digest

(e$B<g$Ke(B)e$B$f$>$5$se(B

e$B!!e(BOpenSSL::Digest::* e$B$re(B Digest::Base
e$B$N%5%V%/%i%9$K$9$k$Y$/[email protected](B
e$B$7$F$$?$N$G!"%l%S%e!<$r$*4j$$$7$^$9!#$J$*e(B openssl/digest.rb
e$B$Ne(B
e$B=hM}$Oe(B ossl_digest.c e$B$K<h$j9~$
$^$7$?!#e(B

e$B!!%a%j%C%H$H$7$F$O!“6l$b$J$/e(BAPIe$B$,E}0l$5$l$k!“e(B #file()
e$B$J$I$NDI2Ce(B
e$B%a%=%C%I$,;H$($k!“e(B bubblebabble e$B$de(B hmac (OpenSSL
e$B$K$b$”$k$,e(B)e$BEy$Ne(B
e$B%”%I%$%s$N287C$r<u$1$i$l$k!”$J$I$G$9!#e(B

e$B!!$H$3$m$G!":n6H$NCf$Ge(B

OpenSSL::Digest::Digest::new(name)

e$B$J$k%$%s%?!<%U%’!<%9$rH/8+$7$^$7$?!#e(BDigest
[email protected]$V$j$,8+6l$7$$e(B
e$B46$8$,$9$k$N$G!"Be$o$j$Ke(B OpenSSL::Digest(name) e$B$rDj5A$7$Fe(B

OpenSSL::Digest("MD5").new

e$B$H=q$1$k$h$&$K$7$F$_$^$7$?$,!"$I$&$G$7$g$&$+!#e(B

e$B!!$"$H$O!"e(B size() e$B$He(B name()
e$B$O%$%s%9%?%s%9%a%=%C%I$H$7$FB8:_$9$Y$-e(B
e$B$J$N$+$h$/$o$+$j$^$;$s$G$7$?$,!“[email protected]$r9MN8$7$F;D$7$F$”$j$^$9!#e(B

e$B!!0J>e!"$h$m$7$/$*4j$$$7$^$9!#e(B


/
/__ __ 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.rb
R ext/openssl/lib/openssl/digest.rb
M test/openssl/test_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 13 Oct 2006 12:03:37 -0000
@@ -2,6 +2,7 @@

  • $Id: ossl_digest.c,v 1.7 2006/08/31 10:27:46 matz Exp $
  • ‘OpenSSL for Ruby’ project
  • Copyright © 2001-2002 Michal R. [email protected]
    • Copyright © 2006 Akinori MUSHA [email protected]
    • All rights reserved.
      /
      /

      @@ -10,17 +11,6 @@
      */
      #include “ossl.h”

-#define GetDigest(obj, ctx) do { \

  • Data_Get_Struct(obj, EVP_MD_CTX, ctx); \
  • if (!ctx) { \
  • ossl_raise(rb_eRuntimeError, “Digest CTX wasn’t initialized!”); \
  • }
    -} while (0)
    -#define SafeGetDigest(obj, ctx) do { \
  • OSSL_Check_Kind(obj, cDigest); \
  • GetDigest(obj, ctx);
    -} while (0)

/*

  • Classes
    */
    @@ -28,267 +18,272 @@
    VALUE cDigest;
    VALUE eDigestError;

-static VALUE ossl_digest_alloc(VALUE klass);
+static ID id_evp_md, id_new;
+
+static const char *digest_names[] = {

  • “DSS”,
  • “DSS1”,
  • “MD2”,
  • “MD4”,
  • “MD5”,
  • “MDC2”,
  • “RIPEMD160”,
  • “SHA”,
  • “SHA1”,
    +#if OPENSSL_VERSION_NUMBER > 0x00908000
  • “SHA224”,
  • “SHA256”,
  • “SHA384”,
  • “SHA512”,
    +#endif
    +};

/*

    • Public
    • Digest::Base
      */
      -const EVP_MD *
      -GetDigestPtr(VALUE obj)

+static EVP_MD *
+get_digest_base_metadata(VALUE klass)
{

  • EVP_MD_CTX *ctx;
  • VALUE obj;
  • EVP_MD *md;
  • SafeGetDigest(obj, ctx);
  • if (rb_ivar_defined(klass, id_evp_md) == Qfalse) {
  •    return NULL;
    
  • }
  • return EVP_MD_CTX_md(ctx); /== ctx->digest/
    -}
  • obj = rb_ivar_get(klass, id_evp_md);

-VALUE
-ossl_digest_new(const EVP_MD *md)
-{

  • VALUE ret;
  • EVP_MD_CTX *ctx;
  • Data_Get_Struct(obj, EVP_MD, md);
  • ret = ossl_digest_alloc(cDigest);
  • GetDigest(ret, ctx);
  • EVP_MD_CTX_init(ctx);
  • EVP_DigestInit_ex(ctx, md, NULL);
  • return ret;
  • return md;
    }

-/*

    • Private
  • */
    static VALUE
    -ossl_digest_alloc(VALUE klass)
    +rb_ossl_digest_base_alloc(VALUE klass)
    {
  • EVP_MD *md;
    EVP_MD_CTX *ctx;
    VALUE obj;

  • md = get_digest_base_metadata(klass);

  • if (md == NULL) {

  •    return Data_Wrap_Struct(klass, 0, free, 0);
    
  • }

  • ctx = EVP_MD_CTX_create();

  • if (ctx == NULL)
  • ossl_raise(rb_eRuntimeError, “EVP_MD_CTX_create() failed”);
  • EVP_MD_CTX_init(ctx);
  • obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx);
  • return obj;
    }

-VALUE ossl_digest_update(VALUE, VALUE);

static VALUE
-ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
+rb_ossl_digest_base_copy(VALUE copy, VALUE obj)
{

  • EVP_MD_CTX *ctx;
  • const EVP_MD *md;
  • char *name;
  • VALUE type, data;
  • rb_scan_args(argc, argv, “11”, &type, &data);
  • StringValue(type);
  • if (!NIL_P(data)) StringValue(data);
  • name = StringValuePtr(type);
  • md = EVP_get_digestbyname(name);
  • if (!md) {
  • ossl_raise(rb_eRuntimeError, “Unsupported digest algorithm (%s).”,
    name);
  • EVP_MD *md;
  • EVP_MD_CTX *ctx1, *ctx2;
  • if (copy == obj) return copy;
  • rb_check_frozen(copy);
  • md = get_digest_base_metadata(rb_obj_class(copy));
  • if (md == NULL) {
  •    /* initialize_copy() is undefined or something */
    
  •    rb_notimplement();
    
    }
  • GetDigest(self, ctx);
  • EVP_DigestInit_ex(ctx, md, NULL);
  • if (!NIL_P(data)) return ossl_digest_update(self, data);
  • return self;
  • /* get_digest_base_metadata() may return a NULL */
  • if (md != get_digest_base_metadata(rb_obj_class(obj))) {
  • ossl_raise(rb_eTypeError, “wrong argument class”);
  • }
  • Data_Get_Struct(obj, EVP_MD_CTX, ctx1);
  • Data_Get_Struct(copy, EVP_MD_CTX, ctx2);
  • EVP_MD_CTX_copy(ctx2, ctx1);
  • return copy;
    }

static VALUE
-ossl_digest_copy(VALUE self, VALUE other)
+rb_ossl_digest_base_update(VALUE self, VALUE str)
{

  • EVP_MD_CTX *ctx1, *ctx2;
  • rb_check_frozen(self);
  • if (self == other) return self;
  • EVP_MD_CTX *ctx;
  • GetDigest(self, ctx1);
  • SafeGetDigest(other, ctx2);
  • Data_Get_Struct(self, EVP_MD_CTX, ctx);
  • if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
  • ossl_raise(eDigestError, NULL);
  • if (ctx == NULL) {
  • ossl_raise(rb_eRuntimeError, “Unsupported digest algorithm”);
    }
  • StringValue(str);
  • EVP_DigestUpdate(ctx, RSTRING_PTR(str), RSTRING_LEN(str));
  • return self;
    }

static VALUE
-ossl_digest_reset(VALUE self)
+rb_ossl_digest_base_init(int argc, VALUE *argv, VALUE self)
{

  • EVP_MD *md;
    EVP_MD_CTX *ctx;
  • VALUE arg;
  • GetDigest(self, ctx);
  • EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL);
  • md = get_digest_base_metadata(rb_obj_class(self));
  • return self;
    -}
  • if (md == NULL) {
  • ossl_raise(rb_eRuntimeError, “Unsupported digest algorithm”);
  • }

-VALUE
-ossl_digest_update(VALUE self, VALUE data)
-{

  • EVP_MD_CTX *ctx;
  • Data_Get_Struct(self, EVP_MD_CTX, ctx);
  • StringValue(data);
  • GetDigest(self, ctx);
  • EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
  • EVP_DigestInit_ex(ctx, md, NULL);

  • rb_scan_args(argc, argv, “01”, &arg);

  • if (!NIL_P(arg)) rb_ossl_digest_base_update(self, arg);

    return self;
    }

-static void
-digest_final(EVP_MD_CTX *ctx, char **buf, int *buf_len)
+static VALUE
+rb_ossl_digest_base_digest(VALUE self)
{

  • EVP_MD_CTX final;
  • EVP_MD *md;
  • EVP_MD_CTX *ctx1, *ctx2;
  • size_t ctx_size;
  • VALUE str;
  • 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”);
  • md = get_digest_base_metadata(rb_obj_class(self));
  • if (md == NULL) {
  •    /* subclasses must define update() */
    
  •    rb_notimplement();
    
    }
  • EVP_DigestFinal_ex(&final, *buf, buf_len);
  • EVP_MD_CTX_cleanup(&final);
    -}

-static VALUE
-ossl_digest_digest(VALUE self)
-{

  • EVP_MD_CTX *ctx;
  • char *buf;
  • int buf_len;
  • VALUE digest;
  • GetDigest(self, ctx);
  • digest_final(ctx, &buf, &buf_len);
  • digest = ossl_buf2str(buf, buf_len);
  • return digest;
  • Data_Get_Struct(self, EVP_MD_CTX, ctx1);
  • ctx2 = EVP_MD_CTX_create();
  • EVP_MD_CTX_copy(ctx2, ctx1);
  • str = rb_str_new(0, EVP_MD_CTX_size(ctx2));
  • EVP_DigestFinal_ex(ctx2, RSTRING_PTR(str), NULL);
  • EVP_MD_CTX_destroy(ctx2);
  • return str;
    }

static VALUE
-ossl_digest_hexdigest(VALUE self)
+rb_ossl_digest_base_name(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”);
  • EVP_MD *md;
  • md = get_digest_base_metadata(rb_obj_class(self));
  • if (md == NULL) {
  •    /* subclasses must define update() */
    
  •    rb_notimplement();
    
    }
  • OPENSSL_free(buf);

  • hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);

  • return hexdigest;

  • return rb_str_new2(EVP_MD_name(md));
    }

static VALUE
-ossl_digest_s_digest(VALUE klass, VALUE str, VALUE data)
+rb_ossl_digest_base_size(VALUE self)
{

  • VALUE obj = rb_class_new_instance(1, &str, klass);
  • EVP_MD *md;
  • md = get_digest_base_metadata(rb_obj_class(self));
  • ossl_digest_update(obj, data);
  • if (md == NULL) {
  •    /* subclasses must define update() */
    
  •    rb_notimplement();
    
  • }
  • return ossl_digest_digest(obj);
  • return INT2NUM(EVP_MD_size(md));
    }

static VALUE
-ossl_digest_s_hexdigest(VALUE klass, VALUE str, VALUE data)
+ossl_digest_class_by_name(const char *name)
{

  • VALUE obj = rb_class_new_instance(1, &str, klass);
  • VALUE klass = rb_const_get(mDigest, rb_intern(name));
  • ossl_digest_update(obj, data);
  • if (klass == Qnil) {
  • ossl_raise(rb_eRuntimeError, “Unsupported digest algorithm”);
  • }
  • return ossl_digest_hexdigest(obj);
  • return klass;
    }

static VALUE
-ossl_digest_equal(VALUE self, VALUE other)
+rb_ossl_s_Digest(VALUE klass, VALUE name)
{

  • EVP_MD_CTX *ctx;
  • VALUE str1, str2;
  • StringValue(name);
  • 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 ossl_digest_class_by_name(RSTRING_PTR(name));
    }

-static VALUE
-ossl_digest_name(VALUE self)
+const EVP_MD *
+GetDigestPtr(VALUE obj)
{

  • EVP_MD_CTX *ctx;
  • EVP_MD *md = get_digest_base_metadata(rb_obj_class(obj));
  • GetDigest(self, ctx);
  • if (md == NULL) {
  •    ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm");
    
  • }
  • return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
  • return md;
    }

-static VALUE
-ossl_digest_size(VALUE self)
+VALUE
+ossl_digest_new(const EVP_MD *md)
{

  • EVP_MD_CTX *ctx;
  • GetDigest(self, ctx);
  • VALUE klass = ossl_digest_class_by_name(EVP_MD_name(md));
  • return INT2NUM(EVP_MD_CTX_size(ctx));
  • return rb_funcall(klass, id_new, 0);
    }

-/*

    • INIT
  • */
    void
    -Init_ossl_digest()
    +Init_ossl_digest(void)
    {
  • int i;
  • VALUE klass;
  • VALUE rb_cDigest_Base;
  • id_evp_md = rb_intern(“evp_md”);
  • id_new = rb_intern(“new”);
  • rb_define_module_function(mOSSL, “Digest”, rb_ossl_s_Digest, 1);
  • mDigest = rb_define_module_under(mOSSL, “Digest”);
  • eDigestError = rb_define_class_under(mDigest, “DigestError”,
    eOSSLError);
  • cDigest = rb_define_class_under(mDigest, “Digest”, rb_cObject);
  • 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, “update”, ossl_digest_update, 1);
  • rb_define_alias(cDigest, “<<”, “update”);
  • rb_define_method(cDigest, “==”, ossl_digest_equal, 1);
  • rb_define_method(cDigest, “name”, ossl_digest_name, 0);
  • rb_define_method(cDigest, “size”, ossl_digest_size, 0);
  • rb_require(“digest”);
  • rb_cDigest_Base = rb_path2class(“Digest::Base”);
  • for (i = 0; i < sizeof(digest_names); i++) {
  •    const char *name = digest_names[i];
    
  •    const EVP_MD *md = EVP_get_digestbyname(name);
    
  •    if (md == NULL)
    
  •        continue;
    
  •    klass = rb_define_class_under(mDigest, name, rb_cDigest_Base);
    
  •    rb_ivar_set(klass, id_evp_md, Data_Wrap_Struct(rb_cObject, 0, 
    

0, (void *)md));
+

  •    rb_define_const(klass, "DIGEST_LENGTH", 
    

INT2NUM(EVP_MD_size(md)));

  •    rb_define_const(klass, "BLOCK_LENGTH", 
    

INT2NUM(EVP_MD_block_size(md)));
+

  •    rb_define_alloc_func(klass, rb_ossl_digest_base_alloc);
    
  •    rb_define_method(klass, "initialize", rb_ossl_digest_base_init, 
    

-1);

  •    rb_define_method(klass, "initialize_copy", 
    

rb_ossl_digest_base_copy, 1);

  •    rb_define_method(klass, "update", rb_ossl_digest_base_update, 
    

1);

  •    rb_define_method(klass, "digest", rb_ossl_digest_base_digest, 
    

0);
+

  •    rb_define_method(klass, "name", rb_ossl_digest_base_name, 0);
    
  •    rb_define_method(klass, "size", rb_ossl_digest_base_size, 0);
    
  •    rb_define_method(klass, "length", rb_ossl_digest_base_size, 0);
    
  • }
    }
    Index: ext/openssl/lib/openssl.rb
    ===================================================================
    RCS file: /src/ruby/ext/openssl/lib/openssl.rb,v
    retrieving revision 1.1
    diff -u -r1.1 openssl.rb
    — ext/openssl/lib/openssl.rb 23 Jul 2003 16:11:29 -0000 1.1
    +++ ext/openssl/lib/openssl.rb 13 Oct 2006 12:03:37 -0000
    @@ -18,7 +18,6 @@

require ‘openssl/bn’
require ‘openssl/cipher’
-require ‘openssl/digest’
require ‘openssl/ssl’
require ‘openssl/x509’

Index: ext/openssl/lib/openssl/digest.rb

RCS file: ext/openssl/lib/openssl/digest.rb
diff -N ext/openssl/lib/openssl/digest.rb
— ext/openssl/lib/openssl/digest.rb 8 May 2006 00:11:59 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,49 +0,0 @@
-=begin
-= $RCSfile: digest.rb,v $ – Ruby-space predefined Digest subclasses

-= Info

  • ‘OpenSSL for Ruby 2’ project
  • Copyright © 2002 Michal R. [email protected]
  • All rights reserved.

-= Licence

  • This program is licenced under the same licence as Ruby.
  • (See the file ‘LICENCE’.)

-= Version

  • $Id: digest.rb,v 1.3 2006/05/08 00:11:59 gotoyuzo Exp $
    -=end

-##
-# Should we care what if somebody require this file directly?
-#require ‘openssl’

-module OpenSSL

  • module Digest
  • alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
  • if OPENSSL_VERSION_NUMBER > 0x00908000
  •  alg += %w(SHA224 SHA256 SHA384 SHA512)
    
  • end
  • alg.each{|name|
  •  klass = Class.new(Digest){
    
  •    define_method(:initialize){|*data|
    
  •      if data.length > 1
    
  •        raise ArgumentError,
    
  •          "wrong number of arguments (#{data.length} for 1)"
    
  •      end
    
  •      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)
    
  • }
  • end # Digest
    -end # OpenSSL

Index: test/openssl/test_digest.rb

RCS file: /src/ruby/test/openssl/test_digest.rb,v
retrieving revision 1.3
diff -u -r1.3 test_digest.rb
— test/openssl/test_digest.rb 8 May 2006 00:12:00 -0000 1.3
+++ test/openssl/test_digest.rb 13 Oct 2006 12:03:38 -0000
@@ -9,7 +9,7 @@

class OpenSSL::TestDigest < Test::Unit::TestCase
def setup

  • @d1 = OpenSSL::Digest::Digest::new(“MD5”)
  • @d1 = OpenSSL::Digest(“MD5”).new
    @d2 = OpenSSL::Digest::MD5.new
    @md = Digest::MD5.new
    @data = “DATA”

At Fri, 13 Oct 2006 21:25:14 +0900,
I wrote:

e$B!!$"$H$O!"e(B size() e$B$He(B name() e$B$O%$%s%9%?%s%9%a%=%C%I$H$7$FB8:_$9$Y$-e(B
e$B$J$N$+$h$/$o$+$j$^$;$s$G$7$?$,!“[email protected]$r9MN8$7$F;D$7$F$”$j$^$9!#e(B

e$B!!%Q%i%a!<%?$r<h$k%"%k%4%j%:%`$N>l9g!"%/%i%9$G$O$J$/%$%s%9%?%s%9$Ge(B
e$B;}$?$J$$$H%@%a$G$9$M!#e(BDigest e$BA4BN$G:NMQ$7$h$&$H;W$$$^$9!#e(B


/
/__ __ 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”

In message [email protected],
`“Akinori MUSHA” removed_emai[email protected]’ wrote:

(e$B<g$Ke(B)e$B$f$>$5$se(B

e$B$*$R$5$7$V$j$G$9!#e(B

e$B!!%a%j%C%H$H$7$F$O!“6l$b$J$/e(BAPIe$B$,E}0l$5$l$k!“e(B #file() e$B$J$I$NDI2Ce(B
e$B%a%=%C%I$,;H$($k!“e(B bubblebabble e$B$de(B hmac (OpenSSL e$B$K$b$”$k$,e(B)e$BEy$Ne(B
e$B%”%I%$%s$N287C$r<u$1$i$l$k!”$J$I$G$9!#e(B

e$BL\E*$K$O;[email protected]$7$^$9!#e(B

e$B:G6a$Ne(Bext/digeste$B$NJQ99$rDI$C$+$1$F$$$^$;$s$G$7$?$,!“FbIt$N<Be(B
e$BAu$K4X$o$i$J$$5!G=$G$”$l$P!"Nc$($Pe(B::Digest::Utilitiese$B$_$?$$e(B
e$B$J%b%8%e!<%k$rMQ0U$7$F!"e(B

class OpenSSL::Digest::Digest
class <<self
include ::Digest::Utilities::SingletonMethods
end
include ::Digest::Utilities::InstanceMethods
end

e$B$3$s$JIw$K$G$-$k$H3Z$+$J$H$b;W$$$^$7$?!#e(B

e$B!!$H$3$m$G!":n6H$NCf$Ge(B

OpenSSL::Digest::Digest::new(name)

e$B$J$k%$%s%?!<%U%’!<%9$rH/8+$7$^$7$?!#e(BDigest [email protected]$V$j$,8+6l$7$$e(B
e$B46$8$,$9$k$N$G!"Be$o$j$Ke(B OpenSSL::Digest(name) e$B$rDj5A$7$Fe(B

OpenSSL::Digest(“MD5”).new

e$B$H=q$1$k$h$&$K$7$F$_$^$7$?$,!"$I$&$G$7$g$&$+!#e(B

e$BL>A0$,8+6l$7$$$N$O$^$C$?$/F146$G$9!#8=:_$Ne(B
OpenSSL::Digest::Digeste$B%/%i%9$re(BOpenSSL::Digeste$B$H$$$&L>A0$K$7e(B
e$B$F!"e(BOpenSSL::Digest.new(name)e$B$K$7$h$&$+$H9M$($F$O$$$^$7$?!#e(B

e$B$[$+$K$be(BOpenSSL::PKey::PKeye$B$J$s$+$b$"$k$N$G!"e(B1.9e$B$G$O$^$H$ae(B

e$B$FJQ99$9$k$3$H$r8!F$$7$^$9!#e(B

e$BL>A0$O$5$F$*$-!“e(B[ruby-dev:29651]e$B$N%Q%C%A$G$O%”%k%4%j%:%`Kh$Ke(B
e$B%5%V%/%i%9$r:[email protected]$7!"%5%V%/%i%9Kh$K8DJL$K%a%=%C%I$rDj5A$7$F$$e(B
e$B$k$N$,<u$1F~$l$,$?$$$G$9!#e(B

OpenSSL::Digest::Digeste$B$Oe(BOpenSSLe$B%i%$%V%i%j$KDj5A$5$l$F$$$kG$e(B
e$B0U$N%"%k%4%j%:%`L>$G=i4|2=$G$-$k$h$&$K$J$C$F$$$^$9!#Nc$($P!"e(B

OpenSSL::Digest::Digest.new(“SHA256”)

e$B$G;XDj$7$F$$$kL>A0$Oe(BEVP_MDe$B9=B$BN$r8!:w$9$k$?$a$KMxMQ$7$F$$$ke(B
e$B$K2a$.$^$;$s!#$=$N$*$+$2$Ge(BOpenSSL::Digest::SHA256e$B$rDI2C$9$ke(B
e$B0JA0$+$ie(BOpenSSL 0.9.8e$B$r;H$C$F%S%k%I$7$F$$$l$P!"$3$N%"%k%4%je(B
e$B%:%`$r;H$&$3$H$,$G$-$F$$$^$7$?!#e(B

e$B$^$?!“e(BDSS1e$B$He(BSHA1e$B$N$h$&$K!”%"%k%4%j%:%`[email protected]$1$I8x3+800E9fe(B
e$B$N=pL>$N%U%)!<%^%C%HKh$K8DJL$KL>A0$,IU$1$F$"$k$H$$$&e(BOpenSSL
e$BFCM-$N;v>p$b$"$C$F!"$3$l$i$,:#8e$bA}$([email protected][email protected]$l$J$$$Ne(B
e$B$G!“e(BRubye$B%l%Y%k$G$OCN$i$J$$L>A0$G$”$C$F$b=i4|2=$G$-$kM>CO$O;De(B
e$B$7$F$*$-$?$$$H;W$$$^$9!#e(B

At Sat, 14 Oct 2006 11:34:50 +0900,
GOTOU Yuuzou wrote:

class OpenSSL::Digest::Digest
class <<self
include ::Digest::Utilities::SingletonMethods
end
include ::Digest::Utilities::InstanceMethods
end

e$B$3$s$JIw$K$G$-$k$H3Z$+$J$H$b;W$$$^$7$?!#e(B

e$B!!3N$+$Ke(B mix-in e$B$K$7$?J}$,H~$7$$$G$9$M!#8!F$$7$^$9!#e(B

e$B!!:#$$$m$$$mG:$s$G$$$k$N$O!"%-!<$d%O%C%7%eD9$J$I$N%Q%i%a!<%?$re(B
e$B<h$k%"%k%4%j%:%`$r$I$&07$&$+$G$9!#e(B

e$B!!$?$H$($P!"$"$k%a%=%C%I$,%O%C%7%e%"%k%4%j%:%`$N;XDj$r<u$1$k$He(B
e$B$7$?$H$-$r9M$($^$9!#e(B

e$B!!$^$:!"e(B

    check_auth(cookie, "MD5")

e$B$HL>>N$rJ8;zNs$GEO$9J}K!$G$O!"%Q%i%a!<%?$N;XDj$,:$Fq$G$9!#e(B

    check_auth(cookie, "HMAC;hash=MD5;key=blahblahblah")

e$B$He(B DBI
e$B$_$?$$$J46$8$K$7$?$N$G$O!";XDj$b%Q!<%9$bLLE][email protected]!#e(B

e$B!!$^$?!"e(B

    check_auth(cookie, Digest::MD5)

e$B$N$h$&$K%/%i%9%*%V%8%’%/%H$rEO$9J}K!$,$"$j$^$9$,!"%Q%i%a!<%?IU$-e(B
e$B%"%k%4%j%:%`$N>l9g!"%Q%i%a!<%?e(B(e$B$NAH9g$;e(B)e$B$4$H$K8GM-$N%/%i%9$r:n$ke(B
e$B$N$+$H$$$&$Hm4m0$7$^$9!#e(B(digest/hmac e$B$G0lEY$d$C$F$_$^$7$?e(B)

e$B!!$+$H$$$C$F!"e(B

    check_auth(cookie, Digest::Tiger, 160)

e$B$N$h$&$K%Q%i%a!<%?$rJB$Y$FEO$9$N$G$O!V7W;;4o!W$r$R$H$^$H$^$j$Ge(B
e$B;XDj$G$-$F$$$J$$$N$GH~$7$/$J$$!#e(B

e$B!!7W;;4o$rEO$9!"$H$$$&0UL#$G$Oe(B

    check_auth(cookie, Digest::Tiger.new(160))

e$B$H$$$&$N$,$R$H$D$N2r7h:v$G$"$j!“8=;[email protected]$Ne(B digest
e$B$O$3$N$h$&$J7A$re(B
e$BA[Dj$7$F$$$^$9$,!”$$$/$D$+LdBj$b$"$j$^$9!#e(B

e$B!&F1;~$KJ#?t$N7W;;4o%$%s%9%?%s%9$rI,MW$H$9$k>l9g!“e(B clone()
e$B$7$Fe(B
e$B$b$i$&$N$+!)e(B
e$B!&>uBV$N$”$k$b$N$r$d$j$H$j$9$k$N$O5$;}$A0-$$!#;HMQA0!&;HMQ8e$Ke(B
reset() [email protected]$$NM-L5$J$I$,5$$K$J$k!#e(B

e$B!!$D$^$j!"EO$9$Y$-$J$N$O7W;;4o$=$N$b$N$G$O$J$/$F!“7W;;[email protected]@.e(B
e$BJ}K!$G$”$k$H$$$&$3$H$K$J$j$^$9!#e(B

e$B!!$H$$$&$3$H$O!"@h$[$I$N%/%i%9%*%V%8%’%/%H$rEO$9J}K!$,$$$A$P$se(B
e$B6a$=$&$G$9!#$"$k$Y$-;Q$Oe(B

e$B!&e(BDigest e$B<BAu%/%i%9$Oe(B new() e$B$G%Q%i%a!<%?$r<u$1<h$j!“e(B
factory
e$B%%V%8%’%/%[email protected]@.$9$k!#e(B
e$B!&e(Bfactory
e$B%
%V%8%’%/%H$O<[email protected]@.;~$K;XDj$5$l$?%”%k%4%j%:%`$He(B
e$B%Q%i%a!<%?$K1h$C$?!V7W;;[email protected]@.$9$kG=NOe(B(e$B%a%=%C%Ie(B)e$B$r;}$D!#e(B

e$B$H$$$C$?7A$G$7$g$&$+!#$G$b!"$^$8$a$K$=$&$7$F$7$^$&$H$"$s$^$je(B
e$B;H$$$d$9$$46$8$O$7$J$$$G$9$M!#e(B

    tiger160 = Digest::Tiger.new(160)
    hash = tiger160.create()
    hash.update(data)
    digest = hash.digest

JCE e$B$Ne(B Mac e$B%/%i%9$J$I$O$3$s$J46$8$N%$%s%?!<%U%’!<%9$G$9$,!"e(B
e$B2L$?$7$Fe(B Ruby e$B$K%^%C%A$9$k$N$+$I$&$+!#e(B

e$B!!%7%g!<%H%+%C%H%a%=%C%I$r$$$m$$$m:n$l$PC;$/=q$/J}K!$rDs6!$G$-$ke(B
e$B$G$7$g$&$,!">iD9$G9=B$$,$D$+$_$K$/$$$b$N$K$J$C$F$7$^$$$=$&$G$9!#e(B

e$B!!$=$b$=$b$NOC$H$7$F$9$Y$F$N%O%C%7%e4X?t$N%$%s%?!<%U%’!<%9$rE}0le(B
e$B$9$kI,MW$,$"$k$N$+$H$$$&5?Ld$O9M$($i$l$^$9!#e(BMD5 e$B$^$?$Oe(B
HMAC-MD5e$B!“e(B
e$B$J$I$H$$$&A*Br$,<B:]$”$k$N$+$I$&$+J,$+$j$^$;$s$7!#e(B

[email protected]!“8=<B$rM=B,$9$k$N$OFq$7$$$N$G!”$b$&>/$7M}A[$K$D$$$F9M$($Fe(B
e$B$_$?$$$G$9!#Ey$7$/Fq$7$$$N$J$i!#e(B

e$BL>A0$,8+6l$7$$$N$O$^$C$?$/F146$G$9!#8=:_$Ne(B
OpenSSL::Digest::Digeste$B%/%i%9$re(BOpenSSL::Digeste$B$H$$$&L>A0$K$7e(B
e$B$F!"e(BOpenSSL::Digest.new(name)e$B$K$7$h$&$+$H9M$($F$O$$$^$7$?!#e(B

e$B$[$+$K$be(BOpenSSL::PKey::PKeye$B$J$s$+$b$"$k$N$G!"e(B1.9e$B$G$O$^$H$ae(B

e$B$FJQ99$9$k$3$H$r8!F$$7$^$9!#e(B

e$B!!$<$R$$$$7A$K$7$?$$$G$9$M!#e(B

e$BL>A0$O$5$F$*$-!“e(B[ruby-dev:29651]e$B$N%Q%C%A$G$O%”%k%4%j%:%`Kh$Ke(B
e$B%5%V%/%i%9$r:[email protected]$7!"%5%V%/%i%9Kh$K8DJL$K%a%=%C%I$rDj5A$7$F$$e(B
e$B$k$N$,<u$1F~$l$,$?$$$G$9!#e(B

OpenSSL::Digest::Digeste$B$Oe(BOpenSSLe$B%i%$%V%i%j$KDj5A$5$l$F$$$kG$e(B
e$B0U$N%"%k%4%j%:%`L>$G=i4|2=$G$-$k$h$&$K$J$C$F$$$^$9!#Nc$($P!"e(B

e$B!!$J$k$[$I!#$"$/$^$GF0E*$JL>A0;XDj$,<g$G!"8DJL%/%i%9$O=>$G$9$+!#e(B
e$BG0F,$K$*$$$F$$$8$C$F$_$^$9!#e(B


/
/__ __ 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”

(e$B<g$Ke(B)e$B$f$>$5$se(B

e$B!!e(BOpenSSL::Digest::Digest e$B%/%i%9$K!"[email protected]$Ne(B Digest::Class
e$B$r7Q>5e(B
e$B$5$;$F$
$^$7$?!#4pK\E*$K%$%s%?!<%U%’!<%9$NHs8_49$O$J$/!"=c?h$Ke(B
e$B<BAu$N6&M-$r9T$&$b$N$G$9!#e(B

e$B!!M#0l!"e(B == e$B$GJ8;zNs$rM?$($i$l$?:]$O>o$Ke(B to_s (hexdigest)
e$B$NCM$He(B
e$BHf3S$5$l!"D9$5$r8+$Fe(B digest() e$B$^$?$Oe(B hexdigest()
e$B$NCM$HHf3S$9$ke(B
e$B5!G=$O$J$/$J$C$F$$$^$9!#e(BDigest
e$B%*%V%8%’%/%H$,M?$($i$l$?>l9g$Oe(B
digest() e$B$N7k2LF1;N$rHf3S$7$^$9!#e(B

e$B!!$=$N$[$+$O$9$Y$F5!G=DI2C$G$9!#2~$a$F8!F$$r$*4j$$$7$^$9!#e(B


/
/__ __ 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)
    
    }

In article [email protected],
“Akinori MUSHA” [email protected] writes:

e$B$N$h$&$K%/%i%9%*%V%8%’%/%H$rEO$9J}K!$,$"$j$^$9$,!"%Q%i%a!<%?IU$-e(B
e$B!!7W;;4o$rEO$9!"$H$$$&0UL#$G$Oe(B

e$B!!$D$^$j!"EO$9$Y$-$J$N$O7W;;4o$=$N$b$N$G$O$J$/$F!“7W;;[email protected]@.e(B
e$BJ}K!$G$”$k$H$$$&$3$H$K$J$j$^$9!#e(B

e$B!!$H$$$&$3$H$O!"@h$[$I$N%/%i%9%*%V%8%’%/%H$rEO$9J}K!$,$$$A$P$se(B
e$B6a$=$&$G$9!#$"$k$Y$-;Q$Oe(B

e$B!&e(BDigest e$B<BAu%/%i%9$Oe(B new() e$B$G%Q%i%a!<%?$r<u$1<h$j!“e(B factory
e$B%%V%8%’%/%[email protected]@.$9$k!#e(B
e$B!&e(Bfactory e$B%
%V%8%’%/%H$O<[email protected]@.;~$K;XDj$5$l$?%”%k%4%j%:%`$He(B
e$B%Q%i%a!<%?$K1h$C$?!V7W;;[email protected]@.$9$kG=NOe(B(e$B%a%=%C%Ie(B)e$B$r;}$D!#e(B

e$B$=$N%a%=%C%I$R$H$D$K4X$7$FB?BV$G$"$l$P$$$$$N$G$"$l$P!"$=$N%ae(B
e$B%=%C%I$NL>A0$re(B call e$B$K$7$F!"e(Bfactory
[email protected]@.$K$O0z?t$N$J$$e(B
lambda e$B$r;H$($P$$$$$N$G$Oe(B?

e$B%Q%i%a!<%?$r$H$i$J$$%"%k%4%j%:%`$KBP1~$9$k%/%i%9$K$D$$$F$O%/e(B
e$B%i%9%%V%8%’%/%H<+?H$,e(B call e$B$r;}$D$3$H$K$9$l$P%/%i%9%%V%8%'e(B
e$B%/%H<+?H$,e(B factory e$B$H$b?6$kIq$($^$9$7!#e(B

e$B$H$$$C$?7A$G$7$g$&$+!#$G$b!"$^$8$a$K$=$&$7$F$7$^$&$H$"$s$^$je(B
e$B;H$$$d$9$$46$8$O$7$J$$$G$9$M!#e(B

    tiger160 = Digest::Tiger.new(160)
    hash = tiger160.create()
    hash.update(data)
    digest = hash.digest

JCE e$B$Ne(B Mac e$B%/%i%9$J$I$O$3$s$J46$8$N%$%s%?!<%U%’!<%9$G$9$,!"e(B
e$B2L$?$7$Fe(B Ruby e$B$K%^%C%A$9$k$N$+$I$&$+!#e(B

class << Digest::SHA256; alias call new; end
class << Digest::SHA512; alias call new; end

e$B$H$7$F$*$$$F!"e(B

p Digest::Tiger.new(160).update(data).digest
p Digest::SHA256.new.update(data).digest

e$B$HD>@;H$C$F$b$$$$$7!"e(B

p lambda { Digest::Tiger.new(160) }.call.update(data).digest
p Digest::SHA256.call.update(data).digest

e$B$He(B call e$B$G8F$Y$ke(B factory
e$B7PM3$G$d$C$F$b$$$$$H$$$&$3$H$G!"e(B

check_auth(cookie, lambda { Digest::Tiger.new(160) })
check_auth(cookie, Digest::SHA256)

e$B$H$$$&$h$&$K%"%k%4%j%:%`$r<u$1<h$k%a%=%C%I$K$Oe(B lambda e$B$J$$$7e(B
e$B%/%i%9$r;XDj$7!">l9g$K$h$C$F$Oe(B

check_auth(cookie) { Digest::Tiger.new(160) }
check_auth(cookie) { Digest::SHA256.new }

e$B$H%V%m%C%/$r;H$$$?$/$J$k$+$b$7$l$J$$!"$H$+!#e(B

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs