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>
|
Wed Oct 25 08:03:23 2006 Tadayoshi Funaba <tadf@dotrb.org>
|
||||||
|
|
||||||
* lib/date/format.rb: updated based on date2 3.9.6.
|
* lib/date/format.rb: updated based on date2 3.9.6.
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
Makefile
|
Makefile
|
||||||
mkmf.log
|
mkmf.log
|
||||||
*.def
|
*.def
|
||||||
extconf.h
|
|
||||||
|
|
|
@ -15,32 +15,24 @@
|
||||||
|
|
||||||
#include "digest.h"
|
#include "digest.h"
|
||||||
|
|
||||||
static VALUE mDigest, cDigest_Base;
|
static VALUE rb_mDigest;
|
||||||
static ID id_metadata, id_new, id_initialize, id_update, id_digest;
|
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
|
static VALUE
|
||||||
hexdigest_str_new(VALUE str_digest)
|
hexencode_str_new(VALUE str_digest)
|
||||||
{
|
{
|
||||||
char *digest;
|
char *digest;
|
||||||
size_t digest_len;
|
size_t digest_len;
|
||||||
|
@ -72,85 +64,405 @@ hexdigest_str_new(VALUE str_digest)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* Digest.hexencode(string) -> hexencoded_string
|
||||||
|
*
|
||||||
|
* Generates a hex-encoded version of a given _string_.
|
||||||
|
*/
|
||||||
static VALUE
|
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;
|
VALUE str;
|
||||||
char *p;
|
size_t digest_len = 32; /* about this size at least */
|
||||||
int i, j, seed = 1;
|
char *cname;
|
||||||
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'
|
|
||||||
};
|
|
||||||
|
|
||||||
StringValue(str_digest);
|
cname = rb_obj_classname(self);
|
||||||
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';
|
|
||||||
|
|
||||||
|
/* #<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;
|
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
|
static VALUE
|
||||||
rb_digest_base_alloc(VALUE klass)
|
rb_digest_base_alloc(VALUE klass)
|
||||||
{
|
{
|
||||||
algo_t *algo;
|
rb_digest_metadata_t *algo;
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
void *pctx;
|
void *pctx;
|
||||||
|
|
||||||
if (klass == cDigest_Base) {
|
if (klass == rb_cDigest_Base) {
|
||||||
rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
|
rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
|
||||||
}
|
}
|
||||||
|
|
||||||
algo = get_digest_base_metadata(klass);
|
algo = get_digest_base_metadata(klass);
|
||||||
|
|
||||||
if (algo == NULL) {
|
|
||||||
return Data_Wrap_Struct(klass, 0, free, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pctx = xmalloc(algo->ctx_size);
|
pctx = xmalloc(algo->ctx_size);
|
||||||
algo->init_func(pctx);
|
algo->init_func(pctx);
|
||||||
|
|
||||||
|
@ -159,62 +471,19 @@ rb_digest_base_alloc(VALUE klass)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
/* :nodoc: */
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_digest_base_copy(VALUE copy, VALUE obj)
|
rb_digest_base_copy(VALUE copy, VALUE obj)
|
||||||
{
|
{
|
||||||
algo_t *algo;
|
rb_digest_metadata_t *algo;
|
||||||
void *pctx1, *pctx2;
|
void *pctx1, *pctx2;
|
||||||
|
|
||||||
if (copy == obj) return copy;
|
if (copy == obj) return copy;
|
||||||
|
|
||||||
rb_check_frozen(copy);
|
rb_check_frozen(copy);
|
||||||
|
|
||||||
algo = get_digest_base_metadata(rb_obj_class(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(obj, void, pctx1);
|
||||||
Data_Get_Struct(copy, void, pctx2);
|
Data_Get_Struct(copy, void, pctx2);
|
||||||
memcpy(pctx2, pctx1, algo->ctx_size);
|
memcpy(pctx2, pctx1, algo->ctx_size);
|
||||||
|
@ -222,41 +491,31 @@ rb_digest_base_copy(VALUE copy, VALUE obj)
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* :nodoc: */
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_digest_base_reset(VALUE self)
|
rb_digest_base_reset(VALUE self)
|
||||||
{
|
{
|
||||||
algo_t *algo;
|
rb_digest_metadata_t *algo;
|
||||||
void *pctx;
|
void *pctx;
|
||||||
|
|
||||||
algo = get_digest_base_metadata(rb_obj_class(self));
|
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);
|
Data_Get_Struct(self, void, pctx);
|
||||||
|
|
||||||
memset(pctx, 0, algo->ctx_size);
|
|
||||||
algo->init_func(pctx);
|
algo->init_func(pctx);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* :nodoc: */
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_digest_base_update(VALUE self, VALUE str)
|
rb_digest_base_update(VALUE self, VALUE str)
|
||||||
{
|
{
|
||||||
algo_t *algo;
|
rb_digest_metadata_t *algo;
|
||||||
void *pctx;
|
void *pctx;
|
||||||
|
|
||||||
algo = get_digest_base_metadata(rb_obj_class(self));
|
algo = get_digest_base_metadata(rb_obj_class(self));
|
||||||
|
|
||||||
if (algo == NULL) {
|
|
||||||
/* subclasses must define update() */
|
|
||||||
rb_notimplement();
|
|
||||||
}
|
|
||||||
|
|
||||||
Data_Get_Struct(self, void, pctx);
|
Data_Get_Struct(self, void, pctx);
|
||||||
|
|
||||||
StringValue(str);
|
StringValue(str);
|
||||||
|
@ -265,183 +524,116 @@ rb_digest_base_update(VALUE self, VALUE str)
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* :nodoc: */
|
||||||
static VALUE
|
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;
|
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;
|
VALUE str;
|
||||||
|
|
||||||
algo = get_digest_base_metadata(rb_obj_class(self));
|
algo = get_digest_base_metadata(rb_obj_class(self));
|
||||||
|
|
||||||
if (algo == NULL) {
|
Data_Get_Struct(self, void, pctx);
|
||||||
/* 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);
|
|
||||||
|
|
||||||
str = rb_str_new(0, algo->digest_len);
|
str = rb_str_new(0, algo->digest_len);
|
||||||
algo->finish_func(pctx2, RSTRING_PTR(str));
|
algo->finish_func(pctx, RSTRING_PTR(str));
|
||||||
free(pctx2);
|
|
||||||
|
/* avoid potential coredump caused by use of a finished context */
|
||||||
|
algo->init_func(pctx);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* :nodoc: */
|
||||||
static VALUE
|
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
|
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
|
void
|
||||||
Init_digest(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);
|
/* module functions */
|
||||||
rb_define_singleton_method(cDigest_Base, "digest", rb_digest_base_s_digest, 1);
|
rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 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);
|
|
||||||
|
|
||||||
rb_define_method(cDigest_Base, "initialize", rb_digest_base_init, -1);
|
/*
|
||||||
rb_define_method(cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
|
* module Digest::Instance
|
||||||
rb_define_method(cDigest_Base, "reset", rb_digest_base_reset, 0);
|
*/
|
||||||
rb_define_method(cDigest_Base, "update", rb_digest_base_update, 1);
|
rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance");
|
||||||
rb_define_method(cDigest_Base, "<<", rb_digest_base_lshift, 1);
|
|
||||||
rb_define_method(cDigest_Base, "digest", rb_digest_base_digest, 0);
|
/* instance methods that should be overridden */
|
||||||
rb_define_method(cDigest_Base, "hexdigest", rb_digest_base_hexdigest, 0);
|
rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1);
|
||||||
rb_define_method(cDigest_Base, "bubblebabble", rb_digest_base_bubblebabble, 0);
|
rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1);
|
||||||
rb_define_method(cDigest_Base, "to_s", rb_digest_base_hexdigest, 0);
|
rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0);
|
||||||
rb_define_method(cDigest_Base, "inspect", rb_digest_base_inspect, 0);
|
rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0);
|
||||||
rb_define_method(cDigest_Base, "==", rb_digest_base_equal, 1);
|
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_metadata = rb_intern("metadata");
|
||||||
id_new = rb_intern("new");
|
|
||||||
id_initialize = rb_intern("initialize");
|
/* class Digest::Base < Digest::Class */
|
||||||
id_update = rb_intern("update");
|
rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class);
|
||||||
id_digest = rb_intern("digest");
|
|
||||||
|
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"
|
#include "ruby.h"
|
||||||
|
|
||||||
typedef void (*hash_init_func_t)(void *);
|
#define RUBY_DIGEST_API_VERSION 2
|
||||||
typedef void (*hash_update_func_t)(void *, unsigned char *, size_t);
|
|
||||||
typedef void (*hash_finish_func_t)(void *, unsigned char *);
|
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 {
|
typedef struct {
|
||||||
|
int api_version;
|
||||||
size_t digest_len;
|
size_t digest_len;
|
||||||
|
size_t block_len;
|
||||||
size_t ctx_size;
|
size_t ctx_size;
|
||||||
hash_init_func_t init_func;
|
rb_digest_hash_init_func_t init_func;
|
||||||
hash_update_func_t update_func;
|
rb_digest_hash_update_func_t update_func;
|
||||||
hash_finish_func_t finish_func;
|
rb_digest_hash_finish_func_t finish_func;
|
||||||
} algo_t;
|
} 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'
|
require 'digest.so'
|
||||||
|
|
||||||
module Digest
|
module Digest
|
||||||
autoload "MD5", "digest/md5"
|
autoload "SHA256", "digest/sha2.so"
|
||||||
autoload "RMD160", "digest/rmd160"
|
autoload "SHA384", "digest/sha2.so"
|
||||||
autoload "SHA1", "digest/sha1"
|
autoload "SHA512", "digest/sha2.so"
|
||||||
autoload "SHA256", "digest/sha2"
|
|
||||||
autoload "SHA384", "digest/sha2"
|
|
||||||
autoload "SHA512", "digest/sha2"
|
|
||||||
|
|
||||||
class Base
|
def self.const_missing(name)
|
||||||
# creates a digest object and read given file, _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
|
# p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest
|
||||||
# # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
|
# # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
|
||||||
def self.file(name)
|
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|
|
File.open(name, "rb") {|f|
|
||||||
buf = ""
|
buf = ""
|
||||||
while f.read(16384, buf)
|
while f.read(16384, buf)
|
||||||
digest.update buf
|
update buf
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
digest
|
self
|
||||||
end
|
end
|
||||||
end
|
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"
|
#include "md5.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static algo_t md5 = {
|
static rb_digest_metadata_t md5 = {
|
||||||
|
RUBY_DIGEST_API_VERSION,
|
||||||
MD5_DIGEST_LENGTH,
|
MD5_DIGEST_LENGTH,
|
||||||
|
MD5_BLOCK_LENGTH,
|
||||||
sizeof(MD5_CTX),
|
sizeof(MD5_CTX),
|
||||||
(hash_init_func_t)MD5_Init,
|
(rb_digest_hash_init_func_t)MD5_Init,
|
||||||
(hash_update_func_t)MD5_Update,
|
(rb_digest_hash_update_func_t)MD5_Update,
|
||||||
(hash_finish_func_t)MD5_Finish,
|
(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
|
void
|
||||||
Init_md5()
|
Init_md5()
|
||||||
{
|
{
|
||||||
|
@ -28,9 +35,6 @@ Init_md5()
|
||||||
|
|
||||||
cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base);
|
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"),
|
rb_ivar_set(cDigest_MD5, rb_intern("metadata"),
|
||||||
Data_Wrap_Struct(rb_cObject, 0, 0, &md5));
|
Data_Wrap_Struct(rb_cObject, 0, 0, &md5));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,19 +8,25 @@
|
||||||
#include "rmd160.h"
|
#include "rmd160.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static algo_t rmd160 = {
|
static rb_digest_metadata_t rmd160 = {
|
||||||
|
RUBY_DIGEST_API_VERSION,
|
||||||
RMD160_DIGEST_LENGTH,
|
RMD160_DIGEST_LENGTH,
|
||||||
|
RMD160_BLOCK_LENGTH,
|
||||||
sizeof(RMD160_CTX),
|
sizeof(RMD160_CTX),
|
||||||
(hash_init_func_t)RMD160_Init,
|
(rb_digest_hash_init_func_t)RMD160_Init,
|
||||||
(hash_update_func_t)RMD160_Update,
|
(rb_digest_hash_update_func_t)RMD160_Update,
|
||||||
(hash_finish_func_t)RMD160_Finish,
|
(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
|
void
|
||||||
Init_rmd160()
|
Init_rmd160()
|
||||||
{
|
{
|
||||||
VALUE mDigest, cDigest_Base, cDigest_RMD160;
|
VALUE mDigest, cDigest_Base, cDigest_RMD160;
|
||||||
ID id_metadata;
|
|
||||||
|
|
||||||
rb_require("digest");
|
rb_require("digest");
|
||||||
|
|
||||||
|
@ -29,11 +35,6 @@ Init_rmd160()
|
||||||
|
|
||||||
cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base);
|
cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base);
|
||||||
|
|
||||||
rb_define_const(cDigest_RMD160, "DIGEST_LENGTH", INT2NUM(RMD160_DIGEST_LENGTH));
|
rb_ivar_set(cDigest_RMD160, rb_intern("metadata"),
|
||||||
rb_define_const(cDigest_RMD160, "BLOCK_LENGTH", INT2NUM(RMD160_BLOCK_LENGTH));
|
|
||||||
|
|
||||||
id_metadata = rb_intern("metadata");
|
|
||||||
|
|
||||||
rb_ivar_set(cDigest_RMD160, id_metadata,
|
|
||||||
Data_Wrap_Struct(rb_cObject, 0, 0, &rmd160));
|
Data_Wrap_Struct(rb_cObject, 0, 0, &rmd160));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,29 +8,33 @@
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static algo_t sha1 = {
|
static rb_digest_metadata_t sha1 = {
|
||||||
|
RUBY_DIGEST_API_VERSION,
|
||||||
SHA1_DIGEST_LENGTH,
|
SHA1_DIGEST_LENGTH,
|
||||||
|
SHA1_BLOCK_LENGTH,
|
||||||
sizeof(SHA1_CTX),
|
sizeof(SHA1_CTX),
|
||||||
(hash_init_func_t)SHA1_Init,
|
(rb_digest_hash_init_func_t)SHA1_Init,
|
||||||
(hash_update_func_t)SHA1_Update,
|
(rb_digest_hash_update_func_t)SHA1_Update,
|
||||||
(hash_finish_func_t)SHA1_Finish,
|
(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
|
void
|
||||||
Init_sha1()
|
Init_sha1()
|
||||||
{
|
{
|
||||||
VALUE mDigest, cDigest_Base, cDigest_SHA1;
|
VALUE mDigest, cDigest_Base, cDigest_SHA1;
|
||||||
|
|
||||||
rb_require("digest");
|
rb_require("digest");
|
||||||
|
|
||||||
mDigest = rb_path2class("Digest");
|
mDigest = rb_path2class("Digest");
|
||||||
cDigest_Base = rb_path2class("Digest::Base");
|
cDigest_Base = rb_path2class("Digest::Base");
|
||||||
|
|
||||||
cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_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"),
|
rb_ivar_set(cDigest_SHA1, rb_intern("metadata"),
|
||||||
Data_Wrap_Struct(rb_cObject, 0, 0, &sha1));
|
Data_Wrap_Struct(rb_cObject, 0, 0, &sha1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,23 @@
|
||||||
#define FOREACH_BITLEN(func) func(256) func(384) func(512)
|
#define FOREACH_BITLEN(func) func(256) func(384) func(512)
|
||||||
|
|
||||||
#define DEFINE_ALGO_METADATA(bitlen) \
|
#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##_DIGEST_LENGTH, \
|
||||||
|
SHA##bitlen##_BLOCK_LENGTH, \
|
||||||
sizeof(SHA##bitlen##_CTX), \
|
sizeof(SHA##bitlen##_CTX), \
|
||||||
(hash_init_func_t)SHA##bitlen##_Init, \
|
(rb_digest_hash_init_func_t)SHA##bitlen##_Init, \
|
||||||
(hash_update_func_t)SHA##bitlen##_Update, \
|
(rb_digest_hash_update_func_t)SHA##bitlen##_Update, \
|
||||||
(hash_finish_func_t)SHA##bitlen##_Finish, \
|
(rb_digest_hash_finish_func_t)SHA##bitlen##_Finish, \
|
||||||
};
|
};
|
||||||
|
|
||||||
FOREACH_BITLEN(DEFINE_ALGO_METADATA)
|
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
|
void
|
||||||
Init_sha2()
|
Init_sha2()
|
||||||
{
|
{
|
||||||
|
@ -37,9 +44,6 @@ Init_sha2()
|
||||||
|
|
||||||
#define DEFINE_ALGO_CLASS(bitlen) \
|
#define DEFINE_ALGO_CLASS(bitlen) \
|
||||||
cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \
|
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, \
|
rb_ivar_set(cDigest_SHA##bitlen, id_metadata, \
|
||||||
Data_Wrap_Struct(rb_cObject, 0, 0, &sha##bitlen));
|
Data_Wrap_Struct(rb_cObject, 0, 0, &sha##bitlen));
|
||||||
|
|
|
@ -11,8 +11,6 @@ ${RUBY} extconf.rb --with-cflags="${CFLAGS}"
|
||||||
${MAKE} clean
|
${MAKE} clean
|
||||||
${MAKE}
|
${MAKE}
|
||||||
|
|
||||||
mkdir -p lib/digest
|
|
||||||
|
|
||||||
for algo in md5 rmd160 sha1 sha2; do
|
for algo in md5 rmd160 sha1 sha2; do
|
||||||
args=--with-cflags="${CFLAGS}"
|
args=--with-cflags="${CFLAGS}"
|
||||||
|
|
||||||
|
@ -27,7 +25,6 @@ for algo in md5 rmd160 sha1 sha2; do
|
||||||
ln -sf ../../$algo/$algo.so lib/digest/
|
ln -sf ../../$algo/$algo.so lib/digest/
|
||||||
done
|
done
|
||||||
|
|
||||||
${RUBY} -I. -I./lib test.rb
|
${RUBY} -I. -I./lib ../../test/digest/test_digest.rb
|
||||||
|
|
||||||
rm lib/digest/*.so
|
rm lib/digest/*.so
|
||||||
rmdir lib/digest
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ require 'digest'
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
include Digest
|
|
||||||
|
|
||||||
module TestDigest
|
module TestDigest
|
||||||
Data1 = "abc"
|
Data1 = "abc"
|
||||||
|
@ -44,7 +43,8 @@ module TestDigest
|
||||||
def test_eq
|
def test_eq
|
||||||
# This test is also for clone()
|
# 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)
|
assert_equal(md1, md1.clone, self.class::ALGO)
|
||||||
|
|
||||||
|
@ -66,55 +66,55 @@ module TestDigest
|
||||||
|
|
||||||
class TestMD5 < Test::Unit::TestCase
|
class TestMD5 < Test::Unit::TestCase
|
||||||
include TestDigest
|
include TestDigest
|
||||||
ALGO = MD5
|
ALGO = Digest::MD5
|
||||||
DATA = {
|
DATA = {
|
||||||
Data1 => "900150983cd24fb0d6963f7d28e17f72",
|
Data1 => "900150983cd24fb0d6963f7d28e17f72",
|
||||||
Data2 => "8215ef0796a20bcaaae116d3876c664a",
|
Data2 => "8215ef0796a20bcaaae116d3876c664a",
|
||||||
}
|
}
|
||||||
end if defined?(MD5)
|
end if defined?(Digest::MD5)
|
||||||
|
|
||||||
class TestSHA1 < Test::Unit::TestCase
|
class TestSHA1 < Test::Unit::TestCase
|
||||||
include TestDigest
|
include TestDigest
|
||||||
ALGO = SHA1
|
ALGO = Digest::SHA1
|
||||||
DATA = {
|
DATA = {
|
||||||
Data1 => "a9993e364706816aba3e25717850c26c9cd0d89d",
|
Data1 => "a9993e364706816aba3e25717850c26c9cd0d89d",
|
||||||
Data2 => "84983e441c3bd26ebaae4aa1f95129e5e54670f1",
|
Data2 => "84983e441c3bd26ebaae4aa1f95129e5e54670f1",
|
||||||
}
|
}
|
||||||
end if defined?(SHA1)
|
end if defined?(Digest::SHA1)
|
||||||
|
|
||||||
class TestSHA256 < Test::Unit::TestCase
|
class TestSHA256 < Test::Unit::TestCase
|
||||||
include TestDigest
|
include TestDigest
|
||||||
ALGO = SHA256
|
ALGO = Digest::SHA256
|
||||||
DATA = {
|
DATA = {
|
||||||
Data1 => "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
Data1 => "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||||
Data2 => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
|
Data2 => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
|
||||||
}
|
}
|
||||||
end if defined?(SHA256)
|
end if defined?(Digest::SHA256)
|
||||||
|
|
||||||
class TestSHA384 < Test::Unit::TestCase
|
class TestSHA384 < Test::Unit::TestCase
|
||||||
include TestDigest
|
include TestDigest
|
||||||
ALGO = SHA384
|
ALGO = Digest::SHA384
|
||||||
DATA = {
|
DATA = {
|
||||||
Data1 => "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7",
|
Data1 => "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7",
|
||||||
Data2 => "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b",
|
Data2 => "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b",
|
||||||
}
|
}
|
||||||
end if defined?(SHA384)
|
end if defined?(Digest::SHA384)
|
||||||
|
|
||||||
class TestSHA512 < Test::Unit::TestCase
|
class TestSHA512 < Test::Unit::TestCase
|
||||||
include TestDigest
|
include TestDigest
|
||||||
ALGO = SHA512
|
ALGO = Digest::SHA512
|
||||||
DATA = {
|
DATA = {
|
||||||
Data1 => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
|
Data1 => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
|
||||||
Data2 => "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445",
|
Data2 => "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445",
|
||||||
}
|
}
|
||||||
end if defined?(SHA512)
|
end if defined?(Digest::SHA512)
|
||||||
|
|
||||||
class TestRMD160 < Test::Unit::TestCase
|
class TestRMD160 < Test::Unit::TestCase
|
||||||
include TestDigest
|
include TestDigest
|
||||||
ALGO = RMD160
|
ALGO = Digest::RMD160
|
||||||
DATA = {
|
DATA = {
|
||||||
Data1 => "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
|
Data1 => "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
|
||||||
Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
|
Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
|
||||||
}
|
}
|
||||||
end if defined?(RMD160)
|
end if defined?(Digest::RMD160)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue