1 /************************************************
6 created at: Fri May 25 08:57:27 JST 2001
8 Copyright (C) 1995-2001 Yukihiro Matsumoto
9 Copyright (C) 2001-2006 Akinori MUSHA
11 $RoughId: digest.c,v 1.16 2001/07/13 15:38:27 knu Exp $
12 $Id: digest.c 17775 2008-07-01 10:36:22Z shyouhei $
14 ************************************************/
18 static VALUE rb_mDigest;
19 static VALUE rb_mDigest_Instance;
20 static VALUE rb_cDigest_Class;
21 static VALUE rb_cDigest_Base;
23 static ID id_reset, id_update, id_finish, id_digest, id_hexdigest, id_digest_length;
24 static ID id_metadata;
26 RUBY_EXTERN void Init_digest_base(void);
29 * Document-module: Digest
31 * This module provides a framework for message digest libraries.
35 hexencode_str_new(VALUE str_digest)
42 static const char hex[] = {
43 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
44 'a', 'b', 'c', 'd', 'e', 'f'
47 StringValue(str_digest);
48 digest = RSTRING_PTR(str_digest);
49 digest_len = RSTRING_LEN(str_digest);
51 if (LONG_MAX / 2 < digest_len) {
52 rb_raise(rb_eRuntimeError, "digest string too long");
55 str = rb_str_new(0, digest_len * 2);
57 for (i = 0, p = RSTRING_PTR(str); i < digest_len; i++) {
58 unsigned char byte = digest[i];
60 p[i + i] = hex[byte >> 4];
61 p[i + i + 1] = hex[byte & 0x0f];
69 * Digest.hexencode(string) -> hexencoded_string
71 * Generates a hex-encoded version of a given _string_.
74 rb_digest_s_hexencode(VALUE klass, VALUE str)
76 return hexencode_str_new(str);
80 * Document-module: Digest::Instance
82 * This module provides instance methods for a digest implementation
83 * object to calculate message digest values.
88 * digest_obj.update(string) -> digest_obj
89 * digest_obj << string -> digest_obj
91 * Updates the digest using a given _string_ and returns self.
93 * The update() method and the left-shift operator are overridden by
94 * each implementation subclass. (One should be an alias for the
98 rb_digest_instance_update(VALUE self, VALUE str)
100 rb_raise(rb_eRuntimeError, "%s does not implement update()", RSTRING_PTR(rb_inspect(self)));
105 * digest_obj.instance_eval { finish } -> digest_obj
107 * Finishes the digest and returns the resulting hash value.
109 * This method is overridden by each implementation subclass and often
110 * made private, because some of those subclasses may leave internal
111 * data uninitialized. Do not call this method from outside. Use
112 * #digest!() instead, which ensures that internal data be reset for
116 rb_digest_instance_finish(VALUE self)
118 rb_raise(rb_eRuntimeError, "%s does not implement finish()", RSTRING_PTR(rb_inspect(self)));
123 * digest_obj.reset -> digest_obj
125 * Resets the digest to the initial state and returns self.
127 * This method is overridden by each implementation subclass.
130 rb_digest_instance_reset(VALUE self)
132 rb_raise(rb_eRuntimeError, "%s does not implement reset()", RSTRING_PTR(rb_inspect(self)));
137 * digest_obj.new -> another_digest_obj
139 * Returns a new, initialized copy of the digest object. Equivalent
140 * to digest_obj.clone().reset().
143 rb_digest_instance_new(VALUE self)
145 VALUE clone = rb_obj_clone(self);
146 rb_funcall(clone, id_reset, 0);
152 * digest_obj.digest -> string
153 * digest_obj.digest(string) -> string
155 * If none is given, returns the resulting hash value of the digest,
156 * keeping the digest's state.
158 * If a _string_ is given, returns the hash value for the given
159 * _string_, resetting the digest to the initial state before and
163 rb_digest_instance_digest(int argc, VALUE *argv, VALUE self)
167 if (rb_scan_args(argc, argv, "01", &str) > 0) {
168 rb_funcall(self, id_reset, 0);
169 rb_funcall(self, id_update, 1, str);
170 value = rb_funcall(self, id_finish, 0);
171 rb_funcall(self, id_reset, 0);
173 VALUE clone = rb_obj_clone(self);
175 value = rb_funcall(clone, id_finish, 0);
176 rb_funcall(clone, id_reset, 0);
184 * digest_obj.digest! -> string
186 * Returns the resulting hash value and resets the digest to the
190 rb_digest_instance_digest_bang(VALUE self)
192 VALUE value = rb_funcall(self, id_finish, 0);
193 rb_funcall(self, id_reset, 0);
200 * digest_obj.hexdigest -> string
201 * digest_obj.hexdigest(string) -> string
203 * If none is given, returns the resulting hash value of the digest in
204 * a hex-encoded form, keeping the digest's state.
206 * If a _string_ is given, returns the hash value for the given
207 * _string_ in a hex-encoded form, resetting the digest to the initial
208 * state before and after the process.
211 rb_digest_instance_hexdigest(int argc, VALUE *argv, VALUE self)
215 if (rb_scan_args(argc, argv, "01", &str) > 0) {
216 rb_funcall(self, id_reset, 0);
217 rb_funcall(self, id_update, 1, str);
218 value = rb_funcall(self, id_finish, 0);
219 rb_funcall(self, id_reset, 0);
221 VALUE clone = rb_obj_clone(self);
223 value = rb_funcall(clone, id_finish, 0);
224 rb_funcall(clone, id_reset, 0);
227 return hexencode_str_new(value);
232 * digest_obj.hexdigest! -> string
234 * Returns the resulting hash value and resets the digest to the
238 rb_digest_instance_hexdigest_bang(VALUE self)
240 VALUE value = rb_funcall(self, id_finish, 0);
241 rb_funcall(self, id_reset, 0);
243 return hexencode_str_new(value);
248 * digest_obj.to_s -> string
250 * Returns digest_obj.hexdigest().
253 rb_digest_instance_to_s(VALUE self)
255 return rb_funcall(self, id_hexdigest, 0);
260 * digest_obj.inspect -> string
262 * Creates a printable version of the digest object.
265 rb_digest_instance_inspect(VALUE self)
268 size_t digest_len = 32; /* about this size at least */
271 cname = rb_obj_classname(self);
273 /* #<Digest::ClassName: xxxxx...xxxx> */
274 str = rb_str_buf_new(2 + strlen(cname) + 2 + digest_len * 2 + 1);
275 rb_str_buf_cat2(str, "#<");
276 rb_str_buf_cat2(str, cname);
277 rb_str_buf_cat2(str, ": ");
278 rb_str_buf_append(str, rb_digest_instance_hexdigest(0, 0, self));
279 rb_str_buf_cat2(str, ">");
285 * digest_obj == another_digest_obj -> boolean
286 * digest_obj == string -> boolean
288 * If a string is given, checks whether it is equal to the hex-encoded
289 * hash value of the digest object. If another digest instance is
290 * given, checks whether they have the same hash value. Otherwise
294 rb_digest_instance_equal(VALUE self, VALUE other)
298 if (rb_obj_is_kind_of(other, rb_mDigest_Instance) == Qtrue) {
299 str1 = rb_digest_instance_digest(0, 0, self);
300 str2 = rb_digest_instance_digest(0, 0, other);
302 str1 = rb_digest_instance_to_s(self);
306 /* never blindly assume that subclass methods return strings */
310 if (RSTRING_LEN(str1) == RSTRING_LEN(str2) &&
311 rb_str_cmp(str1, str2) == 0) {
319 * digest_obj.digest_length -> integer
321 * Returns the length of the hash value of the digest.
323 * This method should be overridden by each implementation subclass.
324 * If not, digest_obj.digest().length() is returned.
327 rb_digest_instance_digest_length(VALUE self)
329 /* subclasses really should redefine this method */
330 VALUE digest = rb_digest_instance_digest(0, 0, self);
332 /* never blindly assume that #digest() returns a string */
334 return INT2NUM(RSTRING_LEN(digest));
339 * digest_obj.length -> integer
340 * digest_obj.size -> integer
342 * Returns digest_obj.digest_length().
345 rb_digest_instance_length(VALUE self)
347 return rb_funcall(self, id_digest_length, 0);
352 * digest_obj.block_length -> integer
354 * Returns the block length of the digest.
356 * This method is overridden by each implementation subclass.
359 rb_digest_instance_block_length(VALUE self)
361 rb_raise(rb_eRuntimeError, "%s does not implement block_length()", RSTRING_PTR(rb_inspect(self)));
365 * Document-class: Digest::Class
367 * This module stands as a base class for digest implementation
373 * Digest::Class.digest(string, *parameters) -> hash_string
375 * Returns the hash value of a given _string_. This is equivalent to
376 * Digest::Class.new(*parameters).digest(string), where extra
377 * _parameters_, if any, are passed through to the constructor and the
378 * _string_ is passed to #digest().
381 rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass)
387 rb_raise(rb_eArgError, "no data given");
395 obj = rb_obj_alloc(klass);
396 rb_obj_call_init(obj, argc, argv);
398 return rb_funcall(obj, id_digest, 1, str);
403 * Digest::Class.hexdigest(string[, ...]) -> hash_string
405 * Returns the hex-encoded hash value of a given _string_. This is
406 * almost equivalent to
407 * Digest.hexencode(Digest::Class.new(*parameters).digest(string)).
410 rb_digest_class_s_hexdigest(int argc, VALUE *argv, VALUE klass)
412 return hexencode_str_new(rb_funcall2(klass, id_digest, argc, argv));
416 * Document-class: Digest::Base
418 * This abstract class provides a common interface to message digest
419 * implementation classes written in C.
422 static rb_digest_metadata_t *
423 get_digest_base_metadata(VALUE klass)
427 rb_digest_metadata_t *algo;
429 for (p = klass; p; p = RCLASS_SUPER(p)) {
430 if (rb_ivar_defined(p, id_metadata)) {
431 obj = rb_ivar_get(p, id_metadata);
437 rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby");
439 Data_Get_Struct(obj, rb_digest_metadata_t, algo);
441 switch (algo->api_version) {
446 * put conversion here if possible when API is updated
450 rb_raise(rb_eRuntimeError, "Incompatible digest API version");
457 rb_digest_base_alloc(VALUE klass)
459 rb_digest_metadata_t *algo;
463 if (klass == rb_cDigest_Base) {
464 rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
467 algo = get_digest_base_metadata(klass);
469 pctx = xmalloc(algo->ctx_size);
470 algo->init_func(pctx);
472 obj = Data_Wrap_Struct(klass, 0, xfree, pctx);
479 rb_digest_base_copy(VALUE copy, VALUE obj)
481 rb_digest_metadata_t *algo;
484 if (copy == obj) return copy;
486 rb_check_frozen(copy);
488 algo = get_digest_base_metadata(rb_obj_class(copy));
490 Data_Get_Struct(obj, void, pctx1);
491 Data_Get_Struct(copy, void, pctx2);
492 memcpy(pctx2, pctx1, algo->ctx_size);
499 rb_digest_base_reset(VALUE self)
501 rb_digest_metadata_t *algo;
504 algo = get_digest_base_metadata(rb_obj_class(self));
506 Data_Get_Struct(self, void, pctx);
508 algo->init_func(pctx);
515 rb_digest_base_update(VALUE self, VALUE str)
517 rb_digest_metadata_t *algo;
520 algo = get_digest_base_metadata(rb_obj_class(self));
522 Data_Get_Struct(self, void, pctx);
525 algo->update_func(pctx, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
532 rb_digest_base_finish(VALUE self)
534 rb_digest_metadata_t *algo;
538 algo = get_digest_base_metadata(rb_obj_class(self));
540 Data_Get_Struct(self, void, pctx);
542 str = rb_str_new(0, algo->digest_len);
543 algo->finish_func(pctx, (unsigned char *)RSTRING_PTR(str));
545 /* avoid potential coredump caused by use of a finished context */
546 algo->init_func(pctx);
553 rb_digest_base_digest_length(VALUE self)
555 rb_digest_metadata_t *algo;
557 algo = get_digest_base_metadata(rb_obj_class(self));
559 return INT2NUM(algo->digest_len);
564 rb_digest_base_block_length(VALUE self)
566 rb_digest_metadata_t *algo;
568 algo = get_digest_base_metadata(rb_obj_class(self));
570 return INT2NUM(algo->block_len);
576 id_reset = rb_intern("reset");
577 id_update = rb_intern("update");
578 id_finish = rb_intern("finish");
579 id_digest = rb_intern("digest");
580 id_hexdigest = rb_intern("hexdigest");
581 id_digest_length = rb_intern("digest_length");
586 rb_mDigest = rb_define_module("Digest");
588 /* module functions */
589 rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1);
592 * module Digest::Instance
594 rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance");
596 /* instance methods that should be overridden */
597 rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1);
598 rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1);
599 rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0);
600 rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0);
601 rb_define_method(rb_mDigest_Instance, "digest_length", rb_digest_instance_digest_length, 0);
602 rb_define_method(rb_mDigest_Instance, "block_length", rb_digest_instance_block_length, 0);
604 /* instance methods that may be overridden */
605 rb_define_method(rb_mDigest_Instance, "==", rb_digest_instance_equal, 1);
606 rb_define_method(rb_mDigest_Instance, "inspect", rb_digest_instance_inspect, 0);
608 /* instance methods that need not usually be overridden */
609 rb_define_method(rb_mDigest_Instance, "new", rb_digest_instance_new, 0);
610 rb_define_method(rb_mDigest_Instance, "digest", rb_digest_instance_digest, -1);
611 rb_define_method(rb_mDigest_Instance, "digest!", rb_digest_instance_digest_bang, 0);
612 rb_define_method(rb_mDigest_Instance, "hexdigest", rb_digest_instance_hexdigest, -1);
613 rb_define_method(rb_mDigest_Instance, "hexdigest!", rb_digest_instance_hexdigest_bang, 0);
614 rb_define_method(rb_mDigest_Instance, "to_s", rb_digest_instance_to_s, 0);
615 rb_define_method(rb_mDigest_Instance, "length", rb_digest_instance_length, 0);
616 rb_define_method(rb_mDigest_Instance, "size", rb_digest_instance_length, 0);
619 * class Digest::Class
621 rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject);
622 rb_include_module(rb_cDigest_Class, rb_mDigest_Instance);
625 rb_define_singleton_method(rb_cDigest_Class, "digest", rb_digest_class_s_digest, -1);
626 rb_define_singleton_method(rb_cDigest_Class, "hexdigest", rb_digest_class_s_hexdigest, -1);
628 id_metadata = rb_intern("metadata");
630 /* class Digest::Base < Digest::Class */
631 rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class);
633 rb_define_alloc_func(rb_cDigest_Base, rb_digest_base_alloc);
635 rb_define_method(rb_cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
636 rb_define_method(rb_cDigest_Base, "reset", rb_digest_base_reset, 0);
637 rb_define_method(rb_cDigest_Base, "update", rb_digest_base_update, 1);
638 rb_define_method(rb_cDigest_Base, "<<", rb_digest_base_update, 1);
639 rb_define_private_method(rb_cDigest_Base, "finish", rb_digest_base_finish, 0);
640 rb_define_method(rb_cDigest_Base, "digest_length", rb_digest_base_digest_length, 0);
641 rb_define_method(rb_cDigest_Base, "block_length", rb_digest_base_block_length, 0);