sha3 2.1.0 → 2.2.0
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.clang-format +4 -51
- data/.rubocop.yml +1 -1
- data/.vscode/launch.json +15 -0
- data/.vscode/settings.json +9 -0
- data/.vscode/tasks.json +29 -0
- data/CHANGELOG.md +15 -0
- data/README.md +103 -53
- data/ext/sha3/cshake.c +391 -0
- data/ext/sha3/cshake.h +17 -0
- data/ext/sha3/digest.c +90 -86
- data/ext/sha3/digest.h +2 -5
- data/ext/sha3/extconf.rb +11 -5
- data/ext/sha3/kmac.c +188 -218
- data/ext/sha3/kmac.h +3 -3
- data/ext/sha3/sha3.c +6 -2
- data/ext/sha3/sp800_185.c +311 -0
- data/ext/sha3/sp800_185.h +94 -0
- data/lib/constants.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +12 -5
- metadata.gz.sig +0 -0
data/ext/sha3/kmac.c
CHANGED
@@ -1,52 +1,39 @@
|
|
1
1
|
#include "kmac.h"
|
2
2
|
|
3
|
-
#include "KeccakHash.h"
|
4
|
-
#include "SP800-185.h"
|
5
3
|
#include "sha3.h"
|
6
|
-
|
7
|
-
// SHA3::KMAC.new(algorithm, output_length, key, customization)
|
8
|
-
// SHA3::KMAC128.new(output_length, key, customization)
|
9
|
-
// SHA3::KMAC256.new(output_length, key, customization)
|
10
|
-
// kmac.update
|
11
|
-
// kmac.digest | kmac.hexdigest
|
4
|
+
#include "sp800_185.h"
|
12
5
|
|
13
6
|
/*** Types and structs ***/
|
14
|
-
|
15
|
-
typedef enum { KMAC_128 = 0, KMAC_256 } sha3_kmac_algorithms;
|
16
|
-
|
17
7
|
typedef struct {
|
18
|
-
|
19
|
-
sha3_kmac_algorithms algorithm;
|
20
|
-
|
21
|
-
size_t output_length;
|
8
|
+
sp800_185_context_t base;
|
22
9
|
} sha3_kmac_context_t;
|
23
10
|
|
24
11
|
/*** Function prototypes ***/
|
25
|
-
|
26
|
-
static
|
27
|
-
static void sha3_kmac_free_context(void*);
|
28
|
-
static size_t sha3_kmac_context_size(const void*);
|
12
|
+
static void sha3_kmac_free_context(void *);
|
13
|
+
static size_t sha3_kmac_context_size(const void *);
|
29
14
|
|
30
15
|
/* Allocation and initialization */
|
31
16
|
static VALUE rb_sha3_kmac_alloc(VALUE);
|
32
|
-
static VALUE rb_sha3_kmac_init(int, VALUE*, VALUE);
|
17
|
+
static VALUE rb_sha3_kmac_init(int, VALUE *, VALUE);
|
33
18
|
static VALUE rb_sha3_kmac_copy(VALUE, VALUE);
|
34
19
|
|
35
20
|
/* Core digest operations */
|
36
|
-
static VALUE rb_sha3_kmac_finish(int, VALUE*, VALUE);
|
21
|
+
static VALUE rb_sha3_kmac_finish(int, VALUE *, VALUE);
|
37
22
|
static VALUE rb_sha3_kmac_update(VALUE, VALUE);
|
38
23
|
|
39
24
|
/* Digest properties */
|
40
25
|
static VALUE rb_sha3_kmac_name(VALUE);
|
41
26
|
|
42
27
|
/* Output methods */
|
43
|
-
static VALUE rb_sha3_kmac_digest(int, VALUE*, VALUE);
|
44
|
-
static VALUE rb_sha3_kmac_hexdigest(int, VALUE*, VALUE);
|
45
|
-
static VALUE rb_sha3_kmac_self_digest(int, VALUE*, VALUE);
|
46
|
-
static VALUE rb_sha3_kmac_self_hexdigest(int, VALUE*, VALUE);
|
28
|
+
static VALUE rb_sha3_kmac_digest(int, VALUE *, VALUE);
|
29
|
+
static VALUE rb_sha3_kmac_hexdigest(int, VALUE *, VALUE);
|
30
|
+
static VALUE rb_sha3_kmac_self_digest(int, VALUE *, VALUE);
|
31
|
+
static VALUE rb_sha3_kmac_self_hexdigest(int, VALUE *, VALUE);
|
47
32
|
|
48
|
-
|
33
|
+
static VALUE rb_sha3_kmac_squeeze(VALUE, VALUE);
|
34
|
+
static VALUE rb_sha3_kmac_hex_squeeze(VALUE, VALUE);
|
49
35
|
|
36
|
+
/*** Global variables ***/
|
50
37
|
VALUE _sha3_kmac_class;
|
51
38
|
VALUE _sha3_kmac_error_class;
|
52
39
|
|
@@ -55,21 +42,28 @@ static ID _kmac_128_id;
|
|
55
42
|
static ID _kmac_256_id;
|
56
43
|
|
57
44
|
/* TypedData structure for sha3_kmac_context_t */
|
58
|
-
const rb_data_type_t sha3_kmac_data_type_t = {
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
45
|
+
const rb_data_type_t sha3_kmac_data_type_t = {
|
46
|
+
"SHA3::KMAC",
|
47
|
+
{
|
48
|
+
NULL, sha3_kmac_free_context, sha3_kmac_context_size, NULL, /* dcompact field */
|
49
|
+
},
|
50
|
+
NULL,
|
51
|
+
NULL,
|
52
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
53
|
+
};
|
54
|
+
|
55
|
+
// Helper function to extract context from a Ruby object
|
56
|
+
void get_kmac_context(VALUE obj, sp800_185_context_t **context) {
|
57
|
+
sha3_kmac_context_t *kmac_ctx;
|
58
|
+
TypedData_Get_Struct(obj, sha3_kmac_context_t, &sha3_kmac_data_type_t, kmac_ctx);
|
59
|
+
*context = &kmac_ctx->base;
|
60
|
+
}
|
67
61
|
|
68
62
|
void Init_sha3_kmac(void) {
|
69
63
|
_kmac_128_id = rb_intern("kmac_128");
|
70
64
|
_kmac_256_id = rb_intern("kmac_256");
|
71
65
|
|
72
|
-
if (
|
66
|
+
if (!_sha3_module) {
|
73
67
|
_sha3_module = rb_define_module("SHA3");
|
74
68
|
}
|
75
69
|
|
@@ -89,7 +83,7 @@ void Init_sha3_kmac(void) {
|
|
89
83
|
* It is a subclass of the StandardError class -- see the Ruby documentation
|
90
84
|
* for more information.
|
91
85
|
*/
|
92
|
-
_sha3_kmac_error_class = rb_define_class_under(_sha3_kmac_class, "
|
86
|
+
_sha3_kmac_error_class = rb_define_class_under(_sha3_kmac_class, "Error", rb_eStandardError);
|
93
87
|
|
94
88
|
rb_define_alloc_func(_sha3_kmac_class, rb_sha3_kmac_alloc);
|
95
89
|
rb_define_method(_sha3_kmac_class, "initialize", rb_sha3_kmac_init, -1);
|
@@ -100,6 +94,9 @@ void Init_sha3_kmac(void) {
|
|
100
94
|
rb_define_method(_sha3_kmac_class, "digest", rb_sha3_kmac_digest, -1);
|
101
95
|
rb_define_method(_sha3_kmac_class, "hexdigest", rb_sha3_kmac_hexdigest, -1);
|
102
96
|
|
97
|
+
rb_define_method(_sha3_kmac_class, "squeeze", rb_sha3_kmac_squeeze, 1);
|
98
|
+
rb_define_method(_sha3_kmac_class, "hex_squeeze", rb_sha3_kmac_hex_squeeze, 1);
|
99
|
+
|
103
100
|
rb_define_private_method(_sha3_kmac_class, "finish", rb_sha3_kmac_finish, -1);
|
104
101
|
|
105
102
|
rb_define_alias(_sha3_kmac_class, "<<", "update");
|
@@ -110,72 +107,22 @@ void Init_sha3_kmac(void) {
|
|
110
107
|
return;
|
111
108
|
}
|
112
109
|
|
113
|
-
static
|
114
|
-
// First check the algorithm
|
115
|
-
if (context1->algorithm != context2->algorithm) {
|
116
|
-
return 0;
|
117
|
-
}
|
118
|
-
|
119
|
-
// Compare the internal state structure
|
120
|
-
if (memcmp(context1->state, context2->state, sizeof(KMAC_Instance)) != 0) {
|
121
|
-
return 0;
|
122
|
-
}
|
123
|
-
|
124
|
-
// All comparisons passed
|
125
|
-
return 1;
|
126
|
-
}
|
127
|
-
|
128
|
-
static inline void get_sha3_kmac_context(VALUE obj, sha3_kmac_context_t** context) {
|
129
|
-
TypedData_Get_Struct((obj), sha3_kmac_context_t, &sha3_kmac_data_type_t, (*context));
|
130
|
-
if (!(*context)) {
|
131
|
-
rb_raise(rb_eRuntimeError, "KMAC data not initialized!");
|
132
|
-
}
|
133
|
-
}
|
134
|
-
|
135
|
-
static inline void safe_get_sha3_kmac_context(VALUE obj, sha3_kmac_context_t** context) {
|
136
|
-
if (!rb_obj_is_kind_of(obj, _sha3_kmac_class)) {
|
137
|
-
rb_raise(rb_eTypeError, "wrong argument (%s)! (expected %s)", rb_obj_classname(obj),
|
138
|
-
rb_class2name(_sha3_kmac_class));
|
139
|
-
}
|
140
|
-
get_sha3_kmac_context(obj, context);
|
141
|
-
}
|
142
|
-
|
143
|
-
static void sha3_kmac_free_context(void* ptr) {
|
144
|
-
sha3_kmac_context_t* context = (sha3_kmac_context_t*)ptr;
|
145
|
-
if (context) {
|
146
|
-
if (context->state) {
|
147
|
-
free(context->state);
|
148
|
-
}
|
149
|
-
free(context);
|
150
|
-
}
|
151
|
-
}
|
152
|
-
|
153
|
-
static size_t sha3_kmac_context_size(const void* ptr) {
|
154
|
-
const sha3_kmac_context_t* context = (const sha3_kmac_context_t*)ptr;
|
155
|
-
size_t size = sizeof(sha3_kmac_context_t);
|
110
|
+
static void sha3_kmac_free_context(void *ptr) { sp800_185_free_context((sp800_185_context_t *)ptr); }
|
156
111
|
|
157
|
-
|
158
|
-
|
159
|
-
}
|
160
|
-
|
161
|
-
return size;
|
112
|
+
static size_t sha3_kmac_context_size(const void *ptr) {
|
113
|
+
return sp800_185_context_size((const sp800_185_context_t *)ptr, sizeof(sha3_kmac_context_t));
|
162
114
|
}
|
163
115
|
|
164
116
|
static VALUE rb_sha3_kmac_alloc(VALUE klass) {
|
165
|
-
sha3_kmac_context_t*
|
166
|
-
|
167
|
-
rb_raise(_sha3_kmac_error_class, "failed to allocate object memory");
|
168
|
-
}
|
117
|
+
sha3_kmac_context_t *context =
|
118
|
+
(sha3_kmac_context_t *)sp800_185_alloc_context(sizeof(sha3_kmac_context_t), sizeof(KMAC_Instance));
|
169
119
|
|
170
|
-
|
171
|
-
|
172
|
-
sha3_kmac_free_context(context);
|
173
|
-
rb_raise(_sha3_kmac_error_class, "failed to allocate state memory");
|
120
|
+
if (!context) {
|
121
|
+
rb_raise(_sha3_kmac_error_class, "failed to allocate memory");
|
174
122
|
}
|
175
123
|
|
124
|
+
// Create the Ruby object with TypedData - this will automatically handle freeing
|
176
125
|
VALUE obj = TypedData_Wrap_Struct(klass, &sha3_kmac_data_type_t, context);
|
177
|
-
context->output_length = 0; // Default output length in bits
|
178
|
-
context->algorithm = KMAC_128; // Default algorithm
|
179
126
|
|
180
127
|
return obj;
|
181
128
|
}
|
@@ -193,7 +140,7 @@ static VALUE rb_sha3_kmac_alloc(VALUE klass) {
|
|
193
140
|
* - :kmac_256
|
194
141
|
*
|
195
142
|
* +output_length+::
|
196
|
-
* The length of the output in bytes.
|
143
|
+
* The length of the output in bytes. Set to 0 for an arbitrarily-long output using "squeeze" (XOF) methods.
|
197
144
|
*
|
198
145
|
* +key+::
|
199
146
|
* The key to use for the KMAC.
|
@@ -204,47 +151,63 @@ static VALUE rb_sha3_kmac_alloc(VALUE klass) {
|
|
204
151
|
* = example
|
205
152
|
* SHA3::KMAC.new(:kmac_128, 32, "key")
|
206
153
|
* SHA3::KMAC.new(:kmac_256, 64, "key", "customization")
|
154
|
+
* SHA3::KMAC.new(:kmac_128, 0, "key", "customization")
|
155
|
+
*
|
207
156
|
*/
|
208
|
-
static VALUE rb_sha3_kmac_init(int argc, VALUE*
|
209
|
-
sha3_kmac_context_t* context;
|
157
|
+
static VALUE rb_sha3_kmac_init(int argc, VALUE *argv, VALUE self) {
|
210
158
|
VALUE algorithm, output_length, key, customization;
|
211
159
|
|
212
160
|
rb_scan_args(argc, argv, "31", &algorithm, &output_length, &key, &customization);
|
213
161
|
|
214
|
-
|
162
|
+
// Check and convert arguments
|
163
|
+
if (NIL_P(algorithm)) {
|
164
|
+
rb_raise(rb_eArgError, "missing keyword: algorithm");
|
165
|
+
}
|
166
|
+
Check_Type(algorithm, T_SYMBOL);
|
167
|
+
|
168
|
+
if (NIL_P(output_length)) {
|
169
|
+
rb_raise(rb_eArgError, "missing keyword: output_length");
|
170
|
+
}
|
171
|
+
Check_Type(output_length, T_FIXNUM);
|
172
|
+
|
173
|
+
if (NIL_P(key)) {
|
174
|
+
rb_raise(rb_eArgError, "missing keyword: key");
|
175
|
+
}
|
176
|
+
StringValue(key);
|
215
177
|
|
216
|
-
|
217
|
-
|
218
|
-
context->algorithm = KMAC_128;
|
219
|
-
} else if (rb_equal(sym, _kmac_256_id)) {
|
220
|
-
context->algorithm = KMAC_256;
|
178
|
+
if (!NIL_P(customization)) {
|
179
|
+
StringValue(customization);
|
221
180
|
} else {
|
222
|
-
|
181
|
+
customization = rb_str_new2("");
|
223
182
|
}
|
224
183
|
|
225
|
-
|
226
|
-
|
227
|
-
|
184
|
+
sha3_kmac_context_t *context;
|
185
|
+
TypedData_Get_Struct(self, sha3_kmac_context_t, &sha3_kmac_data_type_t, context);
|
186
|
+
|
187
|
+
// Store the output length in bits
|
188
|
+
context->base.output_length = NUM2ULONG(output_length) * 8;
|
189
|
+
context->base.error_class = _sha3_kmac_error_class;
|
190
|
+
|
191
|
+
// Find the appropriate function table based on the algorithm
|
192
|
+
ID sym_id = SYM2ID(algorithm);
|
193
|
+
if (sym_id == _kmac_128_id) {
|
194
|
+
context->base.functions = &sp800_185_functions[SP800_185_KMAC_128];
|
195
|
+
} else if (sym_id == _kmac_256_id) {
|
196
|
+
context->base.functions = &sp800_185_functions[SP800_185_KMAC_256];
|
197
|
+
} else {
|
198
|
+
rb_raise(rb_eArgError, "invalid algorithm: %s", rb_id2name(sym_id));
|
228
199
|
}
|
229
200
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
}
|
241
|
-
} else {
|
242
|
-
if (KMAC256_Initialize(context->state, key_ptr, key_len, context->output_length,
|
243
|
-
NIL_P(customization) ? NULL : (const unsigned char*)RSTRING_PTR(customization),
|
244
|
-
NIL_P(customization) ? 0 : RSTRING_LEN(customization) * 8) != 0) {
|
245
|
-
rb_raise(_sha3_kmac_error_class, "failed to initialize KMAC256");
|
246
|
-
}
|
247
|
-
}
|
201
|
+
// Initialize the KMAC instance
|
202
|
+
size_t key_len = RSTRING_LEN(key) * 8;
|
203
|
+
size_t customization_len = RSTRING_LEN(customization) * 8;
|
204
|
+
|
205
|
+
int result = context->base.functions->kmac.init(context->base.state, (const BitSequence *)RSTRING_PTR(key), key_len,
|
206
|
+
context->base.output_length,
|
207
|
+
(const BitSequence *)RSTRING_PTR(customization), customization_len);
|
208
|
+
|
209
|
+
if (result != 0) {
|
210
|
+
rb_raise(_sha3_kmac_error_class, "failed to initialize %s", context->base.functions->name);
|
248
211
|
}
|
249
212
|
|
250
213
|
return self;
|
@@ -252,9 +215,9 @@ static VALUE rb_sha3_kmac_init(int argc, VALUE* argv, VALUE self) {
|
|
252
215
|
|
253
216
|
/*
|
254
217
|
* :call-seq:
|
255
|
-
*
|
218
|
+
* ::copy(other) -> kmac
|
256
219
|
*
|
257
|
-
*
|
220
|
+
* Creates a copy of the KMAC instance.
|
258
221
|
*
|
259
222
|
* +other+::
|
260
223
|
* The KMAC to copy the state from.
|
@@ -263,8 +226,7 @@ static VALUE rb_sha3_kmac_init(int argc, VALUE* argv, VALUE self) {
|
|
263
226
|
* new_kmac = kmac.dup
|
264
227
|
*/
|
265
228
|
static VALUE rb_sha3_kmac_copy(VALUE self, VALUE other) {
|
266
|
-
sha3_kmac_context_t*
|
267
|
-
sha3_kmac_context_t* other_context;
|
229
|
+
sha3_kmac_context_t *context, *other_context;
|
268
230
|
|
269
231
|
rb_check_frozen(self);
|
270
232
|
if (self == other) {
|
@@ -276,16 +238,15 @@ static VALUE rb_sha3_kmac_copy(VALUE self, VALUE other) {
|
|
276
238
|
rb_class2name(_sha3_kmac_class));
|
277
239
|
}
|
278
240
|
|
279
|
-
|
280
|
-
|
241
|
+
TypedData_Get_Struct(other, sha3_kmac_context_t, &sha3_kmac_data_type_t, other_context);
|
242
|
+
TypedData_Get_Struct(self, sha3_kmac_context_t, &sha3_kmac_data_type_t, context);
|
281
243
|
|
282
|
-
context
|
283
|
-
context->
|
284
|
-
|
244
|
+
// Copy the base context attributes
|
245
|
+
context->base.functions = other_context->base.functions;
|
246
|
+
context->base.output_length = other_context->base.output_length;
|
285
247
|
|
286
|
-
|
287
|
-
|
288
|
-
}
|
248
|
+
// Copy the algorithm-specific state
|
249
|
+
memcpy(context->base.state, other_context->base.state, context->base.functions->state_size);
|
289
250
|
|
290
251
|
return self;
|
291
252
|
}
|
@@ -304,89 +265,48 @@ static VALUE rb_sha3_kmac_copy(VALUE self, VALUE other) {
|
|
304
265
|
* kmac << "more data" # alias for update
|
305
266
|
*/
|
306
267
|
static VALUE rb_sha3_kmac_update(VALUE self, VALUE data) {
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
Check_Type(data, T_STRING);
|
311
|
-
data_len = RSTRING_LEN(data) * 8;
|
312
|
-
|
313
|
-
get_sha3_kmac_context(self, &context);
|
314
|
-
|
315
|
-
if (context->algorithm == KMAC_128) {
|
316
|
-
if (KMAC128_Update(context->state, (const BitSequence*)RSTRING_PTR(data), data_len) != 0) {
|
317
|
-
rb_raise(_sha3_kmac_error_class, "failed to update KMAC128");
|
318
|
-
}
|
319
|
-
} else {
|
320
|
-
if (KMAC256_Update(context->state, (const BitSequence*)RSTRING_PTR(data), data_len) != 0) {
|
321
|
-
rb_raise(_sha3_kmac_error_class, "failed to update KMAC256");
|
322
|
-
}
|
323
|
-
}
|
268
|
+
sp800_185_context_t *context;
|
269
|
+
get_kmac_context(self, &context);
|
270
|
+
sp800_185_update(context, data);
|
324
271
|
|
325
272
|
return self;
|
326
273
|
}
|
327
274
|
|
328
275
|
/*
|
329
276
|
* :call-seq:
|
330
|
-
*
|
331
|
-
*
|
332
|
-
* Returns the final KMAC as a binary string.
|
277
|
+
* name -> String
|
333
278
|
*
|
334
|
-
*
|
335
|
-
* _optional_ Output buffer to receive the final KMAC value.
|
279
|
+
* Returns the name of the algorithm.
|
336
280
|
*
|
337
281
|
* = example
|
338
|
-
* kmac.
|
282
|
+
* kmac.name #=> "KMAC128" or "KMAC256"
|
339
283
|
*/
|
340
|
-
static VALUE
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
rb_scan_args(argc, argv, "01", &output);
|
345
|
-
|
346
|
-
get_sha3_kmac_context(self, &context);
|
347
|
-
|
348
|
-
if (NIL_P(output)) {
|
349
|
-
output = rb_str_new(0, context->output_length / 8);
|
350
|
-
} else {
|
351
|
-
StringValue(output);
|
352
|
-
rb_str_resize(output, context->output_length / 8);
|
353
|
-
}
|
354
|
-
|
355
|
-
if (context->algorithm == KMAC_128) {
|
356
|
-
if (KMAC128_Final(context->state, (BitSequence*)RSTRING_PTR(output)) != 0) {
|
357
|
-
rb_raise(_sha3_kmac_error_class, "failed to finalize KMAC128");
|
358
|
-
}
|
359
|
-
} else {
|
360
|
-
if (KMAC256_Final(context->state, (BitSequence*)RSTRING_PTR(output)) != 0) {
|
361
|
-
rb_raise(_sha3_kmac_error_class, "failed to finalize KMAC256");
|
362
|
-
}
|
363
|
-
}
|
284
|
+
static VALUE rb_sha3_kmac_name(VALUE self) {
|
285
|
+
sp800_185_context_t *context;
|
286
|
+
get_kmac_context(self, &context);
|
364
287
|
|
365
|
-
return
|
288
|
+
return rb_str_new2(sp800_185_name(context));
|
366
289
|
}
|
367
290
|
|
368
291
|
/*
|
369
292
|
* :call-seq:
|
370
|
-
*
|
293
|
+
* finish([message]) -> String
|
371
294
|
*
|
372
|
-
* Returns the
|
295
|
+
* Returns the final KMAC as a binary string.
|
296
|
+
*
|
297
|
+
* +message+::
|
298
|
+
* _optional_ Output buffer to receive the final KMAC value.
|
373
299
|
*
|
374
300
|
* = example
|
375
|
-
* kmac.
|
301
|
+
* kmac.finish
|
376
302
|
*/
|
377
|
-
static VALUE
|
378
|
-
|
303
|
+
static VALUE rb_sha3_kmac_finish(int argc, VALUE *argv, VALUE self) {
|
304
|
+
sp800_185_context_t *context;
|
305
|
+
get_kmac_context(self, &context);
|
379
306
|
|
380
|
-
|
307
|
+
VALUE output = argc > 0 ? argv[0] : Qnil;
|
381
308
|
|
382
|
-
|
383
|
-
case KMAC_128:
|
384
|
-
return rb_str_new2("KMAC128");
|
385
|
-
case KMAC_256:
|
386
|
-
return rb_str_new2("KMAC256");
|
387
|
-
default:
|
388
|
-
rb_raise(_sha3_kmac_error_class, "unknown algorithm");
|
389
|
-
}
|
309
|
+
return sp800_185_finish(context, output);
|
390
310
|
}
|
391
311
|
|
392
312
|
/*
|
@@ -405,21 +325,13 @@ static VALUE rb_sha3_kmac_name(VALUE self) {
|
|
405
325
|
* kmac.digest
|
406
326
|
* kmac.digest('final chunk')
|
407
327
|
*/
|
408
|
-
static VALUE rb_sha3_kmac_digest(int argc, VALUE*
|
409
|
-
|
410
|
-
|
411
|
-
rb_scan_args(argc, argv, "01", &data);
|
328
|
+
static VALUE rb_sha3_kmac_digest(int argc, VALUE *argv, VALUE self) {
|
329
|
+
sp800_185_context_t *context;
|
330
|
+
get_kmac_context(self, &context);
|
412
331
|
|
413
|
-
|
414
|
-
copy = rb_obj_clone(self);
|
332
|
+
VALUE data = argc > 0 ? argv[0] : Qnil;
|
415
333
|
|
416
|
-
|
417
|
-
if (!NIL_P(data)) {
|
418
|
-
rb_sha3_kmac_update(copy, data);
|
419
|
-
}
|
420
|
-
|
421
|
-
// Call finish on the copy
|
422
|
-
return rb_sha3_kmac_finish(0, NULL, copy);
|
334
|
+
return sp800_185_digest(context, data);
|
423
335
|
}
|
424
336
|
|
425
337
|
/*
|
@@ -438,9 +350,55 @@ static VALUE rb_sha3_kmac_digest(int argc, VALUE* argv, VALUE self) {
|
|
438
350
|
* kmac.hexdigest
|
439
351
|
* kmac.hexdigest('final chunk')
|
440
352
|
*/
|
441
|
-
static VALUE rb_sha3_kmac_hexdigest(int argc, VALUE*
|
442
|
-
|
443
|
-
|
353
|
+
static VALUE rb_sha3_kmac_hexdigest(int argc, VALUE *argv, VALUE self) {
|
354
|
+
sp800_185_context_t *context;
|
355
|
+
get_kmac_context(self, &context);
|
356
|
+
|
357
|
+
VALUE data = argc > 0 ? argv[0] : Qnil;
|
358
|
+
|
359
|
+
return sp800_185_hexdigest(context, data);
|
360
|
+
}
|
361
|
+
|
362
|
+
/*
|
363
|
+
* :call-seq:
|
364
|
+
* squeeze(length) -> string
|
365
|
+
*
|
366
|
+
* Returns the squeezed output as a binary string.
|
367
|
+
* This method creates a copy of the current instance so that
|
368
|
+
* the original state is preserved for future updates.
|
369
|
+
*
|
370
|
+
* = note
|
371
|
+
* The KMAC instance must be initialized with 0 output length before calling this method.
|
372
|
+
*
|
373
|
+
* = example
|
374
|
+
* kmac.squeeze(128)
|
375
|
+
*/
|
376
|
+
static VALUE rb_sha3_kmac_squeeze(VALUE self, VALUE length) {
|
377
|
+
sp800_185_context_t *context;
|
378
|
+
get_kmac_context(self, &context);
|
379
|
+
|
380
|
+
return sp800_185_squeeze(context, length);
|
381
|
+
}
|
382
|
+
|
383
|
+
/*
|
384
|
+
* :call-seq:
|
385
|
+
* hex_squeeze(length) -> string
|
386
|
+
*
|
387
|
+
* Returns the squeezed output as a hexadecimal string.
|
388
|
+
* This method creates a copy of the current instance so that
|
389
|
+
* the original state is preserved for future updates.
|
390
|
+
*
|
391
|
+
* = note
|
392
|
+
* The KMAC instance must be initialized with 0 output length before calling this method.
|
393
|
+
*
|
394
|
+
* = example
|
395
|
+
* kmac.hex_squeeze(128)
|
396
|
+
*/
|
397
|
+
static VALUE rb_sha3_kmac_hex_squeeze(VALUE self, VALUE length) {
|
398
|
+
sp800_185_context_t *context;
|
399
|
+
get_kmac_context(self, &context);
|
400
|
+
|
401
|
+
return sp800_185_hex_squeeze(context, length);
|
444
402
|
}
|
445
403
|
|
446
404
|
/*
|
@@ -464,12 +422,18 @@ static VALUE rb_sha3_kmac_hexdigest(int argc, VALUE* argv, VALUE self) {
|
|
464
422
|
* SHA3::KMAC.digest(:kmac_128, "data", 32, "key")
|
465
423
|
* SHA3::KMAC.digest(:kmac_128, "data", 32, "key", "customization")
|
466
424
|
*/
|
467
|
-
static VALUE rb_sha3_kmac_self_digest(int argc, VALUE*
|
425
|
+
static VALUE rb_sha3_kmac_self_digest(int argc, VALUE *argv, VALUE klass) {
|
468
426
|
VALUE algorithm, data, output_length, key, customization;
|
469
427
|
|
470
428
|
rb_scan_args(argc, argv, "41", &algorithm, &data, &output_length, &key, &customization);
|
471
429
|
|
430
|
+
Check_Type(output_length, T_FIXNUM);
|
431
|
+
if (!NIL_P(output_length) && output_length <= INT2FIX(0)) {
|
432
|
+
rb_raise(rb_eArgError, "class method digest does not support XOF mode");
|
433
|
+
}
|
434
|
+
|
472
435
|
VALUE kmac = rb_funcall(klass, rb_intern("new"), 4, algorithm, output_length, key, customization);
|
436
|
+
|
473
437
|
return rb_funcall(kmac, rb_intern("digest"), 1, data);
|
474
438
|
}
|
475
439
|
|
@@ -494,11 +458,17 @@ static VALUE rb_sha3_kmac_self_digest(int argc, VALUE* argv, VALUE klass) {
|
|
494
458
|
* SHA3::KMAC.hexdigest(:kmac_128, "data", 32, "key")
|
495
459
|
* SHA3::KMAC.hexdigest(:kmac_128, "data", 32, "key", "customization")
|
496
460
|
*/
|
497
|
-
static VALUE rb_sha3_kmac_self_hexdigest(int argc, VALUE*
|
461
|
+
static VALUE rb_sha3_kmac_self_hexdigest(int argc, VALUE *argv, VALUE klass) {
|
498
462
|
VALUE algorithm, data, output_length, key, customization;
|
499
463
|
|
500
464
|
rb_scan_args(argc, argv, "41", &algorithm, &data, &output_length, &key, &customization);
|
501
465
|
|
466
|
+
Check_Type(output_length, T_FIXNUM);
|
467
|
+
if (!NIL_P(output_length) && output_length <= INT2FIX(0)) {
|
468
|
+
rb_raise(rb_eArgError, "class method hexdigest does not support XOF mode");
|
469
|
+
}
|
470
|
+
|
502
471
|
VALUE kmac = rb_funcall(klass, rb_intern("new"), 4, algorithm, output_length, key, customization);
|
472
|
+
|
503
473
|
return rb_funcall(kmac, rb_intern("hexdigest"), 1, data);
|
504
474
|
}
|
data/ext/sha3/kmac.h
CHANGED
data/ext/sha3/sha3.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "sha3.h"
|
2
2
|
|
3
|
+
#include "cshake.h"
|
3
4
|
#include "digest.h"
|
4
5
|
#include "kmac.h"
|
5
6
|
|
@@ -17,14 +18,17 @@ void Init_sha3_ext(void) {
|
|
17
18
|
*
|
18
19
|
* == Classes
|
19
20
|
* SHA3::Digest
|
20
|
-
* SHA3::Digest::
|
21
|
+
* SHA3::Digest::Error
|
21
22
|
* SHA3::KMAC
|
22
|
-
* SHA3::KMAC::
|
23
|
+
* SHA3::KMAC::Error
|
24
|
+
* SHA3::CSHAKE
|
25
|
+
* SHA3::CSHAKE::Error
|
23
26
|
*
|
24
27
|
*/
|
25
28
|
_sha3_module = rb_define_module("SHA3");
|
26
29
|
|
27
30
|
Init_sha3_digest();
|
31
|
+
Init_sha3_cshake();
|
28
32
|
Init_sha3_kmac();
|
29
33
|
|
30
34
|
return;
|