Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /************************************************ 00002 00003 digest.c - 00004 00005 $Author: eregon $ 00006 created at: Fri May 25 08:57:27 JST 2001 00007 00008 Copyright (C) 1995-2001 Yukihiro Matsumoto 00009 Copyright (C) 2001-2006 Akinori MUSHA 00010 00011 $RoughId: digest.c,v 1.16 2001/07/13 15:38:27 knu Exp $ 00012 $Id: digest.c 36588 2012-08-01 13:30:51Z eregon $ 00013 00014 ************************************************/ 00015 00016 #include "digest.h" 00017 00018 static VALUE rb_mDigest; 00019 static VALUE rb_mDigest_Instance; 00020 static VALUE rb_cDigest_Class; 00021 static VALUE rb_cDigest_Base; 00022 00023 static ID id_reset, id_update, id_finish, id_digest, id_hexdigest, id_digest_length; 00024 static ID id_metadata; 00025 00026 RUBY_EXTERN void Init_digest_base(void); 00027 00028 /* 00029 * Document-module: Digest 00030 * 00031 * This module provides a framework for message digest libraries. 00032 * 00033 * You may want to look at OpenSSL::Digest as it supports support more 00034 * algorithms. 00035 * 00036 * A cryptographic hash function is a procedure that takes data and return a 00037 * fixed bit string : the hash value, also known as _digest_. Hash functions 00038 * are also called one-way functions, it is easy to compute a digest from 00039 * a message, but it is infeasible to generate a message from a digest. 00040 * 00041 * == Example 00042 * 00043 * require 'digest' 00044 * 00045 * # Compute a complete digest 00046 * sha256 = Digest::SHA256.new 00047 * digest = sha256.digest message 00048 * 00049 * # Compute digest by chunks 00050 * sha256 = Digest::SHA256.new 00051 * sha256.update message1 00052 * sha256 << message2 # << is an alias for update 00053 * 00054 * digest = sha256.digest 00055 * 00056 * == Digest algorithms 00057 * 00058 * Different digest algorithms (or hash functions) are available : 00059 * 00060 * HMAC:: 00061 * See FIPS PUB 198 The Keyed-Hash Message Authentication Code (HMAC) 00062 * RIPEMD-160:: 00063 * (as Digest::RMD160) see 00064 * http://homes.esat.kuleuven.be/~bosselae/ripemd160.html 00065 * SHA1:: 00066 * See FIPS 180 Secure Hash Standard 00067 * SHA2 family:: 00068 * See FIPS 180 Secure Hash Standard which defines the following algorithms: 00069 * * SHA512 00070 * * SHA384 00071 * * SHA256 00072 * 00073 * The latest versions of the FIPS publications can be found here: 00074 * http://csrc.nist.gov/publications/PubsFIPS.html 00075 * 00076 * Additionally Digest::BubbleBabble encodes a digest as a sequence of 00077 * consonants and vowels which is more recognizable and comparable than a 00078 * hexadecimal digest. See http://en.wikipedia.org/wiki/Bubblebabble 00079 */ 00080 00081 static VALUE 00082 hexencode_str_new(VALUE str_digest) 00083 { 00084 char *digest; 00085 size_t digest_len; 00086 size_t i; 00087 VALUE str; 00088 char *p; 00089 static const char hex[] = { 00090 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 00091 'a', 'b', 'c', 'd', 'e', 'f' 00092 }; 00093 00094 StringValue(str_digest); 00095 digest = RSTRING_PTR(str_digest); 00096 digest_len = RSTRING_LEN(str_digest); 00097 00098 if (LONG_MAX / 2 < digest_len) { 00099 rb_raise(rb_eRuntimeError, "digest string too long"); 00100 } 00101 00102 str = rb_usascii_str_new(0, digest_len * 2); 00103 00104 for (i = 0, p = RSTRING_PTR(str); i < digest_len; i++) { 00105 unsigned char byte = digest[i]; 00106 00107 p[i + i] = hex[byte >> 4]; 00108 p[i + i + 1] = hex[byte & 0x0f]; 00109 } 00110 00111 return str; 00112 } 00113 00114 /* 00115 * call-seq: 00116 * Digest.hexencode(string) -> hexencoded_string 00117 * 00118 * Generates a hex-encoded version of a given _string_. 00119 */ 00120 static VALUE 00121 rb_digest_s_hexencode(VALUE klass, VALUE str) 00122 { 00123 return hexencode_str_new(str); 00124 } 00125 00126 NORETURN(static void rb_digest_instance_method_unimpl(VALUE self, const char *method)); 00127 00128 /* 00129 * Document-module: Digest::Instance 00130 * 00131 * This module provides instance methods for a digest implementation 00132 * object to calculate message digest values. 00133 */ 00134 00135 static void 00136 rb_digest_instance_method_unimpl(VALUE self, const char *method) 00137 { 00138 rb_raise(rb_eRuntimeError, "%s does not implement %s()", 00139 rb_obj_classname(self), method); 00140 } 00141 00142 /* 00143 * call-seq: 00144 * digest_obj.update(string) -> digest_obj 00145 * digest_obj << string -> digest_obj 00146 * 00147 * Updates the digest using a given _string_ and returns self. 00148 * 00149 * The update() method and the left-shift operator are overridden by 00150 * each implementation subclass. (One should be an alias for the 00151 * other) 00152 */ 00153 static VALUE 00154 rb_digest_instance_update(VALUE self, VALUE str) 00155 { 00156 rb_digest_instance_method_unimpl(self, "update"); 00157 00158 UNREACHABLE; 00159 } 00160 00161 /* 00162 * call-seq: 00163 * digest_obj.instance_eval { finish } -> digest_obj 00164 * 00165 * Finishes the digest and returns the resulting hash value. 00166 * 00167 * This method is overridden by each implementation subclass and often 00168 * made private, because some of those subclasses may leave internal 00169 * data uninitialized. Do not call this method from outside. Use 00170 * #digest!() instead, which ensures that internal data be reset for 00171 * security reasons. 00172 */ 00173 static VALUE 00174 rb_digest_instance_finish(VALUE self) 00175 { 00176 rb_digest_instance_method_unimpl(self, "finish"); 00177 00178 UNREACHABLE; 00179 } 00180 00181 /* 00182 * call-seq: 00183 * digest_obj.reset -> digest_obj 00184 * 00185 * Resets the digest to the initial state and returns self. 00186 * 00187 * This method is overridden by each implementation subclass. 00188 */ 00189 static VALUE 00190 rb_digest_instance_reset(VALUE self) 00191 { 00192 rb_digest_instance_method_unimpl(self, "reset"); 00193 00194 UNREACHABLE; 00195 } 00196 00197 /* 00198 * call-seq: 00199 * digest_obj.new -> another_digest_obj 00200 * 00201 * Returns a new, initialized copy of the digest object. Equivalent 00202 * to digest_obj.clone().reset(). 00203 */ 00204 static VALUE 00205 rb_digest_instance_new(VALUE self) 00206 { 00207 VALUE clone = rb_obj_clone(self); 00208 rb_funcall(clone, id_reset, 0); 00209 return clone; 00210 } 00211 00212 /* 00213 * call-seq: 00214 * digest_obj.digest -> string 00215 * digest_obj.digest(string) -> string 00216 * 00217 * If none is given, returns the resulting hash value of the digest, 00218 * keeping the digest's state. 00219 * 00220 * If a _string_ is given, returns the hash value for the given 00221 * _string_, resetting the digest to the initial state before and 00222 * after the process. 00223 */ 00224 static VALUE 00225 rb_digest_instance_digest(int argc, VALUE *argv, VALUE self) 00226 { 00227 VALUE str, value; 00228 00229 if (rb_scan_args(argc, argv, "01", &str) > 0) { 00230 rb_funcall(self, id_reset, 0); 00231 rb_funcall(self, id_update, 1, str); 00232 value = rb_funcall(self, id_finish, 0); 00233 rb_funcall(self, id_reset, 0); 00234 } else { 00235 value = rb_funcall(rb_obj_clone(self), id_finish, 0); 00236 } 00237 00238 return value; 00239 } 00240 00241 /* 00242 * call-seq: 00243 * digest_obj.digest! -> string 00244 * 00245 * Returns the resulting hash value and resets the digest to the 00246 * initial state. 00247 */ 00248 static VALUE 00249 rb_digest_instance_digest_bang(VALUE self) 00250 { 00251 VALUE value = rb_funcall(self, id_finish, 0); 00252 rb_funcall(self, id_reset, 0); 00253 00254 return value; 00255 } 00256 00257 /* 00258 * call-seq: 00259 * digest_obj.hexdigest -> string 00260 * digest_obj.hexdigest(string) -> string 00261 * 00262 * If none is given, returns the resulting hash value of the digest in 00263 * a hex-encoded form, keeping the digest's state. 00264 * 00265 * If a _string_ is given, returns the hash value for the given 00266 * _string_ in a hex-encoded form, resetting the digest to the initial 00267 * state before and after the process. 00268 */ 00269 static VALUE 00270 rb_digest_instance_hexdigest(int argc, VALUE *argv, VALUE self) 00271 { 00272 VALUE str, value; 00273 00274 if (rb_scan_args(argc, argv, "01", &str) > 0) { 00275 rb_funcall(self, id_reset, 0); 00276 rb_funcall(self, id_update, 1, str); 00277 value = rb_funcall(self, id_finish, 0); 00278 rb_funcall(self, id_reset, 0); 00279 } else { 00280 value = rb_funcall(rb_obj_clone(self), id_finish, 0); 00281 } 00282 00283 return hexencode_str_new(value); 00284 } 00285 00286 /* 00287 * call-seq: 00288 * digest_obj.hexdigest! -> string 00289 * 00290 * Returns the resulting hash value in a hex-encoded form and resets 00291 * the digest to the initial state. 00292 */ 00293 static VALUE 00294 rb_digest_instance_hexdigest_bang(VALUE self) 00295 { 00296 VALUE value = rb_funcall(self, id_finish, 0); 00297 rb_funcall(self, id_reset, 0); 00298 00299 return hexencode_str_new(value); 00300 } 00301 00302 /* 00303 * call-seq: 00304 * digest_obj.to_s -> string 00305 * 00306 * Returns digest_obj.hexdigest(). 00307 */ 00308 static VALUE 00309 rb_digest_instance_to_s(VALUE self) 00310 { 00311 return rb_funcall(self, id_hexdigest, 0); 00312 } 00313 00314 /* 00315 * call-seq: 00316 * digest_obj.inspect -> string 00317 * 00318 * Creates a printable version of the digest object. 00319 */ 00320 static VALUE 00321 rb_digest_instance_inspect(VALUE self) 00322 { 00323 VALUE str; 00324 size_t digest_len = 32; /* about this size at least */ 00325 const char *cname; 00326 00327 cname = rb_obj_classname(self); 00328 00329 /* #<Digest::ClassName: xxxxx...xxxx> */ 00330 str = rb_str_buf_new(2 + strlen(cname) + 2 + digest_len * 2 + 1); 00331 rb_str_buf_cat2(str, "#<"); 00332 rb_str_buf_cat2(str, cname); 00333 rb_str_buf_cat2(str, ": "); 00334 rb_str_buf_append(str, rb_digest_instance_hexdigest(0, 0, self)); 00335 rb_str_buf_cat2(str, ">"); 00336 return str; 00337 } 00338 00339 /* 00340 * call-seq: 00341 * digest_obj == another_digest_obj -> boolean 00342 * digest_obj == string -> boolean 00343 * 00344 * If a string is given, checks whether it is equal to the hex-encoded 00345 * hash value of the digest object. If another digest instance is 00346 * given, checks whether they have the same hash value. Otherwise 00347 * returns false. 00348 */ 00349 static VALUE 00350 rb_digest_instance_equal(VALUE self, VALUE other) 00351 { 00352 VALUE str1, str2; 00353 00354 if (rb_obj_is_kind_of(other, rb_mDigest_Instance) == Qtrue) { 00355 str1 = rb_digest_instance_digest(0, 0, self); 00356 str2 = rb_digest_instance_digest(0, 0, other); 00357 } else { 00358 str1 = rb_digest_instance_to_s(self); 00359 str2 = other; 00360 } 00361 00362 /* never blindly assume that subclass methods return strings */ 00363 StringValue(str1); 00364 StringValue(str2); 00365 00366 if (RSTRING_LEN(str1) == RSTRING_LEN(str2) && 00367 rb_str_cmp(str1, str2) == 0) { 00368 return Qtrue; 00369 } 00370 return Qfalse; 00371 } 00372 00373 /* 00374 * call-seq: 00375 * digest_obj.digest_length -> integer 00376 * 00377 * Returns the length of the hash value of the digest. 00378 * 00379 * This method should be overridden by each implementation subclass. 00380 * If not, digest_obj.digest().length() is returned. 00381 */ 00382 static VALUE 00383 rb_digest_instance_digest_length(VALUE self) 00384 { 00385 /* subclasses really should redefine this method */ 00386 VALUE digest = rb_digest_instance_digest(0, 0, self); 00387 00388 /* never blindly assume that #digest() returns a string */ 00389 StringValue(digest); 00390 return INT2NUM(RSTRING_LEN(digest)); 00391 } 00392 00393 /* 00394 * call-seq: 00395 * digest_obj.length -> integer 00396 * digest_obj.size -> integer 00397 * 00398 * Returns digest_obj.digest_length(). 00399 */ 00400 static VALUE 00401 rb_digest_instance_length(VALUE self) 00402 { 00403 return rb_funcall(self, id_digest_length, 0); 00404 } 00405 00406 /* 00407 * call-seq: 00408 * digest_obj.block_length -> integer 00409 * 00410 * Returns the block length of the digest. 00411 * 00412 * This method is overridden by each implementation subclass. 00413 */ 00414 static VALUE 00415 rb_digest_instance_block_length(VALUE self) 00416 { 00417 rb_digest_instance_method_unimpl(self, "block_length"); 00418 00419 UNREACHABLE; 00420 } 00421 00422 /* 00423 * Document-class: Digest::Class 00424 * 00425 * This module stands as a base class for digest implementation 00426 * classes. 00427 */ 00428 00429 /* 00430 * call-seq: 00431 * Digest::Class.digest(string, *parameters) -> hash_string 00432 * 00433 * Returns the hash value of a given _string_. This is equivalent to 00434 * Digest::Class.new(*parameters).digest(string), where extra 00435 * _parameters_, if any, are passed through to the constructor and the 00436 * _string_ is passed to #digest(). 00437 */ 00438 static VALUE 00439 rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass) 00440 { 00441 VALUE str; 00442 volatile VALUE obj; 00443 00444 if (argc < 1) { 00445 rb_raise(rb_eArgError, "no data given"); 00446 } 00447 00448 str = *argv++; 00449 argc--; 00450 00451 StringValue(str); 00452 00453 obj = rb_obj_alloc(klass); 00454 rb_obj_call_init(obj, argc, argv); 00455 00456 return rb_funcall(obj, id_digest, 1, str); 00457 } 00458 00459 /* 00460 * call-seq: 00461 * Digest::Class.hexdigest(string[, ...]) -> hash_string 00462 * 00463 * Returns the hex-encoded hash value of a given _string_. This is 00464 * almost equivalent to 00465 * Digest.hexencode(Digest::Class.new(*parameters).digest(string)). 00466 */ 00467 static VALUE 00468 rb_digest_class_s_hexdigest(int argc, VALUE *argv, VALUE klass) 00469 { 00470 return hexencode_str_new(rb_funcall2(klass, id_digest, argc, argv)); 00471 } 00472 00473 /* :nodoc: */ 00474 static VALUE 00475 rb_digest_class_init(VALUE self) 00476 { 00477 return self; 00478 } 00479 00480 /* 00481 * Document-class: Digest::Base 00482 * 00483 * This abstract class provides a common interface to message digest 00484 * implementation classes written in C. 00485 */ 00486 00487 static rb_digest_metadata_t * 00488 get_digest_base_metadata(VALUE klass) 00489 { 00490 VALUE p; 00491 VALUE obj; 00492 rb_digest_metadata_t *algo; 00493 00494 for (p = klass; !NIL_P(p); p = rb_class_superclass(p)) { 00495 if (rb_ivar_defined(p, id_metadata)) { 00496 obj = rb_ivar_get(p, id_metadata); 00497 break; 00498 } 00499 } 00500 00501 if (NIL_P(p)) 00502 rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby"); 00503 00504 Data_Get_Struct(obj, rb_digest_metadata_t, algo); 00505 00506 switch (algo->api_version) { 00507 case 2: 00508 break; 00509 00510 /* 00511 * put conversion here if possible when API is updated 00512 */ 00513 00514 default: 00515 rb_raise(rb_eRuntimeError, "Incompatible digest API version"); 00516 } 00517 00518 return algo; 00519 } 00520 00521 static VALUE 00522 rb_digest_base_alloc(VALUE klass) 00523 { 00524 rb_digest_metadata_t *algo; 00525 VALUE obj; 00526 void *pctx; 00527 00528 if (klass == rb_cDigest_Base) { 00529 rb_raise(rb_eNotImpError, "Digest::Base is an abstract class"); 00530 } 00531 00532 algo = get_digest_base_metadata(klass); 00533 00534 pctx = xmalloc(algo->ctx_size); 00535 algo->init_func(pctx); 00536 00537 obj = Data_Wrap_Struct(klass, 0, xfree, pctx); 00538 00539 return obj; 00540 } 00541 00542 /* :nodoc: */ 00543 static VALUE 00544 rb_digest_base_copy(VALUE copy, VALUE obj) 00545 { 00546 rb_digest_metadata_t *algo; 00547 void *pctx1, *pctx2; 00548 00549 if (copy == obj) return copy; 00550 00551 rb_check_frozen(copy); 00552 00553 algo = get_digest_base_metadata(rb_obj_class(copy)); 00554 00555 Data_Get_Struct(obj, void, pctx1); 00556 Data_Get_Struct(copy, void, pctx2); 00557 memcpy(pctx2, pctx1, algo->ctx_size); 00558 00559 return copy; 00560 } 00561 00562 /* :nodoc: */ 00563 static VALUE 00564 rb_digest_base_reset(VALUE self) 00565 { 00566 rb_digest_metadata_t *algo; 00567 void *pctx; 00568 00569 algo = get_digest_base_metadata(rb_obj_class(self)); 00570 00571 Data_Get_Struct(self, void, pctx); 00572 00573 algo->init_func(pctx); 00574 00575 return self; 00576 } 00577 00578 /* :nodoc: */ 00579 static VALUE 00580 rb_digest_base_update(VALUE self, VALUE str) 00581 { 00582 rb_digest_metadata_t *algo; 00583 void *pctx; 00584 00585 algo = get_digest_base_metadata(rb_obj_class(self)); 00586 00587 Data_Get_Struct(self, void, pctx); 00588 00589 StringValue(str); 00590 algo->update_func(pctx, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)); 00591 00592 return self; 00593 } 00594 00595 /* :nodoc: */ 00596 static VALUE 00597 rb_digest_base_finish(VALUE self) 00598 { 00599 rb_digest_metadata_t *algo; 00600 void *pctx; 00601 VALUE str; 00602 00603 algo = get_digest_base_metadata(rb_obj_class(self)); 00604 00605 Data_Get_Struct(self, void, pctx); 00606 00607 str = rb_str_new(0, algo->digest_len); 00608 algo->finish_func(pctx, (unsigned char *)RSTRING_PTR(str)); 00609 00610 /* avoid potential coredump caused by use of a finished context */ 00611 algo->init_func(pctx); 00612 00613 return str; 00614 } 00615 00616 /* :nodoc: */ 00617 static VALUE 00618 rb_digest_base_digest_length(VALUE self) 00619 { 00620 rb_digest_metadata_t *algo; 00621 00622 algo = get_digest_base_metadata(rb_obj_class(self)); 00623 00624 return INT2NUM(algo->digest_len); 00625 } 00626 00627 /* :nodoc: */ 00628 static VALUE 00629 rb_digest_base_block_length(VALUE self) 00630 { 00631 rb_digest_metadata_t *algo; 00632 00633 algo = get_digest_base_metadata(rb_obj_class(self)); 00634 00635 return INT2NUM(algo->block_len); 00636 } 00637 00638 void 00639 Init_digest(void) 00640 { 00641 id_reset = rb_intern("reset"); 00642 id_update = rb_intern("update"); 00643 id_finish = rb_intern("finish"); 00644 id_digest = rb_intern("digest"); 00645 id_hexdigest = rb_intern("hexdigest"); 00646 id_digest_length = rb_intern("digest_length"); 00647 00648 /* 00649 * module Digest 00650 */ 00651 rb_mDigest = rb_define_module("Digest"); 00652 00653 /* module functions */ 00654 rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1); 00655 00656 /* 00657 * module Digest::Instance 00658 */ 00659 rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance"); 00660 00661 /* instance methods that should be overridden */ 00662 rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1); 00663 rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1); 00664 rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0); 00665 rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0); 00666 rb_define_method(rb_mDigest_Instance, "digest_length", rb_digest_instance_digest_length, 0); 00667 rb_define_method(rb_mDigest_Instance, "block_length", rb_digest_instance_block_length, 0); 00668 00669 /* instance methods that may be overridden */ 00670 rb_define_method(rb_mDigest_Instance, "==", rb_digest_instance_equal, 1); 00671 rb_define_method(rb_mDigest_Instance, "inspect", rb_digest_instance_inspect, 0); 00672 00673 /* instance methods that need not usually be overridden */ 00674 rb_define_method(rb_mDigest_Instance, "new", rb_digest_instance_new, 0); 00675 rb_define_method(rb_mDigest_Instance, "digest", rb_digest_instance_digest, -1); 00676 rb_define_method(rb_mDigest_Instance, "digest!", rb_digest_instance_digest_bang, 0); 00677 rb_define_method(rb_mDigest_Instance, "hexdigest", rb_digest_instance_hexdigest, -1); 00678 rb_define_method(rb_mDigest_Instance, "hexdigest!", rb_digest_instance_hexdigest_bang, 0); 00679 rb_define_method(rb_mDigest_Instance, "to_s", rb_digest_instance_to_s, 0); 00680 rb_define_method(rb_mDigest_Instance, "length", rb_digest_instance_length, 0); 00681 rb_define_method(rb_mDigest_Instance, "size", rb_digest_instance_length, 0); 00682 00683 /* 00684 * class Digest::Class 00685 */ 00686 rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject); 00687 rb_define_method(rb_cDigest_Class, "initialize", rb_digest_class_init, 0); 00688 rb_include_module(rb_cDigest_Class, rb_mDigest_Instance); 00689 00690 /* class methods */ 00691 rb_define_singleton_method(rb_cDigest_Class, "digest", rb_digest_class_s_digest, -1); 00692 rb_define_singleton_method(rb_cDigest_Class, "hexdigest", rb_digest_class_s_hexdigest, -1); 00693 00694 id_metadata = rb_intern("metadata"); 00695 00696 /* class Digest::Base < Digest::Class */ 00697 rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class); 00698 00699 rb_define_alloc_func(rb_cDigest_Base, rb_digest_base_alloc); 00700 00701 rb_define_method(rb_cDigest_Base, "initialize_copy", rb_digest_base_copy, 1); 00702 rb_define_method(rb_cDigest_Base, "reset", rb_digest_base_reset, 0); 00703 rb_define_method(rb_cDigest_Base, "update", rb_digest_base_update, 1); 00704 rb_define_method(rb_cDigest_Base, "<<", rb_digest_base_update, 1); 00705 rb_define_private_method(rb_cDigest_Base, "finish", rb_digest_base_finish, 0); 00706 rb_define_method(rb_cDigest_Base, "digest_length", rb_digest_base_digest_length, 0); 00707 rb_define_method(rb_cDigest_Base, "block_length", rb_digest_base_block_length, 0); 00708 } 00709