3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
13 #define GetDigest(obj, ctx) do { \
14 Data_Get_Struct(obj, EVP_MD_CTX, ctx); \
16 ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
19 #define SafeGetDigest(obj, ctx) do { \
20 OSSL_Check_Kind(obj, cDigest); \
21 GetDigest(obj, ctx); \
30 static VALUE
ossl_digest_alloc(VALUE klass
);
36 GetDigestPtr(VALUE obj
)
40 if (TYPE(obj
) == T_STRING
) {
41 const char *name
= STR2CSTR(obj
);
43 md
= EVP_get_digestbyname(name
);
45 ossl_raise(rb_eRuntimeError
, "Unsupported digest algorithm (%s).", name
);
49 SafeGetDigest(obj
, ctx
);
51 md
= EVP_MD_CTX_md(ctx
);
58 ossl_digest_new(const EVP_MD
*md
)
63 ret
= ossl_digest_alloc(cDigest
);
65 EVP_DigestInit_ex(ctx
, md
, NULL
);
74 ossl_digest_alloc(VALUE klass
)
79 ctx
= EVP_MD_CTX_create();
81 ossl_raise(rb_eRuntimeError
, "EVP_MD_CTX_create() failed");
82 obj
= Data_Wrap_Struct(klass
, 0, EVP_MD_CTX_destroy
, ctx
);
87 VALUE
ossl_digest_update(VALUE
, VALUE
);
91 * Digest.new(string) -> digest
95 ossl_digest_initialize(int argc
, VALUE
*argv
, VALUE self
)
101 rb_scan_args(argc
, argv
, "11", &type
, &data
);
102 md
= GetDigestPtr(type
);
103 if (!NIL_P(data
)) StringValue(data
);
105 GetDigest(self
, ctx
);
106 EVP_DigestInit_ex(ctx
, md
, NULL
);
108 if (!NIL_P(data
)) return ossl_digest_update(self
, data
);
113 ossl_digest_copy(VALUE self
, VALUE other
)
115 EVP_MD_CTX
*ctx1
, *ctx2
;
117 rb_check_frozen(self
);
118 if (self
== other
) return self
;
120 GetDigest(self
, ctx1
);
121 SafeGetDigest(other
, ctx2
);
123 if (!EVP_MD_CTX_copy(ctx1
, ctx2
)) {
124 ossl_raise(eDigestError
, NULL
);
131 * digest.reset -> self
135 ossl_digest_reset(VALUE self
)
139 GetDigest(self
, ctx
);
140 EVP_DigestInit_ex(ctx
, EVP_MD_CTX_md(ctx
), NULL
);
147 * digest.update(string) -> aString
151 ossl_digest_update(VALUE self
, VALUE data
)
156 GetDigest(self
, ctx
);
157 EVP_DigestUpdate(ctx
, RSTRING_PTR(data
), RSTRING_LEN(data
));
164 * digest.finish -> aString
168 ossl_digest_finish(int argc
, VALUE
*argv
, VALUE self
)
173 rb_scan_args(argc
, argv
, "01", &str
);
175 GetDigest(self
, ctx
);
178 str
= rb_str_new(NULL
, EVP_MD_CTX_size(ctx
));
181 rb_str_resize(str
, EVP_MD_CTX_size(ctx
));
184 EVP_DigestFinal_ex(ctx
, (unsigned char *)RSTRING_PTR(str
), NULL
);
191 * digest.name -> string
195 ossl_digest_name(VALUE self
)
199 GetDigest(self
, ctx
);
201 return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx
)));
206 * digest.digest_size -> integer
208 * Returns the output size of the digest.
211 ossl_digest_size(VALUE self
)
215 GetDigest(self
, ctx
);
217 return INT2NUM(EVP_MD_CTX_size(ctx
));
221 ossl_digest_block_length(VALUE self
)
225 GetDigest(self
, ctx
);
227 return INT2NUM(EVP_MD_CTX_block_size(ctx
));
236 rb_require("openssl");
237 rb_require("digest");
239 #if 0 /* let rdoc know about mOSSL */
240 mOSSL
= rb_define_module("OpenSSL");
243 cDigest
= rb_define_class_under(mOSSL
, "Digest", rb_path2class("Digest::Class"));
244 eDigestError
= rb_define_class_under(cDigest
, "DigestError", eOSSLError
);
246 rb_define_alloc_func(cDigest
, ossl_digest_alloc
);
248 rb_define_method(cDigest
, "initialize", ossl_digest_initialize
, -1);
249 rb_define_copy_func(cDigest
, ossl_digest_copy
);
250 rb_define_method(cDigest
, "reset", ossl_digest_reset
, 0);
251 rb_define_method(cDigest
, "update", ossl_digest_update
, 1);
252 rb_define_alias(cDigest
, "<<", "update");
253 rb_define_private_method(cDigest
, "finish", ossl_digest_finish
, -1);
254 rb_define_method(cDigest
, "digest_length", ossl_digest_size
, 0);
255 rb_define_method(cDigest
, "block_length", ossl_digest_block_length
, 0);
257 rb_define_method(cDigest
, "name", ossl_digest_name
, 0);