digest-kangarootwelve 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ /*
2
+ Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3
+ Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4
+ denoted as "the implementer".
5
+
6
+ For more information, feedback or questions, please refer to our websites:
7
+ http://keccak.noekeon.org/
8
+ http://keyak.noekeon.org/
9
+ http://ketje.noekeon.org/
10
+
11
+ To the extent possible under law, the implementer has waived all copyright
12
+ and related or neighboring rights to the source code in this file.
13
+ http://creativecommons.org/publicdomain/zero/1.0/
14
+ */
15
+
16
+ #ifndef _align_h_
17
+ #define _align_h_
18
+
19
+ /* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */
20
+ #ifdef ALIGN
21
+ #undef ALIGN
22
+ #endif
23
+
24
+ #if defined(__GNUC__)
25
+ #define ALIGN(x) __attribute__ ((aligned(x)))
26
+ #elif defined(_MSC_VER)
27
+ #define ALIGN(x) __declspec(align(x))
28
+ #elif defined(__ARMCC_VERSION)
29
+ #define ALIGN(x) __align(x)
30
+ #else
31
+ #define ALIGN(x)
32
+ #endif
33
+
34
+ #endif
@@ -0,0 +1,142 @@
1
+ /*
2
+ ---------------------------------------------------------------------------
3
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
4
+
5
+ LICENSE TERMS
6
+
7
+ The redistribution and use of this software (with or without changes)
8
+ is allowed without the payment of fees or royalties provided that:
9
+
10
+ 1. source code distributions include the above copyright notice, this
11
+ list of conditions and the following disclaimer;
12
+
13
+ 2. binary distributions include the above copyright notice, this list
14
+ of conditions and the following disclaimer in their documentation;
15
+
16
+ 3. the name of the copyright holder is not used to endorse products
17
+ built using this software without specific written permission.
18
+
19
+ DISCLAIMER
20
+
21
+ This software is provided 'as is' with no explicit or implied warranties
22
+ in respect of its properties, including, but not limited to, correctness
23
+ and/or fitness for purpose.
24
+ ---------------------------------------------------------------------------
25
+ Issue Date: 20/12/2007
26
+ Changes for ARM 9/9/2010
27
+ */
28
+
29
+ #ifndef _BRG_ENDIAN_H
30
+ #define _BRG_ENDIAN_H
31
+
32
+ #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
33
+ #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
34
+
35
+ #if 0
36
+ /* Include files where endian defines and byteswap functions may reside */
37
+ #if defined( __sun )
38
+ # include <sys/isa_defs.h>
39
+ #elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
40
+ # include <sys/endian.h>
41
+ #elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
42
+ defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
43
+ # include <machine/endian.h>
44
+ #elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
45
+ # if !defined( __MINGW32__ ) && !defined( _AIX )
46
+ # include <endian.h>
47
+ # if !defined( __BEOS__ )
48
+ # include <byteswap.h>
49
+ # endif
50
+ # endif
51
+ #endif
52
+ #endif
53
+
54
+ /* Now attempt to set the define for platform byte order using any */
55
+ /* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
56
+ /* seem to encompass most endian symbol definitions */
57
+
58
+ #if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
59
+ # if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
60
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
61
+ # elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
62
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
63
+ # endif
64
+ #elif defined( BIG_ENDIAN )
65
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
66
+ #elif defined( LITTLE_ENDIAN )
67
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
68
+ #endif
69
+
70
+ #if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
71
+ # if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
72
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
73
+ # elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
74
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
75
+ # endif
76
+ #elif defined( _BIG_ENDIAN )
77
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
78
+ #elif defined( _LITTLE_ENDIAN )
79
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
80
+ #endif
81
+
82
+ #if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
83
+ # if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
84
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
85
+ # elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
86
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
87
+ # endif
88
+ #elif defined( __BIG_ENDIAN )
89
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
90
+ #elif defined( __LITTLE_ENDIAN )
91
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
92
+ #endif
93
+
94
+ #if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
95
+ # if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
96
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
97
+ # elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
98
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
99
+ # endif
100
+ #elif defined( __BIG_ENDIAN__ )
101
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
102
+ #elif defined( __LITTLE_ENDIAN__ )
103
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
104
+ #endif
105
+
106
+ /* if the platform byte order could not be determined, then try to */
107
+ /* set this define using common machine defines */
108
+ #if !defined(PLATFORM_BYTE_ORDER)
109
+
110
+ #if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
111
+ defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
112
+ defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
113
+ defined( vax ) || defined( vms ) || defined( VMS ) || \
114
+ defined( __VMS ) || defined( _M_X64 )
115
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
116
+
117
+ #elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
118
+ defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
119
+ defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
120
+ defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
121
+ defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
122
+ defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
123
+ defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
124
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
125
+
126
+ #elif defined(__arm__)
127
+ # ifdef __BIG_ENDIAN
128
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
129
+ # else
130
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
131
+ # endif
132
+ #elif 1 /* **** EDIT HERE IF NECESSARY **** */
133
+ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
134
+ #elif 0 /* **** EDIT HERE IF NECESSARY **** */
135
+ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
136
+ #else
137
+ # error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
138
+ #endif
139
+
140
+ #endif
141
+
142
+ #endif
@@ -0,0 +1,640 @@
1
+ /*
2
+ * Copyright (c) 2017 konsolebox
3
+ *
4
+ * MIT License
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining
7
+ * a copy of this software and associated documentation files (the
8
+ * "Software"), to deal in the Software without restriction, including
9
+ * without limitation the rights to use, copy, modify, merge, publish,
10
+ * distribute, sublicense, and/or sell copies of the Software, and to
11
+ * permit persons to whom the Software is furnished to do so, subject to
12
+ * the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be
15
+ * included in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+ #include "KangarooTwelve.h"
27
+ #include <ruby.h>
28
+ #include <ruby/digest.h>
29
+
30
+ #define KT_DEFAULT_DIGEST_LENGTH 64 /* 512 bits */
31
+ #define KT_DEFAULT_BLOCK_LENGTH 8192 * 8 /* chunkSize * Parallellism */
32
+ #define KT_MIN_DIGEST_LENGTH 1
33
+ #define KT_MIN_BLOCK_LENGTH 64
34
+
35
+ #define KT_DIGEST_API_VERSION_IS_SUPPORTED(version) (version == 3)
36
+
37
+ #if !(KT_DIGEST_API_VERSION_IS_SUPPORTED(RUBY_DIGEST_API_VERSION))
38
+ # error Digest API version is not supported.
39
+ #endif
40
+
41
+ #define KT_DEBUG(...) fprintf(stderr, __VA_ARGS__)
42
+
43
+ static ID _id_auto;
44
+ static ID _id_block_length;
45
+ static ID _id_b;
46
+ static ID _id_customization;
47
+ static ID _id_c;
48
+ static ID _id_default;
49
+ static ID _id_digest_length;
50
+ static ID _id_d;
51
+ static ID _id_hexdigest;
52
+ static ID _id_metadata;
53
+ static ID _id_name;
54
+ static ID _id_new;
55
+ static ID _id_n;
56
+ static ID _id_unpack;
57
+
58
+ static VALUE _module_Digest;
59
+ static VALUE _class_Digest_Base;
60
+ static VALUE _module_Digest_KangarooTwelve;
61
+ static VALUE _class_Digest_KangarooTwelve_Impl;
62
+ static VALUE _class_Digest_KangarooTwelve_Metadata;
63
+
64
+ typedef struct {
65
+ KangarooTwelve_Instance instance;
66
+ VALUE customization;
67
+ } kangarootwelve_context_t;
68
+
69
+ #define KT_CONTEXT kangarootwelve_context_t
70
+ #define KT_CONTEXT_PTR(void_ctx_ptr) ((KT_CONTEXT *) void_ctx_ptr)
71
+
72
+ static void check_digest_length(int digest_length)
73
+ {
74
+ if (!(digest_length >= KT_MIN_DIGEST_LENGTH))
75
+ rb_raise(rb_eArgError, "Digest length lesser than minimum (%d): %d", KT_MIN_DIGEST_LENGTH, digest_length);
76
+ }
77
+
78
+ static void check_block_length(int block_length)
79
+ {
80
+ if (!(block_length >= KT_MIN_BLOCK_LENGTH))
81
+ rb_raise(rb_eArgError, "Block length lesser than minimum (%d): %d", KT_MIN_BLOCK_LENGTH, block_length);
82
+ }
83
+
84
+ static int kangarootwelve_init(void *ctx)
85
+ {
86
+ if (ctx == NULL)
87
+ rb_raise(rb_eRuntimeError, "Context pointer is NULL.");
88
+
89
+ VALUE klass_or_instance = rb_current_receiver();
90
+
91
+ if (TYPE(klass_or_instance) == T_CLASS && klass_or_instance == _class_Digest_KangarooTwelve_Impl)
92
+ rb_raise(rb_eStandardError, "Digest::KangarooTwelve::Impl is a base class and cannot be instantiated.");
93
+
94
+ VALUE digest_length = rb_funcall(klass_or_instance, _id_digest_length, 0);
95
+
96
+ if (TYPE(digest_length) != T_FIXNUM)
97
+ rb_raise(rb_eTypeError, "Invalid object type for digest length.");
98
+
99
+ int digest_length_int = FIX2INT(digest_length);
100
+
101
+ check_digest_length(digest_length_int);
102
+
103
+ VALUE customization = rb_funcall(klass_or_instance, _id_customization, 0);
104
+
105
+ if (TYPE(customization) != T_NIL && TYPE(customization) != T_STRING)
106
+ rb_raise(rb_eTypeError, "Invalid object type for a customization string.");
107
+
108
+ KT_CONTEXT_PTR(ctx)->customization = customization;
109
+
110
+ if (KangarooTwelve_Initialize(&KT_CONTEXT_PTR(ctx)->instance, digest_length_int) != 0)
111
+ rb_raise(rb_eRuntimeError, "Failed to initialize hash data instance.");
112
+
113
+ return 1;
114
+ }
115
+
116
+ static void kangarootwelve_update(void *ctx, unsigned char *data, size_t length)
117
+ {
118
+ if (ctx == NULL)
119
+ rb_raise(rb_eRuntimeError, "Context pointer is NULL.");
120
+
121
+ if (data == NULL)
122
+ rb_raise(rb_eRuntimeError, "Data pointer is NULL.");
123
+
124
+ if (KangarooTwelve_Update(&KT_CONTEXT_PTR(ctx)->instance, data, length) != 0)
125
+ rb_raise(rb_eRuntimeError, "Hash update failed.");
126
+ }
127
+
128
+ static int kangarootwelve_finish(void *ctx, unsigned char *data)
129
+ {
130
+ if (ctx == NULL)
131
+ rb_raise(rb_eRuntimeError, "Context pointer is NULL.");
132
+
133
+ VALUE customization = KT_CONTEXT_PTR(ctx)->customization;
134
+
135
+ switch (TYPE(customization)) {
136
+ case T_NIL:
137
+ return KangarooTwelve_Final(&KT_CONTEXT_PTR(ctx)->instance, data, 0, 0) == 0;
138
+ case T_STRING:
139
+ return KangarooTwelve_Final(&KT_CONTEXT_PTR(ctx)->instance, data, RSTRING_PTR(customization),
140
+ RSTRING_LEN(customization)) == 0;
141
+ default:
142
+ rb_raise(rb_eRuntimeError, "Object type of customization string became invalid.");
143
+ }
144
+ }
145
+
146
+ static VALUE do_nothing(VALUE self)
147
+ {
148
+ return Qnil;
149
+ }
150
+
151
+ static VALUE implement(VALUE name, VALUE digest_length, VALUE block_length, VALUE customization)
152
+ {
153
+ if (!KT_DIGEST_API_VERSION_IS_SUPPORTED(RUBY_DIGEST_API_VERSION))
154
+ rb_raise(rb_eRuntimeError, "Digest API version is not supported.");
155
+
156
+ int digest_length_int, block_length_int;
157
+
158
+ switch (TYPE(digest_length)) {
159
+ case T_NIL:
160
+ digest_length_int = KT_DEFAULT_DIGEST_LENGTH;
161
+ break;
162
+ case T_FIXNUM:
163
+ digest_length_int = FIX2INT(digest_length);
164
+ check_digest_length(digest_length);
165
+ break;
166
+ default:
167
+ rb_raise(rb_eTypeError, "Invalid value type for digest length.");
168
+ }
169
+
170
+ switch (TYPE(block_length)) {
171
+ case T_NIL:
172
+ block_length_int = KT_DEFAULT_BLOCK_LENGTH;
173
+ break;
174
+ case T_FIXNUM:
175
+ block_length_int = FIX2INT(block_length);
176
+ check_block_length(block_length_int);
177
+ break;
178
+ default:
179
+ rb_raise(rb_eTypeError, "Invalid value type for block length.");
180
+ }
181
+
182
+ switch (TYPE(customization)) {
183
+ case T_NIL:
184
+ case T_STRING:
185
+ break;
186
+ default:
187
+ rb_raise(rb_eTypeError, "Invalid value type for customization string.");
188
+ }
189
+
190
+ VALUE impl_class_name = Qnil;
191
+ ID impl_class_name_id, id;
192
+
193
+ switch (TYPE(name)) {
194
+ case T_NIL:
195
+ break;
196
+ case T_SYMBOL:
197
+ id = SYM2ID(name);
198
+
199
+ if (id == _id_auto) {
200
+ if (customization != Qnil) {
201
+ VALUE customization_hex_in_array = rb_funcall(customization, _id_unpack, 1, rb_str_new_literal("H*"));
202
+ VALUE customization_hex = rb_ary_pop(customization_hex_in_array);
203
+ impl_class_name = rb_sprintf("KangarooTwelve_%d_%d_%s", digest_length_int, block_length_int,
204
+ StringValueCStr(customization_hex));
205
+ } else if (block_length_int != KT_DEFAULT_BLOCK_LENGTH) {
206
+ impl_class_name = rb_sprintf("KangarooTwelve_%d_%d", digest_length_int, block_length_int);
207
+ } else {
208
+ impl_class_name = rb_sprintf("KangarooTwelve_%d", digest_length_int);
209
+ }
210
+
211
+ impl_class_name_id = rb_intern_str(impl_class_name);
212
+ } else {
213
+ VALUE symbol_inspect = rb_inspect(name);
214
+ rb_raise(rb_eArgError, "Invalid symbol argument for class name: %s", StringValueCStr(symbol_inspect));
215
+ }
216
+
217
+ break;
218
+ case T_STRING:
219
+ id = rb_intern_str(name);
220
+
221
+ if (!rb_is_const_id(id))
222
+ rb_raise(rb_eArgError, "Not a valid class name: %s", StringValueCStr(name));
223
+
224
+ impl_class_name = name;
225
+ impl_class_name_id = id;
226
+ break;
227
+ default:
228
+ rb_raise(rb_eTypeError, "Invalid argument type for class name.");
229
+ }
230
+
231
+ VALUE impl_class;
232
+
233
+ if (impl_class_name == Qnil) {
234
+ impl_class = rb_funcall(rb_cClass, _id_new, 1, _class_Digest_KangarooTwelve_Impl);
235
+ } else {
236
+ if (rb_const_defined(_module_Digest, impl_class_name_id)) {
237
+ impl_class = rb_const_get(_module_Digest, impl_class_name_id);
238
+
239
+ if (TYPE(impl_class) != T_CLASS) {
240
+ rb_raise(rb_eTypeError,
241
+ "Digest::%s was already defined but is not a class.",
242
+ StringValueCStr(impl_class_name));
243
+ }
244
+
245
+ if (rb_class_superclass(impl_class) != _class_Digest_KangarooTwelve_Impl) {
246
+ rb_raise(rb_eTypeError,
247
+ "Digest::%s was already defined but not derived from Digest::KangarooTwelve::Impl.",
248
+ StringValueCStr(impl_class_name));
249
+ }
250
+
251
+ VALUE prev_digest_length = rb_ivar_get(impl_class, _id_digest_length);
252
+
253
+ if (TYPE(prev_digest_length) != T_FIXNUM) {
254
+ rb_raise(rb_eRuntimeError,
255
+ "Previous definition of Digest::%s has invalid digest length value type.",
256
+ StringValueCStr(impl_class_name));
257
+ }
258
+
259
+ int prev_digest_length_int = FIX2INT(prev_digest_length);
260
+
261
+ if (prev_digest_length_int != digest_length_int) {
262
+ rb_raise(rb_eTypeError,
263
+ "Digest::%s was already defined but has different digest length (%d instead of %d).",
264
+ StringValueCStr(impl_class_name),
265
+ prev_digest_length_int,
266
+ digest_length_int);
267
+ }
268
+
269
+ VALUE prev_block_length = rb_ivar_get(impl_class, _id_block_length);
270
+
271
+ if (TYPE(prev_block_length) != T_FIXNUM) {
272
+ rb_raise(rb_eRuntimeError,
273
+ "Previous definition of Digest::%s has invalid block length value type.",
274
+ StringValueCStr(impl_class_name));
275
+ }
276
+
277
+ int prev_block_length_int = FIX2INT(prev_block_length);
278
+
279
+ if (prev_block_length_int != block_length_int) {
280
+ rb_raise(rb_eTypeError,
281
+ "Digest::%s was already defined but has different block length (%d instead of %d).",
282
+ StringValueCStr(impl_class_name),
283
+ prev_block_length_int,
284
+ block_length_int);
285
+ }
286
+
287
+ return impl_class;
288
+ }
289
+
290
+ impl_class = rb_define_class_id_under(_module_Digest, impl_class_name_id, _class_Digest_KangarooTwelve_Impl);
291
+ }
292
+
293
+ VALUE metadata_obj;
294
+ rb_digest_metadata_t *metadata;
295
+ metadata_obj = Data_Make_Struct(_class_Digest_KangarooTwelve_Metadata, rb_digest_metadata_t, 0, -1, metadata);
296
+
297
+ metadata->api_version = RUBY_DIGEST_API_VERSION;
298
+ metadata->digest_len = digest_length_int;
299
+ metadata->block_len = block_length_int;
300
+ metadata->ctx_size = sizeof(KT_CONTEXT);
301
+ metadata->init_func = kangarootwelve_init;
302
+ metadata->update_func = kangarootwelve_update;
303
+ metadata->finish_func = kangarootwelve_finish;
304
+
305
+ rb_ivar_set(impl_class, _id_metadata, metadata_obj);
306
+ rb_ivar_set(impl_class, _id_digest_length, INT2FIX(digest_length_int));
307
+ rb_ivar_set(impl_class, _id_block_length, INT2FIX(block_length_int));
308
+ rb_ivar_set(impl_class, _id_customization, customization);
309
+
310
+ return impl_class;
311
+ }
312
+
313
+ /*
314
+ * Document-module: Digest::KangarooTwelve
315
+ *
316
+ * The Digest::KangarooTwelve module is the main component of the KangarooTwelve
317
+ * extension.
318
+ *
319
+ * To create a hashing object, one must use one of the singleton methods in this
320
+ * module to produce an implementation class, which can then be used to create
321
+ * the hashing object.
322
+ *
323
+ * An example to this is <code>hash = Digest::KangarooTwelve[32].new</code>.
324
+ *
325
+ * The produced implementation class and the hash object can be used just like
326
+ * any other implementation classes and instances in Digest.
327
+ */
328
+
329
+ /*
330
+ * call-seq: Digest::KangarooTwelve.default -> klass
331
+ *
332
+ * Returns the default implementation class which has a digest length of 64
333
+ * bytes, and doesn't have a customization string.
334
+ */
335
+ VALUE rbx_Digest_KangarooTwelve_singleton_default(VALUE self)
336
+ {
337
+ VALUE default_ = rb_ivar_get(self, _id_default);
338
+
339
+ if (NIL_P(default_)) {
340
+ default_ = implement(ID2SYM(_id_auto), INT2FIX(KT_DEFAULT_DIGEST_LENGTH), Qnil, Qnil);
341
+ rb_ivar_set(self, _id_default, default_);
342
+ }
343
+
344
+ Check_Type(default_, T_CLASS);
345
+ return default_;
346
+ }
347
+
348
+ /*
349
+ * call-seq: Digest::KangarooTwelve.implement(**opts) -> klass
350
+ *
351
+ * The Digest::KangarooTwelve::implement method is more configurable than the
352
+ * Digest::KangarooTwelve::[] method, and can implement classes with
353
+ * customization strings, a custom block length, and a different or anonymous
354
+ * name.
355
+ *
356
+ * The method can be called with the following options:
357
+ *
358
+ * :n, :name ::
359
+ * Specifies the name of the class, which would be placed in the Digest
360
+ * module.
361
+ *
362
+ * The default value for this option is +:auto+, and it implies automatic
363
+ * generation of the name. The generated name is in the format of
364
+ * Digest::KangarooTwelve_<digest_length> if neither a customization string
365
+ * nor a custom block length is specified.
366
+ *
367
+ * If a customization string is specified, the format would become
368
+ * Digest::KangarooTwelve_<digest_length>_<block_length>_<cust_str_hex>.
369
+ *
370
+ * If no customization string is specified but a custom block is, the format
371
+ * would be Digest::KangarooTwelve_<digest_length>_<block_length>.
372
+ *
373
+ * Specifying a string would make the method produce Digest::<string>.
374
+ *
375
+ * Specifying +nil+ would produce an anonymous class. I.e., a class not
376
+ * assigned to any constant, and has no name returned with Class#name,
377
+ * but +nil+.
378
+ *
379
+ * :d, :digest_length ::
380
+ * Specifies the digest length.
381
+ *
382
+ * See Digest::KangarooTwelve::DEFAULT_DIGEST_LENGTH for the default value.
383
+ *
384
+ * :b, :block_length ::
385
+ * Specifies a custom block length. This doesn't affect the digest results
386
+ * and is mostly just used for tweaking performance or memory usage. Examine
387
+ * the update function in KangarooTwelve.c to know if this is needed to be
388
+ * configured.
389
+ *
390
+ * See Digest::KangarooTwelve::DEFAULT_BLOCK_LENGTH for the default value.
391
+ *
392
+ * :c, :customization ::
393
+ * Specifies the customization string. Adding a customization string changes
394
+ * the resulting digest of every input.
395
+ *
396
+ * Calling the method with no argument would be the same as calling the
397
+ * Digest::KangarooTwelve::default method.
398
+ */
399
+ VALUE rbx_Digest_KangarooTwelve_singleton_implement(int argc, VALUE *argv, VALUE self)
400
+ {
401
+ VALUE opts, name, digest_length, block_length, customization;
402
+
403
+ rb_scan_args(argc, argv, "0:", &opts);
404
+
405
+ if (NIL_P(opts)) {
406
+ name = ID2SYM(_id_auto);
407
+ digest_length = block_length = customization = Qnil;
408
+ } else {
409
+ name = rb_hash_lookup2(opts, ID2SYM(_id_n), Qundef);
410
+
411
+ if (name == Qundef)
412
+ name = rb_hash_lookup2(opts, ID2SYM(_id_name), ID2SYM(_id_auto));
413
+
414
+ digest_length = rb_hash_lookup2(opts, ID2SYM(_id_d), Qundef);
415
+
416
+ if (digest_length == Qundef)
417
+ digest_length = rb_hash_lookup2(opts, ID2SYM(_id_digest_length), Qnil);
418
+
419
+ block_length = rb_hash_lookup2(opts, ID2SYM(_id_b), Qundef);
420
+
421
+ if (block_length == Qundef)
422
+ block_length = rb_hash_lookup2(opts, ID2SYM(_id_block_length), Qnil);
423
+
424
+ customization = rb_hash_lookup2(opts, ID2SYM(_id_c), Qundef);
425
+
426
+ if (customization == Qundef)
427
+ customization = rb_hash_lookup2(opts, ID2SYM(_id_customization), Qnil);
428
+ }
429
+
430
+ return implement(name, digest_length, block_length, customization);
431
+ }
432
+
433
+ /*
434
+ * call-seq: Digest::KangarooTwelve[digest_length] -> klass
435
+ *
436
+ * Creates an implementation class with specified digest length. This method
437
+ * is the simpler form of Digest::KangarooTwelve.implement.
438
+ *
439
+ * The class is generated in the name form of
440
+ * Digest::KangarooTwelve_<digest_length>, and can be directly referenced after
441
+ * this method is called.
442
+ */
443
+ VALUE rbx_Digest_KangarooTwelve_singleton_implement_simple(VALUE self, VALUE digest_length)
444
+ {
445
+ return implement(ID2SYM(_id_auto), digest_length, Qnil, Qnil);
446
+ }
447
+
448
+ /*
449
+ * Document-class: Digest::KangarooTwelve::Impl
450
+ *
451
+ * This is the base class for KangarooTwelve's implementation classes,
452
+ * and it adds additional class methods and instance methods to the methods
453
+ * provided by Digest::Base, which can be used with the implementaion classes
454
+ * and the hashing objects respectively.
455
+ */
456
+
457
+ /*
458
+ * call-seq: new -> obj
459
+ *
460
+ * Creates a new object instance of the implementation class.
461
+ */
462
+ VALUE rbx_Digest_KangarooTwelve_Impl_singleton_new(VALUE self)
463
+ {
464
+ if (self == _class_Digest_KangarooTwelve_Impl)
465
+ rb_raise(rb_eRuntimeError, "Digest::KangarooTwelve::Impl is an abstract class.");
466
+
467
+ if (rb_obj_class(rb_ivar_get(self, _id_metadata)) != _class_Digest_KangarooTwelve_Metadata)
468
+ rb_raise(rb_eRuntimeError, "Metadata not set or invalid. Please do not manually inherit KangarooTwelve.");
469
+
470
+ return rb_call_super(0, 0);
471
+ }
472
+
473
+ /*
474
+ * call-seq: digest_length -> int
475
+ *
476
+ * Returns configured digest length of the implementation class.
477
+ */
478
+ VALUE rbx_Digest_KangarooTwelve_Impl_singleton_digest_length(VALUE self)
479
+ {
480
+ if (self == _class_Digest_KangarooTwelve_Impl)
481
+ rb_raise(rb_eRuntimeError, "Digest::KangarooTwelve::Impl is an abstract class.");
482
+
483
+ return rb_ivar_get(self, _id_digest_length);
484
+ }
485
+
486
+ /*
487
+ * call-seq: block_length -> int
488
+ *
489
+ * Returns configured block length of the implementation class.
490
+ */
491
+ VALUE rbx_Digest_KangarooTwelve_Impl_singleton_block_length(VALUE self)
492
+ {
493
+ if (self == _class_Digest_KangarooTwelve_Impl)
494
+ rb_raise(rb_eRuntimeError, "Digest::KangarooTwelve::Impl is an abstract class.");
495
+
496
+ return rb_ivar_get(self, _id_block_length);
497
+ }
498
+
499
+ /*
500
+ * call-seq: customization -> string or nil
501
+ *
502
+ * Returns configured customization string of the implementation class.
503
+ */
504
+ VALUE rbx_Digest_KangarooTwelve_Impl_singleton_customization(VALUE self)
505
+ {
506
+ if (self == _class_Digest_KangarooTwelve_Impl)
507
+ rb_raise(rb_eRuntimeError, "Digest::KangarooTwelve::Impl is an abstract class.");
508
+
509
+ return rb_ivar_get(self, _id_customization);
510
+ }
511
+
512
+ /*
513
+ * call-seq: customization -> string or nil
514
+ *
515
+ * Returns configured customization string of the implementation object.
516
+ */
517
+ VALUE rbx_Digest_KangarooTwelve_Impl_customization(VALUE self)
518
+ {
519
+ VALUE customization;
520
+
521
+ if (rb_ivar_defined(self, _id_customization)) {
522
+ customization = rb_ivar_get(self, _id_customization);
523
+ } else {
524
+ VALUE klass = rb_obj_class(self);
525
+ customization = rb_ivar_get(klass, _id_customization);
526
+ rb_ivar_set(self, _id_customization, customization);
527
+ }
528
+
529
+ return customization;
530
+ }
531
+
532
+ /*
533
+ * call-seq: inspect -> string
534
+ *
535
+ * Returns a string in the format of #<implementation_class_name|digest_length|block_length|customization_string|digest>
536
+ */
537
+ VALUE rbx_Digest_KangarooTwelve_inspect(VALUE self)
538
+ {
539
+ VALUE klass = rb_obj_class(self);
540
+ VALUE klass_name = rb_class_name(klass);
541
+
542
+ if (klass_name == Qnil)
543
+ klass_name = rb_inspect(klass);
544
+
545
+ VALUE digest_length = rb_funcall(self, _id_digest_length, 0);
546
+ VALUE block_length = rb_funcall(self, _id_block_length, 0);
547
+ VALUE customization = rb_funcall(self, _id_customization, 0);
548
+ VALUE hexdigest = rb_funcall(self, _id_hexdigest, 0);
549
+
550
+ VALUE args[] = { klass_name, digest_length, block_length, customization, hexdigest };
551
+ return rb_str_format(sizeof(args), args, rb_str_new_literal("#<%s|%d|%d|%s|%s>"));
552
+ }
553
+
554
+ /*
555
+ * Init
556
+ */
557
+
558
+ void Init_kangarootwelve()
559
+ {
560
+ #define DEFINE_ID(x) _id_##x = rb_intern_const(#x);
561
+
562
+ DEFINE_ID(auto)
563
+ DEFINE_ID(block_length)
564
+ DEFINE_ID(b)
565
+ DEFINE_ID(customization)
566
+ DEFINE_ID(c)
567
+ DEFINE_ID(default)
568
+ DEFINE_ID(digest_length)
569
+ DEFINE_ID(d)
570
+ DEFINE_ID(hexdigest)
571
+ DEFINE_ID(metadata)
572
+ DEFINE_ID(name)
573
+ DEFINE_ID(new)
574
+ DEFINE_ID(n)
575
+ DEFINE_ID(unpack)
576
+
577
+ rb_require("digest");
578
+ _module_Digest = rb_path2class("Digest");
579
+ _class_Digest_Base = rb_path2class("Digest::Base");
580
+
581
+ #if 0
582
+ _module_Digest = rb_define_module("Digest"); /* Tell RDoc about Digest since it doesn't recognize rb_path2class. */
583
+ #endif
584
+
585
+ /*
586
+ * module Digest::KangarooTwelve
587
+ */
588
+
589
+ _module_Digest_KangarooTwelve = rb_define_module_under(_module_Digest, "KangarooTwelve");
590
+
591
+ rb_define_singleton_method(_module_Digest_KangarooTwelve, "default",
592
+ rbx_Digest_KangarooTwelve_singleton_default, 0);
593
+ rb_define_singleton_method(_module_Digest_KangarooTwelve, "implement",
594
+ rbx_Digest_KangarooTwelve_singleton_implement, -1);
595
+ rb_define_singleton_method(_module_Digest_KangarooTwelve, "[]",
596
+ rbx_Digest_KangarooTwelve_singleton_implement_simple, 1);
597
+
598
+ /*
599
+ * Currently 65536 bytes (8192 x 8)
600
+ */
601
+
602
+ rb_define_const(_module_Digest_KangarooTwelve, "DEFAULT_BLOCK_LENGTH", INT2FIX(KT_DEFAULT_BLOCK_LENGTH));
603
+
604
+ /*
605
+ * 64 bytes (512 bits)
606
+ */
607
+
608
+ rb_define_const(_module_Digest_KangarooTwelve, "DEFAULT_DIGEST_LENGTH", INT2FIX(KT_DEFAULT_DIGEST_LENGTH));
609
+
610
+ /*
611
+ * class Digest::KangarooTwelve::Impl < Digest::Base
612
+ */
613
+
614
+ _class_Digest_KangarooTwelve_Impl = rb_define_class_under(_module_Digest_KangarooTwelve, "Impl",
615
+ _class_Digest_Base);
616
+
617
+ rb_define_singleton_method(_class_Digest_KangarooTwelve_Impl, "new",
618
+ rbx_Digest_KangarooTwelve_Impl_singleton_new, 0);
619
+ rb_define_singleton_method(_class_Digest_KangarooTwelve_Impl, "block_length",
620
+ rbx_Digest_KangarooTwelve_Impl_singleton_block_length, 0);
621
+ rb_define_singleton_method(_class_Digest_KangarooTwelve_Impl, "digest_length",
622
+ rbx_Digest_KangarooTwelve_Impl_singleton_digest_length, 0);
623
+ rb_define_singleton_method(_class_Digest_KangarooTwelve_Impl, "customization",
624
+ rbx_Digest_KangarooTwelve_Impl_singleton_customization, 0);
625
+
626
+ rb_define_method(_class_Digest_KangarooTwelve_Impl, "customization",
627
+ rbx_Digest_KangarooTwelve_Impl_customization, 0);
628
+ rb_define_method(_class_Digest_KangarooTwelve_Impl, "inspect",
629
+ rbx_Digest_KangarooTwelve_inspect, 0);
630
+
631
+ /*
632
+ * class Digest::KangarooTwelve::Metadata < Data
633
+ *
634
+ * This class represents the internal metadata produced for the
635
+ * implementation classes.
636
+ */
637
+
638
+ _class_Digest_KangarooTwelve_Metadata = rb_define_class_under(_module_Digest_KangarooTwelve, "Metadata",
639
+ rb_path2class("Data"));
640
+ }