Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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