ext/digest/digest.c


DEFINITIONS

This source file includes following functions.
  1. get_digest_base_metadata
  2. rb_digest_base_alloc
  3. rb_digest_base_s_digest
  4. rb_digest_base_s_hexdigest
  5. rb_digest_base_become
  6. rb_digest_base_update
  7. rb_digest_base_init
  8. rb_digest_base_digest
  9. rb_digest_base_hexdigest
  10. rb_digest_base_equal
  11. Init_digest


   1  /************************************************
   2  
   3    digest.c -
   4  
   5    $Author: matz $
   6    created at: Fri May 25 08:57:27 JST 2001
   7  
   8    Copyright (C) 1995-2001 Yukihiro Matsumoto
   9    Copyright (C) 2001 Akinori MUSHA
  10  
  11    $RoughId: digest.c,v 1.16 2001/07/13 15:38:27 knu Exp $
  12    $Id: digest.c,v 1.7 2002/09/05 02:11:41 matz Exp $
  13  
  14  ************************************************/
  15  
  16  /*
  17   * This module provides an interface to the following hash algorithms:
  18   *
  19   *   - the MD5 Message-Digest Algorithm by the RSA Data Security,
  20   *     Inc., described in RFC 1321
  21   *
  22   *   - the SHA-1 Secure Hash Algorithm by NIST (the US' National
  23   *     Institute of Standards and Technology), described in FIPS PUB
  24   *     180-1.
  25   *
  26   *   - the SHA-256/384/512 Secure Hash Algorithm by NIST (the US'
  27   *     National Institute of Standards and Technology), described in
  28   *     FIPS PUB 180-2.
  29   *
  30   *   - the RIPEMD-160 cryptographic hash function, designed by Hans
  31   *     Dobbertin, Antoon Bosselaers, and Bart Preneel.
  32   */
  33  
  34  #include "digest.h"
  35  
  36  static VALUE mDigest, cDigest_Base;
  37  static ID id_metadata;
  38  
  39  /*
  40   * Digest::Base
  41   */
  42  
  43  static algo_t *
  44  get_digest_base_metadata(klass)
  45      VALUE klass;
  46  {
  47      VALUE obj;
  48      algo_t *algo;
  49  
  50      if (rb_cvar_defined(klass, id_metadata) == Qfalse) {
  51          rb_notimplement();
  52      }
  53  
  54      obj = rb_cvar_get(klass, id_metadata);
  55  
  56      Data_Get_Struct(obj, algo_t, algo);
  57  
  58      return algo;
  59  }
  60          
  61  static VALUE
  62  rb_digest_base_alloc(klass)
  63      VALUE klass;
  64  {
  65      algo_t *algo;
  66      VALUE obj;
  67      void *pctx;
  68  
  69      if (klass == cDigest_Base) {
  70          rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
  71      }
  72  
  73      algo = get_digest_base_metadata(klass);
  74  
  75      pctx = xmalloc(algo->ctx_size);
  76      algo->init_func(pctx);
  77  
  78      obj = Data_Wrap_Struct(klass, 0, free, pctx);
  79  
  80      return obj;
  81  }
  82  
  83  static VALUE
  84  rb_digest_base_s_digest(klass, str)
  85      VALUE klass;
  86      VALUE str;
  87  {
  88      algo_t *algo;
  89      void *pctx;
  90      size_t len;
  91      unsigned char *digest;
  92      VALUE obj = rb_digest_base_alloc(klass);
  93  
  94      algo = get_digest_base_metadata(klass);
  95      Data_Get_Struct(obj, void, pctx);
  96  
  97      StringValue(str);
  98      algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
  99  
 100      len = algo->digest_len;
 101  
 102      digest = xmalloc(len);
 103      algo->final_func(digest, pctx);
 104  
 105      obj = rb_str_new(digest, len);
 106  
 107      free(digest);
 108      free(pctx);
 109  
 110      return obj;
 111  }
 112  
 113  static VALUE
 114  rb_digest_base_s_hexdigest(klass, str)
 115      VALUE klass;
 116      VALUE str;
 117  {
 118      algo_t *algo;
 119      void *pctx;
 120      size_t len;
 121      unsigned char *hexdigest;
 122      VALUE obj = rb_digest_base_alloc(klass);
 123  
 124      StringValue(str);
 125      algo = get_digest_base_metadata(klass);
 126  
 127      pctx = xmalloc(algo->ctx_size);
 128      algo->init_func(pctx);
 129      algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
 130  
 131      len = algo->digest_len * 2;
 132  
 133      hexdigest = xmalloc(len + 1); /* +1 is for '\0' */
 134      algo->end_func(pctx, hexdigest);
 135  
 136      obj = rb_str_new(hexdigest, len);
 137  
 138      free(hexdigest);
 139      free(pctx);
 140  
 141      return obj;
 142  }
 143  
 144  static VALUE
 145  rb_digest_base_become(copy, obj)
 146      VALUE copy, obj;
 147  {
 148      algo_t *algo;
 149      void *pctx1, *pctx2;
 150  
 151      if (copy == obj) return copy;
 152      rb_check_frozen(copy);
 153      algo = get_digest_base_metadata(CLASS_OF(copy));
 154      if (algo != get_digest_base_metadata(CLASS_OF(obj))) {
 155          rb_raise(rb_eTypeError, "wrong argument class");
 156      }
 157      Data_Get_Struct(obj, void, pctx1);
 158      Data_Get_Struct(copy, void, pctx2);
 159      memcpy(pctx2, pctx1, algo->ctx_size);
 160  
 161      return copy;
 162  }
 163  
 164  static VALUE
 165  rb_digest_base_update(self, str)
 166      VALUE self, str;
 167  {
 168      algo_t *algo;
 169      void *pctx;
 170  
 171      StringValue(str);
 172      algo = get_digest_base_metadata(CLASS_OF(self));
 173      Data_Get_Struct(self, void, pctx);
 174  
 175      algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
 176  
 177      return self;
 178  }
 179  
 180  static VALUE
 181  rb_digest_base_init(argc, argv, self)
 182      int argc;
 183      VALUE* argv;
 184      VALUE self;
 185  {
 186      VALUE arg;
 187  
 188      rb_scan_args(argc, argv, "01", &arg);
 189  
 190      if (!NIL_P(arg)) rb_digest_base_update(self, arg);
 191  
 192      return self;
 193  }
 194  
 195  static VALUE
 196  rb_digest_base_digest(self)
 197      VALUE self;
 198  {
 199      algo_t *algo;
 200      void *pctx1, *pctx2;
 201      unsigned char *digest;
 202      size_t len;
 203      VALUE str;
 204  
 205      algo = get_digest_base_metadata(CLASS_OF(self));
 206      Data_Get_Struct(self, void, pctx1);
 207  
 208      len = algo->ctx_size;
 209  
 210      pctx2 = xmalloc(len);
 211      memcpy(pctx2, pctx1, len);
 212  
 213      len = algo->digest_len;
 214  
 215      digest = xmalloc(len);
 216      algo->final_func(digest, pctx2);
 217  
 218      str = rb_str_new(digest, len);
 219  
 220      free(digest);
 221      free(pctx2);
 222  
 223      return str;
 224  }
 225  
 226  static VALUE
 227  rb_digest_base_hexdigest(self)
 228      VALUE self;
 229  {
 230      algo_t *algo;
 231      void *pctx1, *pctx2;
 232      unsigned char *hexdigest;
 233      size_t len;
 234      VALUE str;
 235  
 236      algo = get_digest_base_metadata(CLASS_OF(self));
 237      Data_Get_Struct(self, void, pctx1);
 238  
 239      len = algo->ctx_size;
 240  
 241      pctx2 = xmalloc(len);
 242      memcpy(pctx2, pctx1, len);
 243  
 244      len = algo->digest_len * 2;
 245  
 246      hexdigest = xmalloc(len + 1); /* +1 is for '\0' */
 247      algo->end_func(pctx2, hexdigest);
 248  
 249      str = rb_str_new(hexdigest, len);
 250  
 251      free(hexdigest);
 252      free(pctx2);
 253  
 254      return str;
 255  }
 256  
 257  static VALUE
 258  rb_digest_base_equal(self, other)
 259      VALUE self, other;
 260  {
 261      algo_t *algo;
 262      VALUE klass;
 263      VALUE str1, str2;
 264  
 265      klass = CLASS_OF(self);
 266      algo = get_digest_base_metadata(klass);
 267  
 268      if (CLASS_OF(other) == klass) {
 269          void *pctx1, *pctx2;
 270  
 271          Data_Get_Struct(self, void, pctx1);
 272          Data_Get_Struct(other, void, pctx2);
 273  
 274          return algo->equal_func(pctx1, pctx2) ? Qtrue : Qfalse;
 275      }
 276  
 277      StringValue(other);
 278      str2 = other;
 279  
 280      if (RSTRING(str2)->len == algo->digest_len)
 281          str1 = rb_digest_base_digest(self);
 282      else
 283          str1 = rb_digest_base_hexdigest(self);
 284  
 285      if (RSTRING(str1)->len == RSTRING(str2)->len
 286        && rb_str_cmp(str1, str2) == 0)
 287          return Qtrue;
 288  
 289      return Qfalse;
 290  }
 291  
 292  /*
 293   * Init
 294   */
 295  
 296  void
 297  Init_digest()
 298  {
 299      mDigest = rb_define_module("Digest");
 300  
 301      cDigest_Base = rb_define_class_under(mDigest, "Base", rb_cObject);
 302  
 303      rb_define_singleton_method(cDigest_Base, "allocate", rb_digest_base_alloc, 0);
 304      rb_define_singleton_method(cDigest_Base, "digest", rb_digest_base_s_digest, 1);
 305      rb_define_singleton_method(cDigest_Base, "hexdigest", rb_digest_base_s_hexdigest, 1);
 306  
 307      rb_define_method(cDigest_Base, "initialize", rb_digest_base_init, -1);
 308      rb_define_method(cDigest_Base, "become",  rb_digest_base_become, 1);
 309      rb_define_method(cDigest_Base, "update", rb_digest_base_update, 1);
 310      rb_define_method(cDigest_Base, "<<", rb_digest_base_update, 1);
 311      rb_define_method(cDigest_Base, "digest", rb_digest_base_digest, 0);
 312      rb_define_method(cDigest_Base, "hexdigest", rb_digest_base_hexdigest, 0);
 313      rb_define_method(cDigest_Base, "to_s", rb_digest_base_hexdigest, 0);
 314      rb_define_method(cDigest_Base, "==", rb_digest_base_equal, 1);
 315  
 316      id_metadata = rb_intern("metadata");
 317  }