2
* Ruby Bindings for Librhash
3
* Copyright (c) 2011-2012, Sergey Basalaev <sbasalaev@gmail.com>
4
* Librhash is (c) 2011-2012, Aleksey Kravchenko <rhash.admin@gmail.com>
6
* Permission is hereby granted, free of charge, to any person obtaining a copy
7
* of this software and associated documentation files (the "Software"), to deal
8
* in the Software without restriction, including without limitation the rights
9
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
* copies of the Software, and to permit persons to whom the Software is
13
* This library is distributed in the hope that it will be useful, but WITHOUT
14
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
* FOR A PARTICULAR PURPOSE. Use it at your own risk!
19
#include <rhash/rhash.h>
24
static void rh_free(rhash ctx) {
30
* rhash.update(data) -> RHash
31
* rhash << data -> RHash
33
* Updates this <code>RHash</code> with new data chunk.
35
static VALUE rh_update(VALUE self, VALUE msg) {
37
Data_Get_Struct(self, struct rhash_context, ctx);
39
if (TYPE(msg) != T_STRING) {
40
msg = rb_obj_as_string(msg); // convert to string
43
rhash_update(ctx, RSTRING_PTR(msg), RSTRING_LEN(msg));
49
* rhash.update_file(filename) -> RHash
51
* Updates this <code>RHash</code> with data from given file.
53
static VALUE rh_update_file(VALUE self, VALUE file) {
54
// this function is actually implemented in pure Ruby below
55
// this allows us to handle files in platform-independent way
63
* Finishes calculation for all data buffered by
64
* <code>update</code> and stops calculation of hashes.
66
static VALUE rh_finish(VALUE self) {
68
Data_Get_Struct(self, struct rhash_context, ctx);
69
rhash_final(ctx, NULL);
77
* Resets this RHash to initial state.
78
* The RHash becomes available to process
81
static VALUE rh_reset(VALUE self) {
83
Data_Get_Struct(self, struct rhash_context, ctx);
88
static VALUE rh_print(VALUE self, VALUE type, int flags) {
91
Data_Get_Struct(self, struct rhash_context, ctx);
92
int len = rhash_print(buf, ctx, type == Qnil ? 0 : FIX2INT(type), flags);
93
return rb_str_new(buf, len);
101
* Returns value of the RHash digest as raw bytes.
102
* If RHash was created with a single hashing algorithm
103
* then argument may be omitted.
105
static VALUE rh_to_raw(int argc, VALUE* argv, VALUE self) {
107
rb_scan_args(argc, argv, "01", &type);
108
return rh_print(self, type, RHPR_RAW);
116
* Returns value of the RHash digest as hexadecimal string.
117
* If RHash was created with a single hashing algorithm
118
* then argument may be omitted.
120
static VALUE rh_to_hex(int argc, VALUE* argv, VALUE self) {
122
rb_scan_args(argc, argv, "01", &type);
123
return rh_print(self, type, RHPR_HEX);
128
* rhash.to_base32(id)
131
* Returns value of the RHash digest as base32 string.
132
* If RHash was created with a single hashing algorithm
133
* then argument may be omitted.
135
static VALUE rh_to_base32(int argc, VALUE* argv, VALUE self) {
137
rb_scan_args(argc, argv, "01", &type);
138
return rh_print(self, type, RHPR_BASE32);
143
* rhash.magnet(filepath)
146
* Returns magnet link with all hashes computed by
148
* if filepath is specified, then it is url-encoded
149
* and included into the resulting magnet link.
151
static VALUE rh_magnet(int argc, VALUE* argv, VALUE self) {
153
const char* filepath = 0;
158
Data_Get_Struct(self, struct rhash_context, ctx);
160
rb_scan_args(argc, argv, "01", &value);
162
if (TYPE(value) != T_STRING) value = rb_obj_as_string(value);
163
filepath = RSTRING_PTR(value);
166
buf_size = rhash_print_magnet(0, filepath, ctx, RHASH_ALL_HASHES, RHPR_FILESIZE);
167
buf = (char*)malloc(buf_size);
168
if (!buf) return Qnil;
170
rhash_print_magnet(buf, filepath, ctx, RHASH_ALL_HASHES, RHPR_FILESIZE);
171
value = rb_str_new2(buf);
178
* rhash.to_base64(id)
181
* Returns value of the RHash digest as base64 string.
182
* If RHash was created with a single hashing algorithm
183
* then argument may be omitted.
185
static VALUE rh_to_base64(int argc, VALUE* argv, VALUE self) {
187
rb_scan_args(argc, argv, "01", &type);
188
return rh_print(self, type, RHPR_BASE64);
196
* Returns value of the RHash digest for given algorithm
197
* as string in default format. If RHash was created with
198
* a single hashing algorithm then argument may be omitted.
200
static VALUE rh_to_s(int argc, VALUE* argv, VALUE self) {
202
rb_scan_args(argc, argv, "01", &type);
203
return rh_print(self, type, 0);
208
* RHash.base32?(id) -> true or false
210
* Returns true if default format for given hash algorithm is
211
* base32 and false if it is hexadecimal.
213
static VALUE rh_is_base32(VALUE self, VALUE type) {
214
return rhash_is_base32(FIX2INT(type)) ? Qtrue : Qfalse;
217
static VALUE rh_init(int argc, VALUE *argv, VALUE self) {
225
* Creates RHash object to calculate hashes for given algorithms.
226
* Parameters should be constants defined in this class.
228
VALUE rh_new(int argc, VALUE* argv, VALUE clz) {
230
for (i=0; i<argc; i++) {
231
flags |= FIX2INT(argv[i]);
233
if (!flags) flags = RHASH_ALL_HASHES;
234
rhash ctx = rhash_init(flags);
235
rhash_set_autofinal(ctx, 0);
236
VALUE newobj = Data_Wrap_Struct(clz, NULL, rh_free, ctx);
237
rb_obj_call_init(newobj, argc, argv);
242
* Librhash is a library for computing and verifying hash sums
243
* that supports many hashing algorithms. This module provides
244
* class for incremental hashing that utilizes the library.
245
* Sample usage of it you can see from the following example:
247
* hasher = RHash.new(RHash::CRC32, RHash::MD5)
248
* hasher.update('Hello, ')
249
* hasher << 'world' << '!'
251
* puts hasher.to_hex RHash::CRC32
252
* puts hasher.to_base32 RHash::MD5
257
* ntjvk3plbwsuxsqgbngdsr4yhe
259
* In this example <code>RHash</code> object is first created
260
* for a set of hashing algorithms.
262
* Next, data for hashing is given in chunks with methods
263
* <code>update</code> and <code>update_file</code>. Finally,
264
* call <code>finish</code> to end up all remaining calculations.
266
* To receive text represenation of the message digest use one
267
* of methods <code>to_hex</code>, <code>to_base32</code> and
268
* <code>to_base64</code>. Binary message digest may be obtained
269
* with <code>to_raw</code>. All of these methods accept algorithm
270
* value as argument. It may be omitted if <code>RHash</code> was
271
* created to compute hash for only a single hashing algorithm.
274
rhash_library_init();
276
cRHash = rb_define_class("RHash", rb_cObject);
278
rb_define_singleton_method(cRHash, "new", rh_new, -1);
279
rb_define_singleton_method(cRHash, "base32?", rh_is_base32, 1);
281
rb_define_method(cRHash, "initialize", rh_init, -1);
282
rb_define_method(cRHash, "update", rh_update, 1);
283
rb_define_method(cRHash, "<<", rh_update, 1);
284
rb_define_method(cRHash, "finish", rh_finish, 0);
285
rb_define_method(cRHash, "reset", rh_reset, 0);
286
rb_define_method(cRHash, "to_raw", rh_to_raw, -1);
287
rb_define_method(cRHash, "to_hex", rh_to_hex, -1);
288
rb_define_method(cRHash, "to_base32", rh_to_base32, -1);
289
rb_define_method(cRHash, "to_base64", rh_to_base64, -1);
290
rb_define_method(cRHash, "to_s", rh_to_s, -1);
291
rb_define_method(cRHash, "magnet", rh_magnet, -1);
295
def update_file(filename) \n\
296
f = File.open(filename, 'rb') \n\
297
while block = f.read(4096) \n\
298
self.update(block) \n\
304
def RHash.hash_for_msg(msg, hash_id)\n\
305
RHash.new(hash_id).update(msg).finish.to_s\n\
308
def RHash.hash_for_file(filename, hash_id)\n\
309
RHash.new(hash_id).update_file(filename).finish.to_s\n\
312
def RHash.magnet_for_file(filename, *hash_ids)\n\
313
RHash.new(*hash_ids).update_file(filename).finish.magnet(filename)\n\
316
/** CRC32 checksum. */
317
rb_define_const(cRHash, "CRC32", INT2FIX(RHASH_CRC32));
319
rb_define_const(cRHash, "MD4", INT2FIX(RHASH_MD4));
321
rb_define_const(cRHash, "MD5", INT2FIX(RHASH_MD5));
323
rb_define_const(cRHash, "SHA1", INT2FIX(RHASH_SHA1));
325
rb_define_const(cRHash, "TIGER", INT2FIX(RHASH_TIGER));
326
/** Tiger tree hash */
327
rb_define_const(cRHash, "TTH", INT2FIX(RHASH_TTH));
328
/** BitTorrent info hash. */
329
rb_define_const(cRHash, "BTIH", INT2FIX(RHASH_BTIH));
330
/** EDonkey 2000 hash. */
331
rb_define_const(cRHash, "ED2K", INT2FIX(RHASH_ED2K));
333
rb_define_const(cRHash, "AICH", INT2FIX(RHASH_AICH));
334
/** Whirlpool hash. */
335
rb_define_const(cRHash, "WHIRLPOOL", INT2FIX(RHASH_WHIRLPOOL));
336
/** RIPEMD-160 hash. */
337
rb_define_const(cRHash, "RIPEMD160", INT2FIX(RHASH_RIPEMD160));
338
/** GOST R 34.11-94. */
339
rb_define_const(cRHash, "GOST", INT2FIX(RHASH_GOST));
340
/** GOST R 34.11-94. */
341
rb_define_const(cRHash, "GOST_CRYPTOPRO", INT2FIX(RHASH_GOST_CRYPTOPRO));
343
rb_define_const(cRHash, "HAS160", INT2FIX(RHASH_HAS160));
344
/** Snefru-128 hash. */
345
rb_define_const(cRHash, "SNEFRU128", INT2FIX(RHASH_SNEFRU128));
346
/** Snefru-256 hash. */
347
rb_define_const(cRHash, "SNEFRU256", INT2FIX(RHASH_SNEFRU256));
349
rb_define_const(cRHash, "SHA224", INT2FIX(RHASH_SHA224));
351
rb_define_const(cRHash, "SHA256", INT2FIX(RHASH_SHA256));
353
rb_define_const(cRHash, "SHA384", INT2FIX(RHASH_SHA384));
355
rb_define_const(cRHash, "SHA512", INT2FIX(RHASH_SHA512));
357
rb_define_const(cRHash, "EDONR256", INT2FIX(RHASH_EDONR256));
359
rb_define_const(cRHash, "EDONR512", INT2FIX(RHASH_EDONR512));
360
/** Create RHash with this parameter to compute hashes for all available algorithms. */
361
rb_define_const(cRHash, "ALL", INT2FIX(RHASH_ALL_HASHES));