mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/digest, test/digest/test_digest.rb: Merge from trunk:
- Introduce versioning in Digest::Base API, and prefix C constants with RUBY_ and C type names with rb_ to avoid name clash in writing extensions. - Introduce Digest::Class and Digest::Instance for ease of implementing subclasses and add-ons. - Digest::Instance module requires and assumes that any instance be resettable and clonable. An instance method #new() is added so digest instances work just like digest classes. - The constructor does no longer take an initial string to feed; digest() and hexdigest() now do, instead. This allows digest classes to take their own hashing parameters. - Make some changes to digest() and hexdigest() class methods, which now take extra arguments, which are passed through to the constructor in an internal call. - Add #digest_length/size/length() and #block_length(), - Add the Digest::SHA2 class to wrap up SHA2 variants: SHA256, SHA384 and SHA512, hoping this module would make a decent example of a digest subclass written in Ruby. - Rip BubbleBabble support out of the base class and have a separate module named digest/bubblebabble. - Remove RD documents in favor of newly written and embedded RDoc documentation. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@11223 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0bdf887afc
commit
817afbd987
14 changed files with 883 additions and 587 deletions
26
ChangeLog
26
ChangeLog
|
@ -1,3 +1,29 @@
|
|||
Wed Oct 25 17:23:28 2006 Akinori MUSHA <knu@iDaemons.org>
|
||||
|
||||
* ext/digest, test/digest/test_digest.rb: Merge from trunk:
|
||||
- Introduce versioning in Digest::Base API, and prefix C
|
||||
constants with RUBY_ and C type names with rb_ to avoid name
|
||||
clash in writing extensions.
|
||||
- Introduce Digest::Class and Digest::Instance for ease of
|
||||
implementing subclasses and add-ons.
|
||||
- Digest::Instance module requires and assumes that any instance
|
||||
be resettable and clonable. An instance method #new() is
|
||||
added so digest instances work just like digest classes.
|
||||
- The constructor does no longer take an initial string to feed;
|
||||
digest() and hexdigest() now do, instead. This allows digest
|
||||
classes to take their own hashing parameters.
|
||||
- Make some changes to digest() and hexdigest() class methods,
|
||||
which now take extra arguments, which are passed through to
|
||||
the constructor in an internal call.
|
||||
- Add #digest_length/size/length() and #block_length(),
|
||||
- Add the Digest::SHA2 class to wrap up SHA2 variants: SHA256,
|
||||
SHA384 and SHA512, hoping this module would make a decent
|
||||
example of a digest subclass written in Ruby.
|
||||
- Rip BubbleBabble support out of the base class and have a
|
||||
separate module named digest/bubblebabble.
|
||||
- Remove RD documents in favor of newly written and embedded
|
||||
RDoc documentation.
|
||||
|
||||
Wed Oct 25 08:03:23 2006 Tadayoshi Funaba <tadf@dotrb.org>
|
||||
|
||||
* lib/date/format.rb: updated based on date2 3.9.6.
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
Makefile
|
||||
mkmf.log
|
||||
*.def
|
||||
extconf.h
|
||||
|
|
|
@ -15,32 +15,24 @@
|
|||
|
||||
#include "digest.h"
|
||||
|
||||
static VALUE mDigest, cDigest_Base;
|
||||
static ID id_metadata, id_new, id_initialize, id_update, id_digest;
|
||||
static VALUE rb_mDigest;
|
||||
static VALUE rb_mDigest_Instance;
|
||||
static VALUE rb_cDigest_Class;
|
||||
static VALUE rb_cDigest_Base;
|
||||
|
||||
static ID id_reset, id_update, id_finish, id_digest, id_hexdigest, id_digest_length;
|
||||
static ID id_metadata;
|
||||
|
||||
RUBY_EXTERN void Init_digest_base(void);
|
||||
|
||||
/*
|
||||
* Digest::Base
|
||||
* Document-module: Digest
|
||||
*
|
||||
* This module provides a framework for message digest libraries.
|
||||
*/
|
||||
|
||||
static algo_t *
|
||||
get_digest_base_metadata(VALUE klass)
|
||||
{
|
||||
VALUE obj;
|
||||
algo_t *algo;
|
||||
|
||||
if (rb_ivar_defined(klass, id_metadata) == Qfalse) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj = rb_ivar_get(klass, id_metadata);
|
||||
|
||||
Data_Get_Struct(obj, algo_t, algo);
|
||||
|
||||
return algo;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
hexdigest_str_new(VALUE str_digest)
|
||||
hexencode_str_new(VALUE str_digest)
|
||||
{
|
||||
char *digest;
|
||||
size_t digest_len;
|
||||
|
@ -72,85 +64,405 @@ hexdigest_str_new(VALUE str_digest)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Digest.hexencode(string) -> hexencoded_string
|
||||
*
|
||||
* Generates a hex-encoded version of a given _string_.
|
||||
*/
|
||||
static VALUE
|
||||
bubblebabble_str_new(VALUE str_digest)
|
||||
rb_digest_s_hexencode(VALUE klass, VALUE str)
|
||||
{
|
||||
return hexencode_str_new(str);
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-module: Digest::Instance
|
||||
*
|
||||
* This module provides instance methods for a digest implementation
|
||||
* object to calculate message digest values.
|
||||
*/
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.update(string) -> digest_obj
|
||||
* digest_obj << string -> digest_obj
|
||||
*
|
||||
* Updates the digest using a given _string_ and returns self.
|
||||
*
|
||||
* The update() method and the left-shift operator are overridden by
|
||||
* each implementation subclass. (One should be an alias for the
|
||||
* other)
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_update(VALUE self, VALUE str)
|
||||
{
|
||||
rb_raise(rb_eRuntimeError, "%s does not implement update()", rb_inspect(self));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.instance_eval { finish } -> digest_obj
|
||||
*
|
||||
* Finishes the digest and returns the resulting hash value.
|
||||
*
|
||||
* This method is overridden by each implementation subclass and often
|
||||
* made private, because some of those subclasses may leave internal
|
||||
* data uninitialized. Do not call this method from outside. Use
|
||||
* #digest!() instead, which ensures that internal data be reset for
|
||||
* security reasons.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_finish(VALUE self)
|
||||
{
|
||||
rb_raise(rb_eRuntimeError, "%s does not implement finish()", rb_inspect(self));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.reset -> digest_obj
|
||||
*
|
||||
* Resets the digest to the initial state and returns self.
|
||||
*
|
||||
* This method is overridden by each implementation subclass.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_reset(VALUE self)
|
||||
{
|
||||
rb_raise(rb_eRuntimeError, "%s does not implement reset()", rb_inspect(self));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.new -> another_digest_obj
|
||||
*
|
||||
* Returns a new, initialized copy of the digest object. Equivalent
|
||||
* to digest_obj.clone().reset().
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_new(VALUE self)
|
||||
{
|
||||
VALUE clone = rb_obj_clone(self);
|
||||
rb_funcall(clone, id_reset, 0);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.digest -> string
|
||||
* digest_obj.digest(string) -> string
|
||||
*
|
||||
* If none is given, returns the resulting hash value of the digest,
|
||||
* keeping the digest's state.
|
||||
*
|
||||
* If a _string_ is given, returns the hash value for the given
|
||||
* _string_, resetting the digest to the initial state before and
|
||||
* after the process.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_digest(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE str, value;
|
||||
|
||||
if (rb_scan_args(argc, argv, "01", &str) > 0) {
|
||||
rb_funcall(self, id_reset, 0);
|
||||
rb_funcall(self, id_update, 1, str);
|
||||
value = rb_funcall(self, id_finish, 0);
|
||||
rb_funcall(self, id_reset, 0);
|
||||
} else {
|
||||
VALUE clone = rb_obj_clone(self);
|
||||
|
||||
value = rb_funcall(clone, id_finish, 0);
|
||||
rb_funcall(clone, id_reset, 0);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.digest! -> string
|
||||
*
|
||||
* Returns the resulting hash value and resets the digest to the
|
||||
* initial state.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_digest_bang(VALUE self)
|
||||
{
|
||||
VALUE value = rb_funcall(self, id_finish, 0);
|
||||
rb_funcall(self, id_reset, 0);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.hexdigest -> string
|
||||
* digest_obj.hexdigest(string) -> string
|
||||
*
|
||||
* If none is given, returns the resulting hash value of the digest in
|
||||
* a hex-encoded form, keeping the digest's state.
|
||||
*
|
||||
* If a _string_ is given, returns the hash value for the given
|
||||
* _string_ in a hex-encoded form, resetting the digest to the initial
|
||||
* state before and after the process.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_hexdigest(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE str, value;
|
||||
|
||||
if (rb_scan_args(argc, argv, "01", &str) > 0) {
|
||||
rb_funcall(self, id_reset, 0);
|
||||
rb_funcall(self, id_update, 1, str);
|
||||
value = rb_funcall(self, id_finish, 0);
|
||||
rb_funcall(self, id_reset, 0);
|
||||
} else {
|
||||
VALUE clone = rb_obj_clone(self);
|
||||
|
||||
value = rb_funcall(clone, id_finish, 0);
|
||||
rb_funcall(clone, id_reset, 0);
|
||||
}
|
||||
|
||||
return hexencode_str_new(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.hexdigest! -> string
|
||||
*
|
||||
* Returns the resulting hash value and resets the digest to the
|
||||
* initial state.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_hexdigest_bang(VALUE self)
|
||||
{
|
||||
VALUE value = rb_funcall(self, id_finish, 0);
|
||||
rb_funcall(self, id_reset, 0);
|
||||
|
||||
return hexencode_str_new(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.to_s -> string
|
||||
*
|
||||
* Returns digest_obj.hexdigest().
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_to_s(VALUE self)
|
||||
{
|
||||
return rb_funcall(self, id_hexdigest, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.inspect -> string
|
||||
*
|
||||
* Creates a printable version of the digest object.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_inspect(VALUE self)
|
||||
{
|
||||
char *digest;
|
||||
size_t digest_len;
|
||||
VALUE str;
|
||||
char *p;
|
||||
int i, j, seed = 1;
|
||||
static const char vowels[] = {
|
||||
'a', 'e', 'i', 'o', 'u', 'y'
|
||||
};
|
||||
static const char consonants[] = {
|
||||
'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n',
|
||||
'p', 'r', 's', 't', 'v', 'z', 'x'
|
||||
};
|
||||
size_t digest_len = 32; /* about this size at least */
|
||||
char *cname;
|
||||
|
||||
StringValue(str_digest);
|
||||
digest = RSTRING_PTR(str_digest);
|
||||
digest_len = RSTRING_LEN(str_digest);
|
||||
|
||||
if ((LONG_MAX - 2) / 3 < (digest_len | 1)) {
|
||||
rb_raise(rb_eRuntimeError, "digest string too long");
|
||||
}
|
||||
|
||||
str = rb_str_new(0, (digest_len | 1) * 3 + 2);
|
||||
p = RSTRING_PTR(str);
|
||||
|
||||
i = j = 0;
|
||||
p[j++] = 'x';
|
||||
|
||||
for (;;) {
|
||||
unsigned char byte1, byte2;
|
||||
|
||||
if (i >= digest_len) {
|
||||
p[j++] = vowels[seed % 6];
|
||||
p[j++] = consonants[16];
|
||||
p[j++] = vowels[seed / 6];
|
||||
break;
|
||||
}
|
||||
|
||||
byte1 = digest[i++];
|
||||
p[j++] = vowels[(((byte1 >> 6) & 3) + seed) % 6];
|
||||
p[j++] = consonants[(byte1 >> 2) & 15];
|
||||
p[j++] = vowels[((byte1 & 3) + (seed / 6)) % 6];
|
||||
|
||||
if (i >= digest_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
byte2 = digest[i++];
|
||||
p[j++] = consonants[(byte2 >> 4) & 15];
|
||||
p[j++] = '-';
|
||||
p[j++] = consonants[byte2 & 15];
|
||||
|
||||
seed = (seed * 5 + byte1 * 7 + byte2) % 36;
|
||||
}
|
||||
|
||||
p[j] = 'x';
|
||||
cname = rb_obj_classname(self);
|
||||
|
||||
/* #<Digest::ClassName: xxxxx...xxxx> */
|
||||
str = rb_str_buf_new(2 + strlen(cname) + 2 + digest_len * 2 + 1);
|
||||
rb_str_buf_cat2(str, "#<");
|
||||
rb_str_buf_cat2(str, cname);
|
||||
rb_str_buf_cat2(str, ": ");
|
||||
rb_str_buf_append(str, rb_digest_instance_hexdigest(0, 0, self));
|
||||
rb_str_buf_cat2(str, ">");
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj == another_digest_obj -> boolean
|
||||
* digest_obj == string -> boolean
|
||||
*
|
||||
* If a string is given, checks whether it is equal to the hex-encoded
|
||||
* hash value of the digest object. If another instance of the same
|
||||
* digest class is given, checks whether they have the same hash
|
||||
* value. Otherwise returns false.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_equal(VALUE self, VALUE other)
|
||||
{
|
||||
VALUE str1, str2;
|
||||
|
||||
if (rb_obj_class(self) == rb_obj_class(other)) {
|
||||
str1 = rb_digest_instance_digest(0, 0, self);
|
||||
str2 = rb_digest_instance_digest(0, 0, other);
|
||||
} else {
|
||||
str1 = rb_digest_instance_to_s(self);
|
||||
str2 = other;
|
||||
}
|
||||
|
||||
/* never blindly assume that subclass methods return strings */
|
||||
StringValue(str1);
|
||||
StringValue(str2);
|
||||
|
||||
if (RSTRING_LEN(str1) == RSTRING_LEN(str2) &&
|
||||
rb_str_cmp(str1, str2) == 0) {
|
||||
return Qtrue;
|
||||
}
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.digest_length -> integer
|
||||
*
|
||||
* Returns the length of the hash value of the digest.
|
||||
*
|
||||
* This method should be overridden by each implementation subclass.
|
||||
* If not, digest_obj.digest().length() is returned.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_digest_length(VALUE self)
|
||||
{
|
||||
/* subclasses really should redefine this method */
|
||||
VALUE digest = rb_digest_instance_digest(0, 0, self);
|
||||
|
||||
/* never blindly assume that #digest() returns a string */
|
||||
StringValue(digest);
|
||||
return INT2NUM(RSTRING_LEN(digest));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.length -> integer
|
||||
* digest_obj.size -> integer
|
||||
*
|
||||
* Returns digest_obj.digest_length().
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_length(VALUE self)
|
||||
{
|
||||
return rb_funcall(self, id_digest_length, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest_obj.block_length -> integer
|
||||
*
|
||||
* Returns the block length of the digest.
|
||||
*
|
||||
* This method is overridden by each implementation subclass.
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_instance_block_length(VALUE self)
|
||||
{
|
||||
rb_raise(rb_eRuntimeError, "%s does not implement block_length()", rb_inspect(self));
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-class: Digest::Class
|
||||
*
|
||||
* This module stands as a base class for digest implementation
|
||||
* classes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Digest::Class.digest(string, *parameters) -> hash_string
|
||||
*
|
||||
* Returns the hash value of a given _string_. This is equivalent to
|
||||
* Digest::Class.new(*parameters).digest(string), where extra
|
||||
* _parameters_, if any, are passed through to the constructor and the
|
||||
* _string_ is passed to #digest().
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
VALUE str;
|
||||
void *pctx;
|
||||
volatile VALUE obj;
|
||||
|
||||
if (argc < 1) {
|
||||
rb_raise(rb_eArgError, "no data given");
|
||||
}
|
||||
|
||||
str = *argv++;
|
||||
argc--;
|
||||
|
||||
StringValue(str);
|
||||
|
||||
obj = rb_obj_alloc(klass);
|
||||
rb_obj_call_init(obj, argc, argv);
|
||||
|
||||
return rb_funcall(obj, id_digest, 1, str);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Digest::Class.hexdigest(string[, ...]) -> hash_string
|
||||
*
|
||||
* Returns the hex-encoded hash value of a given _string_. This is
|
||||
* almost equivalent to
|
||||
* Digest.hexencode(Digest::Class.new(*parameters).digest(string)).
|
||||
*/
|
||||
static VALUE
|
||||
rb_digest_class_s_hexdigest(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
return hexencode_str_new(rb_funcall2(klass, id_digest, argc, argv));
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-class: Digest::Base
|
||||
*
|
||||
* This abstract class provides a common interface to message digest
|
||||
* implementation classes written in C.
|
||||
*/
|
||||
|
||||
static rb_digest_metadata_t *
|
||||
get_digest_base_metadata(VALUE klass)
|
||||
{
|
||||
VALUE obj;
|
||||
rb_digest_metadata_t *algo;
|
||||
|
||||
if (rb_ivar_defined(klass, id_metadata) == Qfalse) {
|
||||
/* This class should not be subclassed in Ruby */
|
||||
rb_notimplement();
|
||||
}
|
||||
|
||||
obj = rb_ivar_get(klass, id_metadata);
|
||||
|
||||
Data_Get_Struct(obj, rb_digest_metadata_t, algo);
|
||||
|
||||
switch (algo->api_version) {
|
||||
case 2:
|
||||
break;
|
||||
|
||||
/*
|
||||
* put conversion here if possible when API is updated
|
||||
*/
|
||||
|
||||
default:
|
||||
rb_raise(rb_eRuntimeError, "Incompatible digest API version");
|
||||
}
|
||||
|
||||
return algo;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_digest_base_alloc(VALUE klass)
|
||||
{
|
||||
algo_t *algo;
|
||||
rb_digest_metadata_t *algo;
|
||||
VALUE obj;
|
||||
void *pctx;
|
||||
|
||||
if (klass == cDigest_Base) {
|
||||
if (klass == rb_cDigest_Base) {
|
||||
rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
|
||||
}
|
||||
|
||||
algo = get_digest_base_metadata(klass);
|
||||
|
||||
if (algo == NULL) {
|
||||
return Data_Wrap_Struct(klass, 0, free, 0);
|
||||
}
|
||||
|
||||
pctx = xmalloc(algo->ctx_size);
|
||||
algo->init_func(pctx);
|
||||
|
||||
|
@ -159,62 +471,19 @@ rb_digest_base_alloc(VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_digest_base_s_digest(VALUE klass, VALUE str)
|
||||
{
|
||||
algo_t *algo = get_digest_base_metadata(klass);
|
||||
void *pctx;
|
||||
volatile VALUE obj;
|
||||
|
||||
if (algo == NULL) {
|
||||
VALUE obj = rb_funcall(klass, id_new, 0);
|
||||
rb_funcall(obj, id_update, 1, str);
|
||||
return rb_funcall(obj, id_digest, 0);
|
||||
}
|
||||
|
||||
obj = rb_digest_base_alloc(klass);
|
||||
Data_Get_Struct(obj, void, pctx);
|
||||
|
||||
StringValue(str);
|
||||
algo->update_func(pctx, RSTRING_PTR(str), RSTRING_LEN(str));
|
||||
|
||||
str = rb_str_new(0, algo->digest_len);
|
||||
algo->finish_func(pctx, RSTRING_PTR(str));
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_digest_base_s_hexdigest(VALUE klass, VALUE str)
|
||||
{
|
||||
return hexdigest_str_new(rb_funcall(klass, id_digest, 1, str));
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_digest_base_s_bubblebabble(VALUE klass, VALUE str)
|
||||
{
|
||||
return bubblebabble_str_new(rb_funcall(klass, id_digest, 1, str));
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
rb_digest_base_copy(VALUE copy, VALUE obj)
|
||||
{
|
||||
algo_t *algo;
|
||||
rb_digest_metadata_t *algo;
|
||||
void *pctx1, *pctx2;
|
||||
|
||||
if (copy == obj) return copy;
|
||||
|
||||
rb_check_frozen(copy);
|
||||
|
||||
algo = get_digest_base_metadata(rb_obj_class(copy));
|
||||
|
||||
if (algo == NULL) {
|
||||
/* initialize_copy() is undefined or something */
|
||||
rb_notimplement();
|
||||
}
|
||||
|
||||
/* get_digest_base_metadata() may return a NULL */
|
||||
if (algo != get_digest_base_metadata(rb_obj_class(obj))) {
|
||||
rb_raise(rb_eTypeError, "wrong argument class");
|
||||
}
|
||||
Data_Get_Struct(obj, void, pctx1);
|
||||
Data_Get_Struct(copy, void, pctx2);
|
||||
memcpy(pctx2, pctx1, algo->ctx_size);
|
||||
|
@ -222,41 +491,31 @@ rb_digest_base_copy(VALUE copy, VALUE obj)
|
|||
return copy;
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
rb_digest_base_reset(VALUE self)
|
||||
{
|
||||
algo_t *algo;
|
||||
rb_digest_metadata_t *algo;
|
||||
void *pctx;
|
||||
|
||||
algo = get_digest_base_metadata(rb_obj_class(self));
|
||||
|
||||
if (algo == NULL) {
|
||||
rb_funcall(self, id_initialize, 0);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
Data_Get_Struct(self, void, pctx);
|
||||
|
||||
memset(pctx, 0, algo->ctx_size);
|
||||
algo->init_func(pctx);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
rb_digest_base_update(VALUE self, VALUE str)
|
||||
{
|
||||
algo_t *algo;
|
||||
rb_digest_metadata_t *algo;
|
||||
void *pctx;
|
||||
|
||||
algo = get_digest_base_metadata(rb_obj_class(self));
|
||||
|
||||
if (algo == NULL) {
|
||||
/* subclasses must define update() */
|
||||
rb_notimplement();
|
||||
}
|
||||
|
||||
Data_Get_Struct(self, void, pctx);
|
||||
|
||||
StringValue(str);
|
||||
|
@ -265,183 +524,116 @@ rb_digest_base_update(VALUE self, VALUE str)
|
|||
return self;
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
rb_digest_base_lshift(VALUE self, VALUE str)
|
||||
rb_digest_base_finish(VALUE self)
|
||||
{
|
||||
algo_t *algo;
|
||||
rb_digest_metadata_t *algo;
|
||||
void *pctx;
|
||||
|
||||
algo = get_digest_base_metadata(rb_obj_class(self));
|
||||
|
||||
if (algo == NULL) {
|
||||
/* subclasses just need to define update(), not << */
|
||||
rb_funcall(self, id_update, 1, str);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
Data_Get_Struct(self, void, pctx);
|
||||
|
||||
StringValue(str);
|
||||
algo->update_func(pctx, RSTRING_PTR(str), RSTRING_LEN(str));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_digest_base_init(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE arg;
|
||||
|
||||
rb_scan_args(argc, argv, "01", &arg);
|
||||
|
||||
if (!NIL_P(arg)) rb_digest_base_update(self, arg);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_digest_base_digest(VALUE self)
|
||||
{
|
||||
algo_t *algo;
|
||||
void *pctx1, *pctx2;
|
||||
size_t ctx_size;
|
||||
VALUE str;
|
||||
|
||||
algo = get_digest_base_metadata(rb_obj_class(self));
|
||||
|
||||
if (algo == NULL) {
|
||||
/* subclasses must define update() */
|
||||
rb_notimplement();
|
||||
}
|
||||
|
||||
Data_Get_Struct(self, void, pctx1);
|
||||
|
||||
ctx_size = algo->ctx_size;
|
||||
pctx2 = xmalloc(ctx_size);
|
||||
memcpy(pctx2, pctx1, ctx_size);
|
||||
Data_Get_Struct(self, void, pctx);
|
||||
|
||||
str = rb_str_new(0, algo->digest_len);
|
||||
algo->finish_func(pctx2, RSTRING_PTR(str));
|
||||
free(pctx2);
|
||||
algo->finish_func(pctx, RSTRING_PTR(str));
|
||||
|
||||
/* avoid potential coredump caused by use of a finished context */
|
||||
algo->init_func(pctx);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
rb_digest_base_hexdigest(VALUE self)
|
||||
rb_digest_base_digest_length(VALUE self)
|
||||
{
|
||||
return hexdigest_str_new(rb_funcall(self, id_digest, 0));
|
||||
rb_digest_metadata_t *algo;
|
||||
|
||||
algo = get_digest_base_metadata(rb_obj_class(self));
|
||||
|
||||
return INT2NUM(algo->digest_len);
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
rb_digest_base_bubblebabble(VALUE self)
|
||||
rb_digest_base_block_length(VALUE self)
|
||||
{
|
||||
return bubblebabble_str_new(rb_funcall(self, id_digest, 0));
|
||||
rb_digest_metadata_t *algo;
|
||||
|
||||
algo = get_digest_base_metadata(rb_obj_class(self));
|
||||
|
||||
return INT2NUM(algo->block_len);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_digest_base_inspect(VALUE self)
|
||||
{
|
||||
algo_t *algo;
|
||||
VALUE klass, str;
|
||||
size_t digest_len = 32; /* no need to be just the right size */
|
||||
char *cname;
|
||||
|
||||
klass = rb_obj_class(self);
|
||||
algo = get_digest_base_metadata(klass);
|
||||
|
||||
if (algo != NULL)
|
||||
digest_len = algo->digest_len;
|
||||
|
||||
cname = rb_obj_classname(self);
|
||||
|
||||
/* #<Digest::Alg: xxxxx...xxxx> */
|
||||
str = rb_str_buf_new(2 + strlen(cname) + 2 + digest_len * 2 + 1);
|
||||
rb_str_buf_cat2(str, "#<");
|
||||
rb_str_buf_cat2(str, cname);
|
||||
rb_str_buf_cat2(str, ": ");
|
||||
rb_str_buf_append(str, rb_digest_base_hexdigest(self));
|
||||
rb_str_buf_cat2(str, ">");
|
||||
return str;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_digest_base_equal(VALUE self, VALUE other)
|
||||
{
|
||||
algo_t *algo;
|
||||
VALUE klass;
|
||||
VALUE str1, str2;
|
||||
|
||||
klass = rb_obj_class(self);
|
||||
|
||||
if (rb_obj_class(other) == klass) {
|
||||
str1 = rb_digest_base_digest(self);
|
||||
str2 = rb_digest_base_digest(other);
|
||||
} else {
|
||||
StringValue(other);
|
||||
str2 = other;
|
||||
|
||||
algo = get_digest_base_metadata(klass);
|
||||
|
||||
if (RSTRING_LEN(str2) == algo->digest_len)
|
||||
str1 = rb_digest_base_digest(self);
|
||||
else
|
||||
str1 = rb_digest_base_hexdigest(self);
|
||||
}
|
||||
|
||||
if (RSTRING_LEN(str1) == RSTRING_LEN(str2)
|
||||
&& rb_str_cmp(str1, str2) == 0)
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* This module provides an interface to the following hash algorithms:
|
||||
*
|
||||
* - the MD5 Message-Digest Algorithm by the RSA Data Security,
|
||||
* Inc., described in RFC 1321
|
||||
*
|
||||
* - the SHA-1 Secure Hash Algorithm by NIST (the US' National
|
||||
* Institute of Standards and Technology), described in FIPS PUB
|
||||
* 180-1.
|
||||
*
|
||||
* - the SHA-256/384/512 Secure Hash Algorithm by NIST (the US'
|
||||
* National Institute of Standards and Technology), described in
|
||||
* FIPS PUB 180-2.
|
||||
*
|
||||
* - the RIPEMD-160 cryptographic hash function, designed by Hans
|
||||
* Dobbertin, Antoon Bosselaers, and Bart Preneel.
|
||||
*/
|
||||
|
||||
void
|
||||
Init_digest(void)
|
||||
{
|
||||
mDigest = rb_define_module("Digest");
|
||||
id_reset = rb_intern("reset");
|
||||
id_update = rb_intern("update");
|
||||
id_finish = rb_intern("finish");
|
||||
id_digest = rb_intern("digest");
|
||||
id_hexdigest = rb_intern("hexdigest");
|
||||
id_digest_length = rb_intern("digest_length");
|
||||
|
||||
cDigest_Base = rb_define_class_under(mDigest, "Base", rb_cObject);
|
||||
/*
|
||||
* module Digest
|
||||
*/
|
||||
rb_mDigest = rb_define_module("Digest");
|
||||
|
||||
rb_define_alloc_func(cDigest_Base, rb_digest_base_alloc);
|
||||
rb_define_singleton_method(cDigest_Base, "digest", rb_digest_base_s_digest, 1);
|
||||
rb_define_singleton_method(cDigest_Base, "hexdigest", rb_digest_base_s_hexdigest, 1);
|
||||
rb_define_singleton_method(cDigest_Base, "bubblebabble", rb_digest_base_s_bubblebabble, 1);
|
||||
/* module functions */
|
||||
rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1);
|
||||
|
||||
rb_define_method(cDigest_Base, "initialize", rb_digest_base_init, -1);
|
||||
rb_define_method(cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
|
||||
rb_define_method(cDigest_Base, "reset", rb_digest_base_reset, 0);
|
||||
rb_define_method(cDigest_Base, "update", rb_digest_base_update, 1);
|
||||
rb_define_method(cDigest_Base, "<<", rb_digest_base_lshift, 1);
|
||||
rb_define_method(cDigest_Base, "digest", rb_digest_base_digest, 0);
|
||||
rb_define_method(cDigest_Base, "hexdigest", rb_digest_base_hexdigest, 0);
|
||||
rb_define_method(cDigest_Base, "bubblebabble", rb_digest_base_bubblebabble, 0);
|
||||
rb_define_method(cDigest_Base, "to_s", rb_digest_base_hexdigest, 0);
|
||||
rb_define_method(cDigest_Base, "inspect", rb_digest_base_inspect, 0);
|
||||
rb_define_method(cDigest_Base, "==", rb_digest_base_equal, 1);
|
||||
/*
|
||||
* module Digest::Instance
|
||||
*/
|
||||
rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance");
|
||||
|
||||
/* instance methods that should be overridden */
|
||||
rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1);
|
||||
rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1);
|
||||
rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0);
|
||||
rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0);
|
||||
rb_define_method(rb_mDigest_Instance, "digest_length", rb_digest_instance_digest_length, 0);
|
||||
rb_define_method(rb_mDigest_Instance, "block_length", rb_digest_instance_block_length, 0);
|
||||
|
||||
/* instance methods that may be overridden */
|
||||
rb_define_method(rb_mDigest_Instance, "==", rb_digest_instance_equal, 1);
|
||||
rb_define_method(rb_mDigest_Instance, "inspect", rb_digest_instance_inspect, 0);
|
||||
|
||||
/* instance methods that need not usually be overridden */
|
||||
rb_define_method(rb_mDigest_Instance, "new", rb_digest_instance_new, 0);
|
||||
rb_define_method(rb_mDigest_Instance, "digest", rb_digest_instance_digest, -1);
|
||||
rb_define_method(rb_mDigest_Instance, "digest!", rb_digest_instance_digest_bang, 0);
|
||||
rb_define_method(rb_mDigest_Instance, "hexdigest", rb_digest_instance_hexdigest, -1);
|
||||
rb_define_method(rb_mDigest_Instance, "hexdigest!", rb_digest_instance_hexdigest_bang, 0);
|
||||
rb_define_method(rb_mDigest_Instance, "to_s", rb_digest_instance_hexdigest, 0);
|
||||
rb_define_method(rb_mDigest_Instance, "length", rb_digest_instance_length, 0);
|
||||
rb_define_method(rb_mDigest_Instance, "size", rb_digest_instance_length, 0);
|
||||
|
||||
/*
|
||||
* class Digest::Class
|
||||
*/
|
||||
rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject);
|
||||
rb_include_module(rb_cDigest_Class, rb_mDigest_Instance);
|
||||
|
||||
/* class methods */
|
||||
rb_define_singleton_method(rb_cDigest_Class, "digest", rb_digest_class_s_digest, -1);
|
||||
rb_define_singleton_method(rb_cDigest_Class, "hexdigest", rb_digest_class_s_hexdigest, -1);
|
||||
|
||||
id_metadata = rb_intern("metadata");
|
||||
id_new = rb_intern("new");
|
||||
id_initialize = rb_intern("initialize");
|
||||
id_update = rb_intern("update");
|
||||
id_digest = rb_intern("digest");
|
||||
|
||||
/* class Digest::Base < Digest::Class */
|
||||
rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class);
|
||||
|
||||
rb_define_alloc_func(rb_cDigest_Base, rb_digest_base_alloc);
|
||||
|
||||
rb_define_method(rb_cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
|
||||
rb_define_method(rb_cDigest_Base, "reset", rb_digest_base_reset, 0);
|
||||
rb_define_method(rb_cDigest_Base, "update", rb_digest_base_update, 1);
|
||||
rb_define_method(rb_cDigest_Base, "<<", rb_digest_base_update, 1);
|
||||
rb_define_private_method(rb_cDigest_Base, "finish", rb_digest_base_finish, 0);
|
||||
rb_define_method(rb_cDigest_Base, "digest_length", rb_digest_base_digest_length, 0);
|
||||
rb_define_method(rb_cDigest_Base, "block_length", rb_digest_base_block_length, 0);
|
||||
}
|
||||
|
|
|
@ -15,14 +15,18 @@
|
|||
|
||||
#include "ruby.h"
|
||||
|
||||
typedef void (*hash_init_func_t)(void *);
|
||||
typedef void (*hash_update_func_t)(void *, unsigned char *, size_t);
|
||||
typedef void (*hash_finish_func_t)(void *, unsigned char *);
|
||||
#define RUBY_DIGEST_API_VERSION 2
|
||||
|
||||
typedef void (*rb_digest_hash_init_func_t)(void *);
|
||||
typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t);
|
||||
typedef void (*rb_digest_hash_finish_func_t)(void *, unsigned char *);
|
||||
|
||||
typedef struct {
|
||||
int api_version;
|
||||
size_t digest_len;
|
||||
size_t block_len;
|
||||
size_t ctx_size;
|
||||
hash_init_func_t init_func;
|
||||
hash_update_func_t update_func;
|
||||
hash_finish_func_t finish_func;
|
||||
} algo_t;
|
||||
rb_digest_hash_init_func_t init_func;
|
||||
rb_digest_hash_update_func_t update_func;
|
||||
rb_digest_hash_finish_func_t finish_func;
|
||||
} rb_digest_metadata_t;
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
.\" digest.txt - -*- Indented-Text -*- created at: Fri May 25 08:13:50 JST 2001
|
||||
$RoughId: digest.txt,v 1.9 2001/07/13 19:46:51 knu Exp $
|
||||
$Id$
|
||||
|
||||
** MD5(Class)
|
||||
|
||||
A class to implement the MD5 Message-Digest Algorithm by RSA Data
|
||||
Security, Inc., described in RFC1321.
|
||||
|
||||
Superclass: Digest::Base
|
||||
|
||||
require 'digest/md5'
|
||||
|
||||
** SHA1(Class)
|
||||
|
||||
A class to implement the SHA-1 Secure Hash Algorithm by NIST (the US'
|
||||
National Institute of Standards and Technology), described in FIPS PUB
|
||||
180-1.
|
||||
|
||||
Superclass: Digest::Base
|
||||
|
||||
require 'digest/sha1'
|
||||
|
||||
** SHA256(Class)
|
||||
** SHA384(Class)
|
||||
** SHA512(Class)
|
||||
|
||||
Classes to implement the SHA-256/384/512 Secure Hash Algorithm(s) by
|
||||
NIST (the US' National Institute of Standards and Technology),
|
||||
described in FIPS PUB 180-2.
|
||||
|
||||
Superclass: Digest::Base
|
||||
|
||||
require 'digest/sha2'
|
||||
|
||||
** RMD160(Class)
|
||||
|
||||
A class to implement the RIPEMD-160 cryptographic hash function,
|
||||
designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel.
|
||||
|
||||
Superclass: Digest::Base
|
||||
|
||||
require 'digest/rmd160'
|
||||
|
||||
|
||||
Those above classes provide a common interface as shown below.
|
||||
|
||||
|
||||
Class Methods:
|
||||
|
||||
new([str])
|
||||
|
||||
Creates a new digest object. If a string argument is given,
|
||||
it is added to the object. (see update.)
|
||||
|
||||
digest(str)
|
||||
|
||||
Immediately calculates and return the hash of the given
|
||||
strings as a string. Equivalent to new(str).digest.
|
||||
|
||||
hexdigest(str)
|
||||
|
||||
Immediately calculates and return the hash of the given
|
||||
strings as a string of hexadecimal digits. Equivalent to
|
||||
new(str).hexdigest.
|
||||
|
||||
Methods:
|
||||
|
||||
clone
|
||||
|
||||
Creates a copy of the digest object.
|
||||
|
||||
digest
|
||||
|
||||
Returns the hash of the added strings as a string of 16 bytes
|
||||
for MD5, 20 bytes for SHA1 and RMD160, 32 bytes for SHA256, 48
|
||||
bytes for SHA384, and 64 bytes for SHA512.
|
||||
|
||||
hexdigest
|
||||
to_s
|
||||
|
||||
Returns the hash of the added strings as a string of 32
|
||||
hexadecimal digits for MD5, 40 hexadecimal digits for SHA1 and
|
||||
RMD160, 64 hexadecimal digits for SHA256, 96 hexadecimal
|
||||
digits for SHA384, and 128 hexadecimal digits for SHA512.
|
||||
This method is equal to:
|
||||
|
||||
def hexdigest
|
||||
digest.unpack("H*")[0]
|
||||
end
|
||||
|
||||
update(str)
|
||||
<< str
|
||||
|
||||
Appends the string str to the digest object. Repeated calls
|
||||
are equivalent to a single call with the concatenation of all
|
||||
the arguments, i.e. m.update(a); m.update(b) is equivalent to
|
||||
m.update(a + b) and m << a << b is equivalent to m << a + b.
|
||||
|
||||
== md
|
||||
|
||||
Checks if the object is equal to the given digest object.
|
||||
|
||||
== str
|
||||
|
||||
Regards the value as either a digest value or a hexdigest
|
||||
value (depending on the length) and checks if the object is
|
||||
equal to the given string.
|
||||
|
||||
-------------------------------------------------------
|
||||
Local variables:
|
||||
fill-column: 70
|
||||
end:
|
|
@ -1,111 +0,0 @@
|
|||
.\" digest.txt.ja - -*- Indented-Text -*- created at: Fri May 25 08:22:19 JST 2001
|
||||
$RoughId: digest.txt.jp,v 1.8 2001/07/13 15:38:27 knu Exp $
|
||||
$Id$
|
||||
|
||||
** MD5(クラス)
|
||||
|
||||
RFC1321に記述されているRSA Data Security, Inc. の MD5 Message-Digest
|
||||
Algorithmを実装するクラス。
|
||||
|
||||
Superclass: Digest::Base
|
||||
|
||||
require 'digest/md5'
|
||||
|
||||
** SHA1(クラス)
|
||||
|
||||
FIPS PUB 180-1に記述されているNIST (the US' National Institute of
|
||||
Standards and Technology) の SHA-1 Secure Hash Algorithmを実装するクラス。
|
||||
|
||||
Superclass: Digest::Base
|
||||
|
||||
require 'digest/sha1'
|
||||
|
||||
** SHA256(クラス)
|
||||
** SHA384(クラス)
|
||||
** SHA512(クラス)
|
||||
|
||||
FIPS PUB 180-2に記述されているNIST (the US' National Institute of
|
||||
Standards and Technology) の SHA-256/384/512 Secure Hash Algorithmを
|
||||
実装するクラス。
|
||||
|
||||
Superclass: Digest::Base
|
||||
|
||||
require 'digest/sha2'
|
||||
|
||||
** RMD160(クラス)
|
||||
|
||||
Hans Dobbertin, Antoon Bosselaers, Bart Preneel によって設計された
|
||||
RIPEMD-160 ハッシュ関数を実装するクラス。
|
||||
|
||||
Superclass: Digest::Base
|
||||
|
||||
require 'digest/rmd160'
|
||||
|
||||
|
||||
これらのクラスは以下のような共通のインターフェースを提供する。
|
||||
|
||||
|
||||
Class Methods:
|
||||
|
||||
new([str])
|
||||
|
||||
新しいダイジェストオブジェクトを生成する.文字列引数が与えられる
|
||||
とそれを追加する(see update)。
|
||||
|
||||
digest(str)
|
||||
|
||||
与えられた文字列に対するハッシュ値を文字列で返す。
|
||||
new(str).digest と等価。
|
||||
|
||||
hexdigest(str)
|
||||
|
||||
与えられた文字列に対するハッシュ値を、ASCIIコードを使って
|
||||
16進数の列を示す文字列にエンコードして返す。
|
||||
new(str).hexdigest と等価。
|
||||
|
||||
Methods:
|
||||
|
||||
clone
|
||||
|
||||
ダイジェストオブジェクトの複製を作る。
|
||||
|
||||
digest
|
||||
|
||||
今までに追加した文字列に対するハッシュ値を文字列で返す。MD5では
|
||||
16バイト長、SHA1およびRMD160では20バイト長、SHA256では32バイト長、
|
||||
SHA384では48バイト長、SHA512では64バイト長となる。
|
||||
|
||||
hexdigest
|
||||
to_s
|
||||
|
||||
今までに追加した文字列に対するハッシュ値を、ASCIIコードを使って
|
||||
16進数の列を示す文字列にエンコードして返す。MD5では32バイト長、
|
||||
SHA1およびRMD160では40バイト長、SHA256では64バイト長、SHA384では
|
||||
96バイト長、SHA512では128バイト長となる。Rubyで書くと以下と同じ。
|
||||
|
||||
def hexdigest
|
||||
digest.unpack("H*")[0]
|
||||
end
|
||||
|
||||
update(str)
|
||||
<< str
|
||||
|
||||
文字列を追加する。複数回updateを呼ぶことは文字列を連結して
|
||||
updateを呼ぶことと等しい。すなわち m.update(a); m.update(b) は
|
||||
m.update(a + b) と、 m << a << b は m << a + b とそれぞれ等価
|
||||
である。
|
||||
|
||||
== md
|
||||
|
||||
与えられたダイジェストオブジェクトと比較する。
|
||||
|
||||
== str
|
||||
|
||||
与えられた文字列を digest 値、もしくは hexdigest 値と比較する。
|
||||
いずれの値と見るかは与えられた文字列の長さによって自動判別
|
||||
される。
|
||||
|
||||
-------------------------------------------------------
|
||||
Local variables:
|
||||
fill-column: 70
|
||||
end:
|
|
@ -1,27 +1,46 @@
|
|||
require 'digest.so'
|
||||
|
||||
module Digest
|
||||
autoload "MD5", "digest/md5"
|
||||
autoload "RMD160", "digest/rmd160"
|
||||
autoload "SHA1", "digest/sha1"
|
||||
autoload "SHA256", "digest/sha2"
|
||||
autoload "SHA384", "digest/sha2"
|
||||
autoload "SHA512", "digest/sha2"
|
||||
autoload "SHA256", "digest/sha2.so"
|
||||
autoload "SHA384", "digest/sha2.so"
|
||||
autoload "SHA512", "digest/sha2.so"
|
||||
|
||||
class Base
|
||||
# creates a digest object and read given file, _name_.
|
||||
def self.const_missing(name)
|
||||
begin
|
||||
require File.join('digest', name.to_s.downcase)
|
||||
|
||||
return Digest.const_get(name) if Digest.const_defined?(name)
|
||||
rescue LoadError => e
|
||||
end
|
||||
|
||||
raise NameError, "Digest class not found: Digest::#{name}"
|
||||
end
|
||||
|
||||
class ::Digest::Class
|
||||
# creates a digest object and reads a given file, _name_.
|
||||
#
|
||||
# p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest
|
||||
# # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
|
||||
def self.file(name)
|
||||
digest = self.new
|
||||
new.file(name)
|
||||
end
|
||||
end
|
||||
|
||||
module Instance
|
||||
# updates the digest with the contents of a given file _name_ and
|
||||
# returns self.
|
||||
def file(name)
|
||||
File.open(name, "rb") {|f|
|
||||
buf = ""
|
||||
while f.read(16384, buf)
|
||||
digest.update buf
|
||||
update buf
|
||||
end
|
||||
}
|
||||
digest
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def Digest(name)
|
||||
Digest.const_get(name)
|
||||
end
|
||||
|
|
270
ext/digest/lib/digest/hmac.rb
Normal file
270
ext/digest/lib/digest/hmac.rb
Normal file
|
@ -0,0 +1,270 @@
|
|||
# = digest/hmac.rb
|
||||
#
|
||||
# An implementation of HMAC keyed-hashing algorithm
|
||||
#
|
||||
# == Overview
|
||||
#
|
||||
# This library adds a method named hmac() to Digest classes, which
|
||||
# creates a Digest class for calculating HMAC digests.
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
# require 'digest/hmac'
|
||||
#
|
||||
# # one-liner example
|
||||
# puts Digest::HMAC.hexdigest("data", "hash key", Digest::SHA1)
|
||||
#
|
||||
# # rather longer one
|
||||
# hmac = Digest::HMAC.new("foo", Digest::RMD160)
|
||||
#
|
||||
# buf = ""
|
||||
# while stream.read(16384, buf)
|
||||
# hmac.update(buf)
|
||||
# end
|
||||
#
|
||||
# puts hmac.bubblebabble
|
||||
#
|
||||
# == License
|
||||
#
|
||||
# Copyright (c) 2006 Akinori MUSHA <knu@iDaemons.org>
|
||||
#
|
||||
# Documentation by Akinori MUSHA
|
||||
#
|
||||
# All rights reserved. You can redistribute and/or modify it under
|
||||
# the same terms as Ruby.
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
require 'digest'
|
||||
|
||||
module Digest
|
||||
class HMAC < Digest::Class
|
||||
def initialize(key, digester)
|
||||
@md = digester.new
|
||||
|
||||
block_len = @md.block_length
|
||||
|
||||
if key.length > block_len
|
||||
key = @md.digest(key)
|
||||
end
|
||||
|
||||
ipad = Array.new(block_len).fill(0x36)
|
||||
opad = Array.new(block_len).fill(0x5c)
|
||||
|
||||
i = 0
|
||||
key.each_byte { |c|
|
||||
ipad[i] ^= c
|
||||
opad[i] ^= c
|
||||
i += 1
|
||||
}
|
||||
|
||||
@key = key.freeze
|
||||
@ipad = ipad.inject('') { |s, c| s << c.chr }.freeze
|
||||
@opad = opad.inject('') { |s, c| s << c.chr }.freeze
|
||||
end
|
||||
|
||||
def initialize_copy(other)
|
||||
@md = other.instance_eval { @md.clone }
|
||||
end
|
||||
|
||||
def update(text)
|
||||
@md.reset.update(@opad + @md.digest(@ipad + text))
|
||||
self
|
||||
end
|
||||
|
||||
def reset
|
||||
@md.reset
|
||||
self
|
||||
end
|
||||
|
||||
def finish
|
||||
@md.digest!
|
||||
end
|
||||
private :finish
|
||||
|
||||
def digest_length
|
||||
@md.digest_length
|
||||
end
|
||||
|
||||
def block_length
|
||||
@md.block_length
|
||||
end
|
||||
|
||||
def inspect
|
||||
sprintf('#<%s: key=%s, digest=%s>', self.class.name, @key.inspect, @md.inspect.sub(/^\#<(.*)>$/) { $1 });
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
eval DATA.read, nil, $0, __LINE__+4
|
||||
end
|
||||
|
||||
__END__
|
||||
|
||||
require 'test/unit'
|
||||
|
||||
module TM_HMAC
|
||||
def test_s_hexdigest
|
||||
cases.each { |h|
|
||||
digesters.each { |d|
|
||||
assert_equal(h[:hexdigest], Digest::HMAC.hexdigest(h[:data], h[:key], d))
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_hexdigest
|
||||
cases.each { |h|
|
||||
digesters.each { |d|
|
||||
hmac = Digest::HMAC.new(h[:key], d)
|
||||
|
||||
hmac.update(h[:data])
|
||||
|
||||
assert_equal(h[:hexdigest], hmac.hexdigest)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_reset
|
||||
cases.each { |h|
|
||||
digesters.each { |d|
|
||||
hmac = Digest::HMAC.new(h[:key], d)
|
||||
hmac.update("test")
|
||||
hmac.reset
|
||||
hmac.update(h[:data])
|
||||
|
||||
assert_equal(h[:hexdigest], hmac.hexdigest)
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
class TC_HMAC_MD5 < Test::Unit::TestCase
|
||||
include TM_HMAC
|
||||
|
||||
def digesters
|
||||
[Digest::MD5, Digest::MD5.new]
|
||||
end
|
||||
|
||||
# Taken from RFC 2202: Test Cases for HMAC-MD5 and HMAC-SHA-1
|
||||
def cases
|
||||
[
|
||||
{
|
||||
:key => "\x0b" * 16,
|
||||
:data => "Hi There",
|
||||
:hexdigest => "9294727a3638bb1c13f48ef8158bfc9d",
|
||||
}, {
|
||||
:key => "Jefe",
|
||||
:data => "what do ya want for nothing?",
|
||||
:hexdigest => "750c783e6ab0b503eaa86e310a5db738",
|
||||
}, {
|
||||
:key => "\xaa" * 16,
|
||||
:data => "\xdd" * 50,
|
||||
:hexdigest => "56be34521d144c88dbb8c733f0e8b3f6",
|
||||
}, {
|
||||
:key => "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
|
||||
:data => "\xcd" * 50,
|
||||
:hexdigest => "697eaf0aca3a3aea3a75164746ffaa79",
|
||||
}, {
|
||||
:key => "\x0c" * 16,
|
||||
:data => "Test With Truncation",
|
||||
:hexdigest => "56461ef2342edc00f9bab995690efd4c",
|
||||
}, {
|
||||
:key => "\xaa" * 80,
|
||||
:data => "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
:hexdigest => "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd",
|
||||
}, {
|
||||
:key => "\xaa" * 80,
|
||||
:data => "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
|
||||
:hexdigest => "6f630fad67cda0ee1fb1f562db3aa53e",
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
class TC_HMAC_SHA1 < Test::Unit::TestCase
|
||||
include TM_HMAC
|
||||
|
||||
def digesters
|
||||
[Digest::SHA1, Digest::SHA1.new]
|
||||
end
|
||||
|
||||
# Taken from RFC 2202: Test Cases for HMAC-MD5 and HMAC-SHA-1
|
||||
def cases
|
||||
[
|
||||
{
|
||||
:key => "\x0b" * 20,
|
||||
:data => "Hi There",
|
||||
:hexdigest => "b617318655057264e28bc0b6fb378c8ef146be00",
|
||||
}, {
|
||||
:key => "Jefe",
|
||||
:data => "what do ya want for nothing?",
|
||||
:hexdigest => "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79",
|
||||
}, {
|
||||
:key => "\xaa" * 20,
|
||||
:data => "\xdd" * 50,
|
||||
:hexdigest => "125d7342b9ac11cd91a39af48aa17b4f63f175d3",
|
||||
}, {
|
||||
:key => "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
|
||||
:data => "\xcd" * 50,
|
||||
:hexdigest => "4c9007f4026250c6bc8414f9bf50c86c2d7235da",
|
||||
}, {
|
||||
:key => "\x0c" * 20,
|
||||
:data => "Test With Truncation",
|
||||
:hexdigest => "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
|
||||
}, {
|
||||
:key => "\xaa" * 80,
|
||||
:data => "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
:hexdigest => "aa4ae5e15272d00e95705637ce8a3b55ed402112",
|
||||
}, {
|
||||
:key => "\xaa" * 80,
|
||||
:data => "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
|
||||
:hexdigest => "e8e99d0f45237d786d6bbaa7965c7808bbff1a91",
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
class TC_HMAC_RMD160 < Test::Unit::TestCase
|
||||
include TM_HMAC
|
||||
|
||||
def digesters
|
||||
[Digest::RMD160, Digest::RMD160.new]
|
||||
end
|
||||
|
||||
# Taken from RFC 2286: Test Cases for HMAC-RIPEMD160 and HMAC-RIPEMD128
|
||||
def cases
|
||||
[
|
||||
{
|
||||
:key => "\x0b" * 20,
|
||||
:data => "Hi There",
|
||||
:hexdigest => "24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668",
|
||||
}, {
|
||||
:key => "Jefe",
|
||||
:data => "what do ya want for nothing?",
|
||||
:hexdigest => "dda6c0213a485a9e24f4742064a7f033b43c4069",
|
||||
}, {
|
||||
:key => "\xaa" * 20,
|
||||
:data => "\xdd" * 50,
|
||||
:hexdigest => "b0b105360de759960ab4f35298e116e295d8e7c1",
|
||||
}, {
|
||||
:key => "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
|
||||
:data => "\xcd" * 50,
|
||||
:hexdigest => "d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4",
|
||||
}, {
|
||||
:key => "\x0c" * 20,
|
||||
:data => "Test With Truncation",
|
||||
:hexdigest => "7619693978f91d90539ae786500ff3d8e0518e39",
|
||||
}, {
|
||||
:key => "\xaa" * 80,
|
||||
:data => "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
:hexdigest => "6466ca07ac5eac29e1bd523e5ada7605b791fd8b",
|
||||
}, {
|
||||
:key => "\xaa" * 80,
|
||||
:data => "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
|
||||
:hexdigest => "69ea60798d71616cce5fd0871e23754cd75d5a0a",
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
|
@ -8,14 +8,21 @@
|
|||
#include "md5.h"
|
||||
#endif
|
||||
|
||||
static algo_t md5 = {
|
||||
static rb_digest_metadata_t md5 = {
|
||||
RUBY_DIGEST_API_VERSION,
|
||||
MD5_DIGEST_LENGTH,
|
||||
MD5_BLOCK_LENGTH,
|
||||
sizeof(MD5_CTX),
|
||||
(hash_init_func_t)MD5_Init,
|
||||
(hash_update_func_t)MD5_Update,
|
||||
(hash_finish_func_t)MD5_Finish,
|
||||
(rb_digest_hash_init_func_t)MD5_Init,
|
||||
(rb_digest_hash_update_func_t)MD5_Update,
|
||||
(rb_digest_hash_finish_func_t)MD5_Finish,
|
||||
};
|
||||
|
||||
/*
|
||||
* A class for calculating message digests using the MD5
|
||||
* Message-Digest Algorithm by RSA Data Security, Inc., described in
|
||||
* RFC1321.
|
||||
*/
|
||||
void
|
||||
Init_md5()
|
||||
{
|
||||
|
@ -28,9 +35,6 @@ Init_md5()
|
|||
|
||||
cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base);
|
||||
|
||||
rb_define_const(cDigest_MD5, "DIGEST_LENGTH", INT2NUM(MD5_DIGEST_LENGTH));
|
||||
rb_define_const(cDigest_MD5, "BLOCK_LENGTH", INT2NUM(MD5_BLOCK_LENGTH));
|
||||
|
||||
rb_ivar_set(cDigest_MD5, rb_intern("metadata"),
|
||||
Data_Wrap_Struct(rb_cObject, 0, 0, &md5));
|
||||
}
|
||||
|
|
|
@ -8,19 +8,25 @@
|
|||
#include "rmd160.h"
|
||||
#endif
|
||||
|
||||
static algo_t rmd160 = {
|
||||
static rb_digest_metadata_t rmd160 = {
|
||||
RUBY_DIGEST_API_VERSION,
|
||||
RMD160_DIGEST_LENGTH,
|
||||
RMD160_BLOCK_LENGTH,
|
||||
sizeof(RMD160_CTX),
|
||||
(hash_init_func_t)RMD160_Init,
|
||||
(hash_update_func_t)RMD160_Update,
|
||||
(hash_finish_func_t)RMD160_Finish,
|
||||
(rb_digest_hash_init_func_t)RMD160_Init,
|
||||
(rb_digest_hash_update_func_t)RMD160_Update,
|
||||
(rb_digest_hash_finish_func_t)RMD160_Finish,
|
||||
};
|
||||
|
||||
/*
|
||||
* A class for calculating message digests using RIPEMD-160
|
||||
* cryptographic hash function, designed by Hans Dobbertin, Antoon
|
||||
* Bosselaers, and Bart Preneel.
|
||||
*/
|
||||
void
|
||||
Init_rmd160()
|
||||
{
|
||||
VALUE mDigest, cDigest_Base, cDigest_RMD160;
|
||||
ID id_metadata;
|
||||
|
||||
rb_require("digest");
|
||||
|
||||
|
@ -29,11 +35,6 @@ Init_rmd160()
|
|||
|
||||
cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base);
|
||||
|
||||
rb_define_const(cDigest_RMD160, "DIGEST_LENGTH", INT2NUM(RMD160_DIGEST_LENGTH));
|
||||
rb_define_const(cDigest_RMD160, "BLOCK_LENGTH", INT2NUM(RMD160_BLOCK_LENGTH));
|
||||
|
||||
id_metadata = rb_intern("metadata");
|
||||
|
||||
rb_ivar_set(cDigest_RMD160, id_metadata,
|
||||
rb_ivar_set(cDigest_RMD160, rb_intern("metadata"),
|
||||
Data_Wrap_Struct(rb_cObject, 0, 0, &rmd160));
|
||||
}
|
||||
|
|
|
@ -8,29 +8,33 @@
|
|||
#include "sha1.h"
|
||||
#endif
|
||||
|
||||
static algo_t sha1 = {
|
||||
static rb_digest_metadata_t sha1 = {
|
||||
RUBY_DIGEST_API_VERSION,
|
||||
SHA1_DIGEST_LENGTH,
|
||||
SHA1_BLOCK_LENGTH,
|
||||
sizeof(SHA1_CTX),
|
||||
(hash_init_func_t)SHA1_Init,
|
||||
(hash_update_func_t)SHA1_Update,
|
||||
(hash_finish_func_t)SHA1_Finish,
|
||||
(rb_digest_hash_init_func_t)SHA1_Init,
|
||||
(rb_digest_hash_update_func_t)SHA1_Update,
|
||||
(rb_digest_hash_finish_func_t)SHA1_Finish,
|
||||
};
|
||||
|
||||
/*
|
||||
* A class for calculating message digests using the SHA-1 Secure Hash
|
||||
* Algorithm by NIST (the US' National Institute of Standards and
|
||||
* Technology), described in FIPS PUB 180-1.
|
||||
*/
|
||||
void
|
||||
Init_sha1()
|
||||
{
|
||||
VALUE mDigest, cDigest_Base, cDigest_SHA1;
|
||||
|
||||
|
||||
rb_require("digest");
|
||||
|
||||
|
||||
mDigest = rb_path2class("Digest");
|
||||
cDigest_Base = rb_path2class("Digest::Base");
|
||||
|
||||
cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base);
|
||||
|
||||
rb_define_const(cDigest_SHA1, "DIGEST_LENGTH", INT2NUM(SHA1_DIGEST_LENGTH));
|
||||
rb_define_const(cDigest_SHA1, "BLOCK_LENGTH", INT2NUM(SHA1_BLOCK_LENGTH));
|
||||
|
||||
rb_ivar_set(cDigest_SHA1, rb_intern("metadata"),
|
||||
Data_Wrap_Struct(rb_cObject, 0, 0, &sha1));
|
||||
}
|
||||
|
|
|
@ -7,16 +7,23 @@
|
|||
#define FOREACH_BITLEN(func) func(256) func(384) func(512)
|
||||
|
||||
#define DEFINE_ALGO_METADATA(bitlen) \
|
||||
static algo_t sha##bitlen = { \
|
||||
static rb_digest_metadata_t sha##bitlen = { \
|
||||
RUBY_DIGEST_API_VERSION, \
|
||||
SHA##bitlen##_DIGEST_LENGTH, \
|
||||
SHA##bitlen##_BLOCK_LENGTH, \
|
||||
sizeof(SHA##bitlen##_CTX), \
|
||||
(hash_init_func_t)SHA##bitlen##_Init, \
|
||||
(hash_update_func_t)SHA##bitlen##_Update, \
|
||||
(hash_finish_func_t)SHA##bitlen##_Finish, \
|
||||
(rb_digest_hash_init_func_t)SHA##bitlen##_Init, \
|
||||
(rb_digest_hash_update_func_t)SHA##bitlen##_Update, \
|
||||
(rb_digest_hash_finish_func_t)SHA##bitlen##_Finish, \
|
||||
};
|
||||
|
||||
FOREACH_BITLEN(DEFINE_ALGO_METADATA)
|
||||
|
||||
/*
|
||||
* Classes for calculating message digests using the SHA-256/384/512
|
||||
* Secure Hash Algorithm(s) by NIST (the US' National Institute of
|
||||
* Standards and Technology), described in FIPS PUB 180-2.
|
||||
*/
|
||||
void
|
||||
Init_sha2()
|
||||
{
|
||||
|
@ -37,9 +44,6 @@ Init_sha2()
|
|||
|
||||
#define DEFINE_ALGO_CLASS(bitlen) \
|
||||
cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \
|
||||
\
|
||||
rb_define_const(cDigest_SHA##bitlen, "DIGEST_LENGTH", INT2NUM(SHA##bitlen##_DIGEST_LENGTH)); \
|
||||
rb_define_const(cDigest_SHA##bitlen, "BLOCK_LENGTH", INT2NUM(SHA##bitlen##_BLOCK_LENGTH)); \
|
||||
\
|
||||
rb_ivar_set(cDigest_SHA##bitlen, id_metadata, \
|
||||
Data_Wrap_Struct(rb_cObject, 0, 0, &sha##bitlen));
|
||||
|
|
|
@ -11,8 +11,6 @@ ${RUBY} extconf.rb --with-cflags="${CFLAGS}"
|
|||
${MAKE} clean
|
||||
${MAKE}
|
||||
|
||||
mkdir -p lib/digest
|
||||
|
||||
for algo in md5 rmd160 sha1 sha2; do
|
||||
args=--with-cflags="${CFLAGS}"
|
||||
|
||||
|
@ -27,7 +25,6 @@ for algo in md5 rmd160 sha1 sha2; do
|
|||
ln -sf ../../$algo/$algo.so lib/digest/
|
||||
done
|
||||
|
||||
${RUBY} -I. -I./lib test.rb
|
||||
${RUBY} -I. -I./lib ../../test/digest/test_digest.rb
|
||||
|
||||
rm lib/digest/*.so
|
||||
rmdir lib/digest
|
||||
|
|
|
@ -12,7 +12,6 @@ require 'digest'
|
|||
rescue LoadError
|
||||
end
|
||||
end
|
||||
include Digest
|
||||
|
||||
module TestDigest
|
||||
Data1 = "abc"
|
||||
|
@ -44,7 +43,8 @@ module TestDigest
|
|||
def test_eq
|
||||
# This test is also for clone()
|
||||
|
||||
md1 = self.class::ALGO.new("ABC")
|
||||
md1 = self.class::ALGO.new
|
||||
md1 << "ABC"
|
||||
|
||||
assert_equal(md1, md1.clone, self.class::ALGO)
|
||||
|
||||
|
@ -66,55 +66,55 @@ module TestDigest
|
|||
|
||||
class TestMD5 < Test::Unit::TestCase
|
||||
include TestDigest
|
||||
ALGO = MD5
|
||||
ALGO = Digest::MD5
|
||||
DATA = {
|
||||
Data1 => "900150983cd24fb0d6963f7d28e17f72",
|
||||
Data2 => "8215ef0796a20bcaaae116d3876c664a",
|
||||
}
|
||||
end if defined?(MD5)
|
||||
end if defined?(Digest::MD5)
|
||||
|
||||
class TestSHA1 < Test::Unit::TestCase
|
||||
include TestDigest
|
||||
ALGO = SHA1
|
||||
ALGO = Digest::SHA1
|
||||
DATA = {
|
||||
Data1 => "a9993e364706816aba3e25717850c26c9cd0d89d",
|
||||
Data2 => "84983e441c3bd26ebaae4aa1f95129e5e54670f1",
|
||||
}
|
||||
end if defined?(SHA1)
|
||||
end if defined?(Digest::SHA1)
|
||||
|
||||
class TestSHA256 < Test::Unit::TestCase
|
||||
include TestDigest
|
||||
ALGO = SHA256
|
||||
ALGO = Digest::SHA256
|
||||
DATA = {
|
||||
Data1 => "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||
Data2 => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
|
||||
}
|
||||
end if defined?(SHA256)
|
||||
end if defined?(Digest::SHA256)
|
||||
|
||||
class TestSHA384 < Test::Unit::TestCase
|
||||
include TestDigest
|
||||
ALGO = SHA384
|
||||
ALGO = Digest::SHA384
|
||||
DATA = {
|
||||
Data1 => "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7",
|
||||
Data2 => "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b",
|
||||
}
|
||||
end if defined?(SHA384)
|
||||
end if defined?(Digest::SHA384)
|
||||
|
||||
class TestSHA512 < Test::Unit::TestCase
|
||||
include TestDigest
|
||||
ALGO = SHA512
|
||||
ALGO = Digest::SHA512
|
||||
DATA = {
|
||||
Data1 => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
|
||||
Data2 => "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445",
|
||||
}
|
||||
end if defined?(SHA512)
|
||||
end if defined?(Digest::SHA512)
|
||||
|
||||
class TestRMD160 < Test::Unit::TestCase
|
||||
include TestDigest
|
||||
ALGO = RMD160
|
||||
ALGO = Digest::RMD160
|
||||
DATA = {
|
||||
Data1 => "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
|
||||
Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
|
||||
}
|
||||
end if defined?(RMD160)
|
||||
end if defined?(Digest::RMD160)
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue