|
Ruby
2.0.0p594(2014-10-27revision48167)
|
00001 /************************************************ 00002 00003 digest.c - 00004 00005 $Author: usa $ 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 47333 2014-08-31 07:11:29Z usa $ 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 = rb_check_string_type(other); 00360 if (NIL_P(str2)) return Qfalse; 00361 } 00362 00363 /* never blindly assume that subclass methods return strings */ 00364 StringValue(str1); 00365 StringValue(str2); 00366 00367 if (RSTRING_LEN(str1) == RSTRING_LEN(str2) && 00368 rb_str_cmp(str1, str2) == 0) { 00369 return Qtrue; 00370 } 00371 return Qfalse; 00372 } 00373 00374 /* 00375 * call-seq: 00376 * digest_obj.digest_length -> integer 00377 * 00378 * Returns the length of the hash value of the digest. 00379 * 00380 * This method should be overridden by each implementation subclass. 00381 * If not, digest_obj.digest().length() is returned. 00382 */ 00383 static VALUE 00384 rb_digest_instance_digest_length(VALUE self) 00385 { 00386 /* subclasses really should redefine this method */ 00387 VALUE digest = rb_digest_instance_digest(0, 0, self); 00388 00389 /* never blindly assume that #digest() returns a string */ 00390 StringValue(digest); 00391 return INT2NUM(RSTRING_LEN(digest)); 00392 } 00393 00394 /* 00395 * call-seq: 00396 * digest_obj.length -> integer 00397 * digest_obj.size -> integer 00398 * 00399 * Returns digest_obj.digest_length(). 00400 */ 00401 static VALUE 00402 rb_digest_instance_length(VALUE self) 00403 { 00404 return rb_funcall(self, id_digest_length, 0); 00405 } 00406 00407 /* 00408 * call-seq: 00409 * digest_obj.block_length -> integer 00410 * 00411 * Returns the block length of the digest. 00412 * 00413 * This method is overridden by each implementation subclass. 00414 */ 00415 static VALUE 00416 rb_digest_instance_block_length(VALUE self) 00417 { 00418 rb_digest_instance_method_unimpl(self, "block_length"); 00419 00420 UNREACHABLE; 00421 } 00422 00423 /* 00424 * Document-class: Digest::Class 00425 * 00426 * This module stands as a base class for digest implementation 00427 * classes. 00428 */ 00429 00430 /* 00431 * call-seq: 00432 * Digest::Class.digest(string, *parameters) -> hash_string 00433 * 00434 * Returns the hash value of a given _string_. This is equivalent to 00435 * Digest::Class.new(*parameters).digest(string), where extra 00436 * _parameters_, if any, are passed through to the constructor and the 00437 * _string_ is passed to #digest(). 00438 */ 00439 static VALUE 00440 rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass) 00441 { 00442 VALUE str; 00443 volatile VALUE obj; 00444 00445 if (argc < 1) { 00446 rb_raise(rb_eArgError, "no data given"); 00447 } 00448 00449 str = *argv++; 00450 argc--; 00451 00452 StringValue(str); 00453 00454 obj = rb_obj_alloc(klass); 00455 rb_obj_call_init(obj, argc, argv); 00456 00457 return rb_funcall(obj, id_digest, 1, str); 00458 } 00459 00460 /* 00461 * call-seq: 00462 * Digest::Class.hexdigest(string[, ...]) -> hash_string 00463 * 00464 * Returns the hex-encoded hash value of a given _string_. This is 00465 * almost equivalent to 00466 * Digest.hexencode(Digest::Class.new(*parameters).digest(string)). 00467 */ 00468 static VALUE 00469 rb_digest_class_s_hexdigest(int argc, VALUE *argv, VALUE klass) 00470 { 00471 return hexencode_str_new(rb_funcall2(klass, id_digest, argc, argv)); 00472 } 00473 00474 /* :nodoc: */ 00475 static VALUE 00476 rb_digest_class_init(VALUE self) 00477 { 00478 return self; 00479 } 00480 00481 /* 00482 * Document-class: Digest::Base 00483 * 00484 * This abstract class provides a common interface to message digest 00485 * implementation classes written in C. 00486 */ 00487 00488 static rb_digest_metadata_t * 00489 get_digest_base_metadata(VALUE klass) 00490 { 00491 VALUE p; 00492 VALUE obj; 00493 rb_digest_metadata_t *algo; 00494 00495 for (p = klass; !NIL_P(p); p = rb_class_superclass(p)) { 00496 if (rb_ivar_defined(p, id_metadata)) { 00497 obj = rb_ivar_get(p, id_metadata); 00498 break; 00499 } 00500 } 00501 00502 if (NIL_P(p)) 00503 rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby"); 00504 00505 Data_Get_Struct(obj, rb_digest_metadata_t, algo); 00506 00507 switch (algo->api_version) { 00508 case 2: 00509 break; 00510 00511 /* 00512 * put conversion here if possible when API is updated 00513 */ 00514 00515 default: 00516 rb_raise(rb_eRuntimeError, "Incompatible digest API version"); 00517 } 00518 00519 return algo; 00520 } 00521 00522 static VALUE 00523 rb_digest_base_alloc(VALUE klass) 00524 { 00525 rb_digest_metadata_t *algo; 00526 VALUE obj; 00527 void *pctx; 00528 00529 if (klass == rb_cDigest_Base) { 00530 rb_raise(rb_eNotImpError, "Digest::Base is an abstract class"); 00531 } 00532 00533 algo = get_digest_base_metadata(klass); 00534 00535 pctx = xmalloc(algo->ctx_size); 00536 algo->init_func(pctx); 00537 00538 obj = Data_Wrap_Struct(klass, 0, xfree, pctx); 00539 00540 return obj; 00541 } 00542 00543 /* :nodoc: */ 00544 static VALUE 00545 rb_digest_base_copy(VALUE copy, VALUE obj) 00546 { 00547 rb_digest_metadata_t *algo; 00548 void *pctx1, *pctx2; 00549 00550 if (copy == obj) return copy; 00551 00552 rb_check_frozen(copy); 00553 00554 algo = get_digest_base_metadata(rb_obj_class(copy)); 00555 00556 Data_Get_Struct(obj, void, pctx1); 00557 Data_Get_Struct(copy, void, pctx2); 00558 memcpy(pctx2, pctx1, algo->ctx_size); 00559 00560 return copy; 00561 } 00562 00563 /* :nodoc: */ 00564 static VALUE 00565 rb_digest_base_reset(VALUE self) 00566 { 00567 rb_digest_metadata_t *algo; 00568 void *pctx; 00569 00570 algo = get_digest_base_metadata(rb_obj_class(self)); 00571 00572 Data_Get_Struct(self, void, pctx); 00573 00574 algo->init_func(pctx); 00575 00576 return self; 00577 } 00578 00579 /* :nodoc: */ 00580 static VALUE 00581 rb_digest_base_update(VALUE self, VALUE str) 00582 { 00583 rb_digest_metadata_t *algo; 00584 void *pctx; 00585 00586 algo = get_digest_base_metadata(rb_obj_class(self)); 00587 00588 Data_Get_Struct(self, void, pctx); 00589 00590 StringValue(str); 00591 algo->update_func(pctx, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)); 00592 00593 return self; 00594 } 00595 00596 /* :nodoc: */ 00597 static VALUE 00598 rb_digest_base_finish(VALUE self) 00599 { 00600 rb_digest_metadata_t *algo; 00601 void *pctx; 00602 VALUE str; 00603 00604 algo = get_digest_base_metadata(rb_obj_class(self)); 00605 00606 Data_Get_Struct(self, void, pctx); 00607 00608 str = rb_str_new(0, algo->digest_len); 00609 algo->finish_func(pctx, (unsigned char *)RSTRING_PTR(str)); 00610 00611 /* avoid potential coredump caused by use of a finished context */ 00612 algo->init_func(pctx); 00613 00614 return str; 00615 } 00616 00617 /* :nodoc: */ 00618 static VALUE 00619 rb_digest_base_digest_length(VALUE self) 00620 { 00621 rb_digest_metadata_t *algo; 00622 00623 algo = get_digest_base_metadata(rb_obj_class(self)); 00624 00625 return INT2NUM(algo->digest_len); 00626 } 00627 00628 /* :nodoc: */ 00629 static VALUE 00630 rb_digest_base_block_length(VALUE self) 00631 { 00632 rb_digest_metadata_t *algo; 00633 00634 algo = get_digest_base_metadata(rb_obj_class(self)); 00635 00636 return INT2NUM(algo->block_len); 00637 } 00638 00639 void 00640 Init_digest(void) 00641 { 00642 id_reset = rb_intern("reset"); 00643 id_update = rb_intern("update"); 00644 id_finish = rb_intern("finish"); 00645 id_digest = rb_intern("digest"); 00646 id_hexdigest = rb_intern("hexdigest"); 00647 id_digest_length = rb_intern("digest_length"); 00648 00649 /* 00650 * module Digest 00651 */ 00652 rb_mDigest = rb_define_module("Digest"); 00653 00654 /* module functions */ 00655 rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1); 00656 00657 /* 00658 * module Digest::Instance 00659 */ 00660 rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance"); 00661 00662 /* instance methods that should be overridden */ 00663 rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1); 00664 rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1); 00665 rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0); 00666 rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0); 00667 rb_define_method(rb_mDigest_Instance, "digest_length", rb_digest_instance_digest_length, 0); 00668 rb_define_method(rb_mDigest_Instance, "block_length", rb_digest_instance_block_length, 0); 00669 00670 /* instance methods that may be overridden */ 00671 rb_define_method(rb_mDigest_Instance, "==", rb_digest_instance_equal, 1); 00672 rb_define_method(rb_mDigest_Instance, "inspect", rb_digest_instance_inspect, 0); 00673 00674 /* instance methods that need not usually be overridden */ 00675 rb_define_method(rb_mDigest_Instance, "new", rb_digest_instance_new, 0); 00676 rb_define_method(rb_mDigest_Instance, "digest", rb_digest_instance_digest, -1); 00677 rb_define_method(rb_mDigest_Instance, "digest!", rb_digest_instance_digest_bang, 0); 00678 rb_define_method(rb_mDigest_Instance, "hexdigest", rb_digest_instance_hexdigest, -1); 00679 rb_define_method(rb_mDigest_Instance, "hexdigest!", rb_digest_instance_hexdigest_bang, 0); 00680 rb_define_method(rb_mDigest_Instance, "to_s", rb_digest_instance_to_s, 0); 00681 rb_define_method(rb_mDigest_Instance, "length", rb_digest_instance_length, 0); 00682 rb_define_method(rb_mDigest_Instance, "size", rb_digest_instance_length, 0); 00683 00684 /* 00685 * class Digest::Class 00686 */ 00687 rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject); 00688 rb_define_method(rb_cDigest_Class, "initialize", rb_digest_class_init, 0); 00689 rb_include_module(rb_cDigest_Class, rb_mDigest_Instance); 00690 00691 /* class methods */ 00692 rb_define_singleton_method(rb_cDigest_Class, "digest", rb_digest_class_s_digest, -1); 00693 rb_define_singleton_method(rb_cDigest_Class, "hexdigest", rb_digest_class_s_hexdigest, -1); 00694 00695 id_metadata = rb_intern("metadata"); 00696 00697 /* class Digest::Base < Digest::Class */ 00698 rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class); 00699 00700 rb_define_alloc_func(rb_cDigest_Base, rb_digest_base_alloc); 00701 00702 rb_define_method(rb_cDigest_Base, "initialize_copy", rb_digest_base_copy, 1); 00703 rb_define_method(rb_cDigest_Base, "reset", rb_digest_base_reset, 0); 00704 rb_define_method(rb_cDigest_Base, "update", rb_digest_base_update, 1); 00705 rb_define_method(rb_cDigest_Base, "<<", rb_digest_base_update, 1); 00706 rb_define_private_method(rb_cDigest_Base, "finish", rb_digest_base_finish, 0); 00707 rb_define_method(rb_cDigest_Base, "digest_length", rb_digest_base_digest_length, 0); 00708 rb_define_method(rb_cDigest_Base, "block_length", rb_digest_base_block_length, 0); 00709 } 00710
1.7.6.1