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.
- checksums.yaml +7 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +84 -0
- data/Rakefile +20 -0
- data/digest-kangarootwelve.gemspec +29 -0
- data/ext/digest/kangarootwelve/KangarooTwelve.c +275 -0
- data/ext/digest/kangarootwelve/KangarooTwelve.h +93 -0
- data/ext/digest/kangarootwelve/KeccakP-1600-SnP.h +38 -0
- data/ext/digest/kangarootwelve/KeccakP-1600-compact64.c +412 -0
- data/ext/digest/kangarootwelve/KeccakP-1600-times2-SnP.h +45 -0
- data/ext/digest/kangarootwelve/KeccakP-1600-times2-on1.c +31 -0
- data/ext/digest/kangarootwelve/KeccakP-1600-times4-SnP.h +45 -0
- data/ext/digest/kangarootwelve/KeccakP-1600-times4-on1.c +31 -0
- data/ext/digest/kangarootwelve/KeccakP-1600-times8-SnP.h +45 -0
- data/ext/digest/kangarootwelve/KeccakP-1600-times8-on1.c +31 -0
- data/ext/digest/kangarootwelve/KeccakSponge-common.h +37 -0
- data/ext/digest/kangarootwelve/KeccakSponge.inc +313 -0
- data/ext/digest/kangarootwelve/KeccakSpongeWidth1600.c +56 -0
- data/ext/digest/kangarootwelve/KeccakSpongeWidth1600.h +33 -0
- data/ext/digest/kangarootwelve/Phases.h +26 -0
- data/ext/digest/kangarootwelve/PlSnP-Fallback.inc +283 -0
- data/ext/digest/kangarootwelve/SnP-Relaned.h +134 -0
- data/ext/digest/kangarootwelve/align.h +34 -0
- data/ext/digest/kangarootwelve/brg_endian.h +142 -0
- data/ext/digest/kangarootwelve/ext.c +640 -0
- data/ext/digest/kangarootwelve/extconf.rb +2 -0
- data/lib/digest/kangarootwelve/version.rb +5 -0
- data/test/test.rb +102 -0
- metadata +116 -0
@@ -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
|
+
}
|