Ruby  2.4.2p198(2017-09-14revision59899)
ossl_digest.c
Go to the documentation of this file.
1 /*
2  * 'OpenSSL for Ruby' project
3  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4  * All rights reserved.
5  */
6 /*
7  * This program is licensed under the same licence as Ruby.
8  * (See the file 'LICENCE'.)
9  */
10 #include "ossl.h"
11 
12 #define GetDigest(obj, ctx) do { \
13  TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_digest_type, (ctx)); \
14  if (!(ctx)) { \
15  ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
16  } \
17 } while (0)
18 #define SafeGetDigest(obj, ctx) do { \
19  OSSL_Check_Kind((obj), cDigest); \
20  GetDigest((obj), (ctx)); \
21 } while (0)
22 
23 /*
24  * Classes
25  */
28 
29 static VALUE ossl_digest_alloc(VALUE klass);
30 
31 static void
32 ossl_digest_free(void *ctx)
33 {
34  EVP_MD_CTX_destroy(ctx);
35 }
36 
38  "OpenSSL/Digest",
39  {
41  },
43 };
44 
45 /*
46  * Public
47  */
48 const EVP_MD *
50 {
51  const EVP_MD *md;
52  ASN1_OBJECT *oid = NULL;
53 
54  if (RB_TYPE_P(obj, T_STRING)) {
55  const char *name = StringValueCStr(obj);
56 
57  md = EVP_get_digestbyname(name);
58  if (!md) {
59  oid = OBJ_txt2obj(name, 0);
60  md = EVP_get_digestbyobj(oid);
61  ASN1_OBJECT_free(oid);
62  }
63  if(!md)
64  ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%"PRIsVALUE").", obj);
65  } else {
66  EVP_MD_CTX *ctx;
67 
68  SafeGetDigest(obj, ctx);
69 
70  md = EVP_MD_CTX_md(ctx);
71  }
72 
73  return md;
74 }
75 
76 VALUE
77 ossl_digest_new(const EVP_MD *md)
78 {
79  VALUE ret;
80  EVP_MD_CTX *ctx;
81 
83  ctx = EVP_MD_CTX_new();
84  if (!ctx)
85  ossl_raise(eDigestError, "EVP_MD_CTX_new");
86  RTYPEDDATA_DATA(ret) = ctx;
87 
88  if (!EVP_DigestInit_ex(ctx, md, NULL))
89  ossl_raise(eDigestError, "Digest initialization failed");
90 
91  return ret;
92 }
93 
94 /*
95  * Private
96  */
97 static VALUE
99 {
100  return TypedData_Wrap_Struct(klass, &ossl_digest_type, 0);
101 }
102 
104 
105 /*
106  * call-seq:
107  * Digest.new(string [, data]) -> Digest
108  *
109  * Creates a Digest instance based on +string+, which is either the ln
110  * (long name) or sn (short name) of a supported digest algorithm.
111  *
112  * If +data+ (a +String+) is given, it is used as the initial input to the
113  * Digest instance, i.e.
114  *
115  * digest = OpenSSL::Digest.new('sha256', 'digestdata')
116  *
117  * is equal to
118  *
119  * digest = OpenSSL::Digest.new('sha256')
120  * digest.update('digestdata')
121  */
122 static VALUE
124 {
125  EVP_MD_CTX *ctx;
126  const EVP_MD *md;
127  VALUE type, data;
128 
129  rb_scan_args(argc, argv, "11", &type, &data);
130  md = GetDigestPtr(type);
131  if (!NIL_P(data)) StringValue(data);
132 
133  TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx);
134  if (!ctx) {
135  RTYPEDDATA_DATA(self) = ctx = EVP_MD_CTX_new();
136  if (!ctx)
137  ossl_raise(eDigestError, "EVP_MD_CTX_new");
138  }
139 
140  if (!EVP_DigestInit_ex(ctx, md, NULL))
141  ossl_raise(eDigestError, "Digest initialization failed");
142 
143  if (!NIL_P(data)) return ossl_digest_update(self, data);
144  return self;
145 }
146 
147 static VALUE
149 {
150  EVP_MD_CTX *ctx1, *ctx2;
151 
152  rb_check_frozen(self);
153  if (self == other) return self;
154 
155  TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx1);
156  if (!ctx1) {
157  RTYPEDDATA_DATA(self) = ctx1 = EVP_MD_CTX_new();
158  if (!ctx1)
159  ossl_raise(eDigestError, "EVP_MD_CTX_new");
160  }
161  SafeGetDigest(other, ctx2);
162 
163  if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
165  }
166  return self;
167 }
168 
169 /*
170  * call-seq:
171  * digest.reset -> self
172  *
173  * Resets the Digest in the sense that any Digest#update that has been
174  * performed is abandoned and the Digest is set to its initial state again.
175  *
176  */
177 static VALUE
179 {
180  EVP_MD_CTX *ctx;
181 
182  GetDigest(self, ctx);
183  if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL) != 1) {
184  ossl_raise(eDigestError, "Digest initialization failed.");
185  }
186 
187  return self;
188 }
189 
190 /*
191  * call-seq:
192  * digest.update(string) -> aString
193  *
194  * Not every message digest can be computed in one single pass. If a message
195  * digest is to be computed from several subsequent sources, then each may
196  * be passed individually to the Digest instance.
197  *
198  * === Example
199  * digest = OpenSSL::Digest::SHA256.new
200  * digest.update('First input')
201  * digest << 'Second input' # equivalent to digest.update('Second input')
202  * result = digest.digest
203  *
204  */
205 VALUE
207 {
208  EVP_MD_CTX *ctx;
209 
210  StringValue(data);
211  GetDigest(self, ctx);
212 
213  if (!EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)))
214  ossl_raise(eDigestError, "EVP_DigestUpdate");
215 
216  return self;
217 }
218 
219 /*
220  * call-seq:
221  * digest.finish -> aString
222  *
223  */
224 static VALUE
226 {
227  EVP_MD_CTX *ctx;
228  VALUE str;
229  int out_len;
230 
231  GetDigest(self, ctx);
232  rb_scan_args(argc, argv, "01", &str);
233  out_len = EVP_MD_CTX_size(ctx);
234 
235  if (NIL_P(str)) {
236  str = rb_str_new(NULL, out_len);
237  } else {
238  StringValue(str);
239  rb_str_resize(str, out_len);
240  }
241 
242  if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL))
243  ossl_raise(eDigestError, "EVP_DigestFinal_ex");
244 
245  return str;
246 }
247 
248 /*
249  * call-seq:
250  * digest.name -> string
251  *
252  * Returns the sn of this Digest algorithm.
253  *
254  * === Example
255  * digest = OpenSSL::Digest::SHA512.new
256  * puts digest.name # => SHA512
257  *
258  */
259 static VALUE
261 {
262  EVP_MD_CTX *ctx;
263 
264  GetDigest(self, ctx);
265 
266  return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
267 }
268 
269 /*
270  * call-seq:
271  * digest.digest_length -> integer
272  *
273  * Returns the output size of the digest, i.e. the length in bytes of the
274  * final message digest result.
275  *
276  * === Example
277  * digest = OpenSSL::Digest::SHA1.new
278  * puts digest.digest_length # => 20
279  *
280  */
281 static VALUE
283 {
284  EVP_MD_CTX *ctx;
285 
286  GetDigest(self, ctx);
287 
288  return INT2NUM(EVP_MD_CTX_size(ctx));
289 }
290 
291 /*
292  * call-seq:
293  * digest.block_length -> integer
294  *
295  * Returns the block length of the digest algorithm, i.e. the length in bytes
296  * of an individual block. Most modern algorithms partition a message to be
297  * digested into a sequence of fix-sized blocks that are processed
298  * consecutively.
299  *
300  * === Example
301  * digest = OpenSSL::Digest::SHA1.new
302  * puts digest.block_length # => 64
303  */
304 static VALUE
306 {
307  EVP_MD_CTX *ctx;
308 
309  GetDigest(self, ctx);
310 
311  return INT2NUM(EVP_MD_CTX_block_size(ctx));
312 }
313 
314 /*
315  * INIT
316  */
317 void
319 {
320  rb_require("digest");
321 
322 #if 0
323  mOSSL = rb_define_module("OpenSSL");
325 #endif
326 
327  /* Document-class: OpenSSL::Digest
328  *
329  * OpenSSL::Digest allows you to compute message digests (sometimes
330  * interchangeably called "hashes") of arbitrary data that are
331  * cryptographically secure, i.e. a Digest implements a secure one-way
332  * function.
333  *
334  * One-way functions offer some useful properties. E.g. given two
335  * distinct inputs the probability that both yield the same output
336  * is highly unlikely. Combined with the fact that every message digest
337  * algorithm has a fixed-length output of just a few bytes, digests are
338  * often used to create unique identifiers for arbitrary data. A common
339  * example is the creation of a unique id for binary documents that are
340  * stored in a database.
341  *
342  * Another useful characteristic of one-way functions (and thus the name)
343  * is that given a digest there is no indication about the original
344  * data that produced it, i.e. the only way to identify the original input
345  * is to "brute-force" through every possible combination of inputs.
346  *
347  * These characteristics make one-way functions also ideal companions
348  * for public key signature algorithms: instead of signing an entire
349  * document, first a hash of the document is produced with a considerably
350  * faster message digest algorithm and only the few bytes of its output
351  * need to be signed using the slower public key algorithm. To validate
352  * the integrity of a signed document, it suffices to re-compute the hash
353  * and verify that it is equal to that in the signature.
354  *
355  * Among the supported message digest algorithms are:
356  * * SHA, SHA1, SHA224, SHA256, SHA384 and SHA512
357  * * MD2, MD4, MDC2 and MD5
358  * * RIPEMD160
359  * * DSS, DSS1 (Pseudo algorithms to be used for DSA signatures. DSS is
360  * equal to SHA and DSS1 is equal to SHA1)
361  *
362  * For each of these algorithms, there is a sub-class of Digest that
363  * can be instantiated as simply as e.g.
364  *
365  * digest = OpenSSL::Digest::SHA1.new
366  *
367  * === Mapping between Digest class and sn/ln
368  *
369  * The sn (short names) and ln (long names) are defined in
370  * <openssl/object.h> and <openssl/obj_mac.h>. They are textual
371  * representations of ASN.1 OBJECT IDENTIFIERs. Each supported digest
372  * algorithm has an OBJECT IDENTIFIER associated to it and those again
373  * have short/long names assigned to them.
374  * E.g. the OBJECT IDENTIFIER for SHA-1 is 1.3.14.3.2.26 and its
375  * sn is "SHA1" and its ln is "sha1".
376  * ==== MD2
377  * * sn: MD2
378  * * ln: md2
379  * ==== MD4
380  * * sn: MD4
381  * * ln: md4
382  * ==== MD5
383  * * sn: MD5
384  * * ln: md5
385  * ==== SHA
386  * * sn: SHA
387  * * ln: SHA
388  * ==== SHA-1
389  * * sn: SHA1
390  * * ln: sha1
391  * ==== SHA-224
392  * * sn: SHA224
393  * * ln: sha224
394  * ==== SHA-256
395  * * sn: SHA256
396  * * ln: sha256
397  * ==== SHA-384
398  * * sn: SHA384
399  * * ln: sha384
400  * ==== SHA-512
401  * * sn: SHA512
402  * * ln: sha512
403  *
404  * "Breaking" a message digest algorithm means defying its one-way
405  * function characteristics, i.e. producing a collision or finding a way
406  * to get to the original data by means that are more efficient than
407  * brute-forcing etc. Most of the supported digest algorithms can be
408  * considered broken in this sense, even the very popular MD5 and SHA1
409  * algorithms. Should security be your highest concern, then you should
410  * probably rely on SHA224, SHA256, SHA384 or SHA512.
411  *
412  * === Hashing a file
413  *
414  * data = File.read('document')
415  * sha256 = OpenSSL::Digest::SHA256.new
416  * digest = sha256.digest(data)
417  *
418  * === Hashing several pieces of data at once
419  *
420  * data1 = File.read('file1')
421  * data2 = File.read('file2')
422  * data3 = File.read('file3')
423  * sha256 = OpenSSL::Digest::SHA256.new
424  * sha256 << data1
425  * sha256 << data2
426  * sha256 << data3
427  * digest = sha256.digest
428  *
429  * === Reuse a Digest instance
430  *
431  * data1 = File.read('file1')
432  * sha256 = OpenSSL::Digest::SHA256.new
433  * digest1 = sha256.digest(data1)
434  *
435  * data2 = File.read('file2')
436  * sha256.reset
437  * digest2 = sha256.digest(data2)
438  *
439  */
440  cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
441  /* Document-class: OpenSSL::Digest::DigestError
442  *
443  * Generic Exception class that is raised if an error occurs during a
444  * Digest operation.
445  */
447 
449 
450  rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
454  rb_define_alias(cDigest, "<<", "update");
456  rb_define_method(cDigest, "digest_length", ossl_digest_size, 0);
458 
460 }
VALUE rb_eStandardError
Definition: error.c:760
#define EVP_MD_CTX_new
VALUE mOSSL
Definition: ossl.c:213
VALUE cDigest
Definition: ossl_digest.c:26
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1145
#define INT2NUM(x)
Definition: ruby.h:1538
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1169
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1190
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1527
static VALUE ossl_digest_block_length(VALUE self)
Definition: ossl_digest.c:305
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
VALUE eDigestError
Definition: ossl_digest.c:27
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_path2class(const char *)
Definition: variable.c:431
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
#define rb_define_copy_func(klass, func)
Definition: ruby_missing.h:13
VALUE rb_require(const char *)
Definition: load.c:1056
static VALUE ossl_digest_name(VALUE self)
Definition: ossl_digest.c:260
VALUE rb_eRuntimeError
Definition: error.c:761
VALUE ossl_digest_new(const EVP_MD *md)
Definition: ossl_digest.c:77
#define NIL_P(v)
Definition: ruby.h:451
const EVP_MD * GetDigestPtr(VALUE obj)
Definition: ossl_digest.c:49
VALUE eOSSLError
Definition: ossl.c:218
int argc
Definition: ruby.c:183
#define rb_str_new2
Definition: intern.h:857
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2562
void Init_ossl_digest(void)
Definition: ossl_digest.c:318
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1758
#define RSTRING_LEN(str)
Definition: ruby.h:978
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1919
#define PRIsVALUE
Definition: ruby.h:135
unsigned long VALUE
Definition: ruby.h:85
#define StringValueCStr(v)
Definition: ruby.h:571
#define RSTRING_PTR(str)
Definition: ruby.h:982
static VALUE ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
Definition: ossl_digest.c:123
static VALUE ossl_digest_copy(VALUE self, VALUE other)
Definition: ossl_digest.c:148
static VALUE ossl_digest_alloc(VALUE klass)
Definition: ossl_digest.c:98
static void ossl_digest_free(void *ctx)
Definition: ossl_digest.c:32
#define SafeGetDigest(obj, ctx)
Definition: ossl_digest.c:18
#define T_STRING
Definition: ruby.h:496
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:278
const char * name
Definition: nkf.c:208
static VALUE ossl_digest_finish(int argc, VALUE *argv, VALUE self)
Definition: ossl_digest.c:225
#define RTYPEDDATA_DATA(v)
Definition: ruby.h:1117
static VALUE ossl_digest_size(VALUE self)
Definition: ossl_digest.c:282
#define rb_check_frozen(obj)
Definition: intern.h:276
#define GetDigest(obj, ctx)
Definition: ossl_digest.c:12
VALUE rb_define_module(const char *name)
Definition: class.c:768
VALUE ossl_digest_update(VALUE, VALUE)
Definition: ossl_digest.c:206
#define NULL
Definition: _sdbm.c:102
static const rb_data_type_t ossl_digest_type
Definition: ossl_digest.c:37
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
static VALUE ossl_digest_reset(VALUE self)
Definition: ossl_digest.c:178
char ** argv
Definition: ruby.c:184
#define StringValue(v)
Definition: ruby.h:569
VALUE rb_str_new(const char *, long)
Definition: string.c:736