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 */ 27VALUE cDigest; 28VALUE eDigestError; 29 30static VALUE ossl_digest_alloc(VALUE klass); 31 32/* 33 * Public 34 */ 35const EVP_MD * 36GetDigestPtr(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 63VALUE 64ossl_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 */ 81static VALUE 82ossl_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 95VALUE 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 */ 115static VALUE 116ossl_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 135static VALUE 136ossl_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 */ 160static VALUE 161ossl_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 */ 188VALUE 189ossl_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 */ 205static VALUE 206ossl_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 */ 238static VALUE 239ossl_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 */ 260static VALUE 261ossl_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 */ 283static VALUE 284ossl_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 */ 296void 297Init_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