sha3 2.2.1 → 2.2.3
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/.rubocop.yml +66 -0
- data/ext/sha3/common.h +118 -0
- data/ext/sha3/cshake.c +32 -105
- data/ext/sha3/cshake.h +3 -3
- data/ext/sha3/digest.c +101 -79
- data/ext/sha3/kmac.c +34 -109
- data/ext/sha3/kmac.h +5 -2
- data/ext/sha3/sp800_185.c +110 -119
- data/ext/sha3/sp800_185.h +69 -22
- data/lib/constants.rb +1 -1
- data/sha3.gemspec +4 -4
- data.tar.gz.sig +0 -0
- metadata +4 -3
- metadata.gz.sig +2 -1
data/ext/sha3/sp800_185.c
CHANGED
@@ -1,45 +1,85 @@
|
|
1
1
|
#include "sp800_185.h"
|
2
2
|
|
3
|
-
|
3
|
+
/* Wrapper functions for consistent interface */
|
4
|
+
static int cshake128_init_wrapper(void *state, void *params) {
|
5
|
+
cshake_init_params_t *p = (cshake_init_params_t *)params;
|
6
|
+
return cSHAKE128_Initialize(state, p->capacity, p->N, p->NLen, p->S, p->SLen);
|
7
|
+
}
|
8
|
+
|
9
|
+
static int cshake256_init_wrapper(void *state, void *params) {
|
10
|
+
cshake_init_params_t *p = (cshake_init_params_t *)params;
|
11
|
+
return cSHAKE256_Initialize(state, p->capacity, p->N, p->NLen, p->S, p->SLen);
|
12
|
+
}
|
13
|
+
|
14
|
+
static int kmac128_init_wrapper(void *state, void *params) {
|
15
|
+
kmac_init_params_t *p = (kmac_init_params_t *)params;
|
16
|
+
return KMAC128_Initialize(state, p->key, p->keyBitLen, p->outputBitLen, p->customization, p->customBitLen);
|
17
|
+
}
|
18
|
+
|
19
|
+
static int kmac256_init_wrapper(void *state, void *params) {
|
20
|
+
kmac_init_params_t *p = (kmac_init_params_t *)params;
|
21
|
+
return KMAC256_Initialize(state, p->key, p->keyBitLen, p->outputBitLen, p->customization, p->customBitLen);
|
22
|
+
}
|
4
23
|
|
5
24
|
/*** Function table for SP800-185 algorithms ***/
|
6
25
|
sp800_185_function_table_t sp800_185_functions[] = {{.algorithm = SP800_185_CSHAKE_128,
|
7
26
|
.name = "CSHAKE128",
|
8
27
|
.state_size = sizeof(cSHAKE_Instance),
|
9
|
-
.
|
10
|
-
|
11
|
-
|
12
|
-
|
28
|
+
.is_keyed = false,
|
29
|
+
.init = cshake128_init_wrapper,
|
30
|
+
.update = (sp800_185_update_fn)cSHAKE128_Update,
|
31
|
+
.final = (sp800_185_final_fn)cSHAKE128_Final,
|
32
|
+
.squeeze = (sp800_185_squeeze_fn)cSHAKE128_Squeeze},
|
13
33
|
{.algorithm = SP800_185_CSHAKE_256,
|
14
34
|
.name = "CSHAKE256",
|
15
35
|
.state_size = sizeof(cSHAKE_Instance),
|
16
|
-
.
|
17
|
-
|
18
|
-
|
19
|
-
|
36
|
+
.is_keyed = false,
|
37
|
+
.init = cshake256_init_wrapper,
|
38
|
+
.update = (sp800_185_update_fn)cSHAKE256_Update,
|
39
|
+
.final = (sp800_185_final_fn)cSHAKE256_Final,
|
40
|
+
.squeeze = (sp800_185_squeeze_fn)cSHAKE256_Squeeze},
|
20
41
|
{.algorithm = SP800_185_KMAC_128,
|
21
42
|
.name = "KMAC128",
|
22
43
|
.state_size = sizeof(KMAC_Instance),
|
23
|
-
.
|
24
|
-
|
25
|
-
|
26
|
-
|
44
|
+
.is_keyed = true,
|
45
|
+
.init = kmac128_init_wrapper,
|
46
|
+
.update = (sp800_185_update_fn)KMAC128_Update,
|
47
|
+
.final = (sp800_185_final_fn)KMAC128_Final,
|
48
|
+
.squeeze = (sp800_185_squeeze_fn)KMAC128_Squeeze},
|
27
49
|
{.algorithm = SP800_185_KMAC_256,
|
28
50
|
.name = "KMAC256",
|
29
51
|
.state_size = sizeof(KMAC_Instance),
|
30
|
-
.
|
31
|
-
|
32
|
-
|
33
|
-
|
52
|
+
.is_keyed = true,
|
53
|
+
.init = kmac256_init_wrapper,
|
54
|
+
.update = (sp800_185_update_fn)KMAC256_Update,
|
55
|
+
.final = (sp800_185_final_fn)KMAC256_Final,
|
56
|
+
.squeeze = (sp800_185_squeeze_fn)KMAC256_Squeeze}};
|
57
|
+
|
58
|
+
/* Algorithm lookup functions */
|
59
|
+
const sp800_185_function_table_t *sp800_185_get_algorithm(sp800_185_algorithm_t algorithm) {
|
60
|
+
if (algorithm >= SP800_185_CSHAKE_128 && algorithm <= SP800_185_KMAC_256) {
|
61
|
+
return &sp800_185_functions[algorithm];
|
62
|
+
}
|
63
|
+
return NULL;
|
64
|
+
}
|
65
|
+
|
66
|
+
const sp800_185_function_table_t *sp800_185_get_algorithm_by_name(const char *name) {
|
67
|
+
for (size_t i = 0; i < sizeof(sp800_185_functions) / sizeof(sp800_185_functions[0]); i++) {
|
68
|
+
if (strcmp(sp800_185_functions[i].name, name) == 0) {
|
69
|
+
return &sp800_185_functions[i];
|
70
|
+
}
|
71
|
+
}
|
72
|
+
return NULL;
|
73
|
+
}
|
34
74
|
|
35
75
|
// Generic context allocation function
|
36
76
|
sp800_185_context_t *sp800_185_alloc_context(size_t context_size, size_t state_size) {
|
37
|
-
sp800_185_context_t *context = (sp800_185_context_t *)
|
77
|
+
sp800_185_context_t *context = (sp800_185_context_t *)ruby_xmalloc(context_size);
|
38
78
|
if (!context) return NULL;
|
39
79
|
|
40
|
-
context->state =
|
80
|
+
context->state = ruby_xcalloc(1, state_size);
|
41
81
|
if (!context->state) {
|
42
|
-
|
82
|
+
ruby_xfree(context);
|
43
83
|
return NULL;
|
44
84
|
}
|
45
85
|
|
@@ -52,9 +92,9 @@ sp800_185_context_t *sp800_185_alloc_context(size_t context_size, size_t state_s
|
|
52
92
|
void sp800_185_free_context(sp800_185_context_t *context) {
|
53
93
|
if (context) {
|
54
94
|
if (context->state) {
|
55
|
-
|
95
|
+
ruby_xfree(context->state);
|
56
96
|
}
|
57
|
-
|
97
|
+
ruby_xfree(context);
|
58
98
|
}
|
59
99
|
}
|
60
100
|
|
@@ -72,7 +112,7 @@ void *sp800_185_copy_state(sp800_185_context_t *context) {
|
|
72
112
|
if (context->functions->state_size <= 0) {
|
73
113
|
rb_raise(context->error_class, "invalid state size");
|
74
114
|
}
|
75
|
-
void *state_copy =
|
115
|
+
void *state_copy = ruby_xmalloc(context->functions->state_size);
|
76
116
|
|
77
117
|
if (!state_copy) {
|
78
118
|
rb_raise(rb_eNoMemError, "failed to allocate memory for state copy");
|
@@ -85,6 +125,12 @@ void *sp800_185_copy_state(sp800_185_context_t *context) {
|
|
85
125
|
|
86
126
|
VALUE sp800_185_update(sp800_185_context_t *context, VALUE data) {
|
87
127
|
StringValue(data);
|
128
|
+
|
129
|
+
// Check for NULL data pointer
|
130
|
+
if (RSTRING_PTR(data) == NULL && RSTRING_LEN(data) > 0) {
|
131
|
+
rb_raise(context->error_class, "cannot update with NULL data");
|
132
|
+
}
|
133
|
+
|
88
134
|
size_t data_len = (RSTRING_LEN(data) * 8);
|
89
135
|
|
90
136
|
if (data_len == 0) {
|
@@ -94,21 +140,7 @@ VALUE sp800_185_update(sp800_185_context_t *context, VALUE data) {
|
|
94
140
|
// Use the function table to call the appropriate update function
|
95
141
|
int result;
|
96
142
|
|
97
|
-
|
98
|
-
switch (context->functions->algorithm) {
|
99
|
-
case SP800_185_CSHAKE_128:
|
100
|
-
case SP800_185_CSHAKE_256:
|
101
|
-
result =
|
102
|
-
context->functions->cshake.update(context->state, (const BitSequence *)RSTRING_PTR(data), data_len);
|
103
|
-
break;
|
104
|
-
case SP800_185_KMAC_128:
|
105
|
-
case SP800_185_KMAC_256:
|
106
|
-
result = context->functions->kmac.update(context->state, (const BitSequence *)RSTRING_PTR(data), data_len);
|
107
|
-
break;
|
108
|
-
default:
|
109
|
-
rb_raise(context->error_class, "unknown algorithm");
|
110
|
-
return Qnil;
|
111
|
-
}
|
143
|
+
result = context->functions->update(context->state, (const BitSequence *)RSTRING_PTR(data), data_len);
|
112
144
|
|
113
145
|
if (result != 0) {
|
114
146
|
rb_raise(context->error_class, "failed to update %s state", context->functions->name);
|
@@ -129,19 +161,7 @@ VALUE sp800_185_finish(sp800_185_context_t *context, VALUE output) {
|
|
129
161
|
// Use the function table to call the appropriate final function
|
130
162
|
int result;
|
131
163
|
|
132
|
-
|
133
|
-
case SP800_185_CSHAKE_128:
|
134
|
-
case SP800_185_CSHAKE_256:
|
135
|
-
result = context->functions->cshake.final(context->state, (BitSequence *)RSTRING_PTR(output));
|
136
|
-
break;
|
137
|
-
case SP800_185_KMAC_128:
|
138
|
-
case SP800_185_KMAC_256:
|
139
|
-
result = context->functions->kmac.final(context->state, (BitSequence *)RSTRING_PTR(output));
|
140
|
-
break;
|
141
|
-
default:
|
142
|
-
rb_raise(context->error_class, "unknown algorithm");
|
143
|
-
return Qnil;
|
144
|
-
}
|
164
|
+
result = context->functions->final(context->state, (BitSequence *)RSTRING_PTR(output));
|
145
165
|
|
146
166
|
if (result != 0) {
|
147
167
|
rb_raise(context->error_class, "failed to finalize %s state", context->functions->name);
|
@@ -158,7 +178,7 @@ VALUE sp800_185_digest(sp800_185_context_t *context, VALUE data) {
|
|
158
178
|
}
|
159
179
|
|
160
180
|
// Create a copy of the state for processing
|
161
|
-
void *state_copy =
|
181
|
+
void *state_copy = ruby_xmalloc(context->functions->state_size);
|
162
182
|
if (!state_copy) {
|
163
183
|
rb_raise(rb_eNoMemError, "failed to allocate memory for state copy");
|
164
184
|
}
|
@@ -173,25 +193,10 @@ VALUE sp800_185_digest(sp800_185_context_t *context, VALUE data) {
|
|
173
193
|
size_t data_len = (RSTRING_LEN(data) * 8);
|
174
194
|
|
175
195
|
if (data_len > 0) {
|
176
|
-
|
177
|
-
case SP800_185_CSHAKE_128:
|
178
|
-
case SP800_185_CSHAKE_256:
|
179
|
-
result =
|
180
|
-
context->functions->cshake.update(state_copy, (const BitSequence *)RSTRING_PTR(data), data_len);
|
181
|
-
break;
|
182
|
-
case SP800_185_KMAC_128:
|
183
|
-
case SP800_185_KMAC_256:
|
184
|
-
result =
|
185
|
-
context->functions->kmac.update(state_copy, (const BitSequence *)RSTRING_PTR(data), data_len);
|
186
|
-
break;
|
187
|
-
default:
|
188
|
-
free(state_copy);
|
189
|
-
rb_raise(context->error_class, "unknown algorithm");
|
190
|
-
return Qnil;
|
191
|
-
}
|
196
|
+
result = context->functions->update(state_copy, (const BitSequence *)RSTRING_PTR(data), data_len);
|
192
197
|
|
193
198
|
if (result != 0) {
|
194
|
-
|
199
|
+
ruby_xfree(state_copy);
|
195
200
|
rb_raise(context->error_class, "failed to update %s state", context->functions->name);
|
196
201
|
}
|
197
202
|
}
|
@@ -200,22 +205,9 @@ VALUE sp800_185_digest(sp800_185_context_t *context, VALUE data) {
|
|
200
205
|
// Prepare output and finalize
|
201
206
|
VALUE output = rb_str_new(0, context->output_length / 8);
|
202
207
|
|
203
|
-
|
204
|
-
case SP800_185_CSHAKE_128:
|
205
|
-
case SP800_185_CSHAKE_256:
|
206
|
-
result = context->functions->cshake.final(state_copy, (BitSequence *)RSTRING_PTR(output));
|
207
|
-
break;
|
208
|
-
case SP800_185_KMAC_128:
|
209
|
-
case SP800_185_KMAC_256:
|
210
|
-
result = context->functions->kmac.final(state_copy, (BitSequence *)RSTRING_PTR(output));
|
211
|
-
break;
|
212
|
-
default:
|
213
|
-
free(state_copy);
|
214
|
-
rb_raise(context->error_class, "unknown algorithm");
|
215
|
-
return Qnil;
|
216
|
-
}
|
208
|
+
result = context->functions->final(state_copy, (BitSequence *)RSTRING_PTR(output));
|
217
209
|
|
218
|
-
|
210
|
+
ruby_xfree(state_copy);
|
219
211
|
|
220
212
|
if (result != 0) {
|
221
213
|
rb_raise(context->error_class, "failed to finalize %s state", context->functions->name);
|
@@ -234,18 +226,23 @@ VALUE sp800_185_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
234
226
|
rb_raise(context->error_class, "use digest methods for fixed-length output");
|
235
227
|
}
|
236
228
|
|
237
|
-
|
229
|
+
long output_byte_len;
|
238
230
|
VALUE str;
|
239
231
|
|
240
232
|
Check_Type(length, T_FIXNUM);
|
241
|
-
output_byte_len =
|
233
|
+
output_byte_len = NUM2LONG(length);
|
242
234
|
|
243
235
|
if (output_byte_len <= 0) {
|
244
|
-
rb_raise(context->error_class, "output length must be
|
236
|
+
rb_raise(context->error_class, "output length must be positive");
|
237
|
+
}
|
238
|
+
|
239
|
+
// Limit output to 1MB for safety
|
240
|
+
if (output_byte_len > (1L << 20)) {
|
241
|
+
rb_raise(context->error_class, "output length too large (max 1MB)");
|
245
242
|
}
|
246
243
|
|
247
244
|
// Create a copy of the state for processing
|
248
|
-
void *state_copy =
|
245
|
+
void *state_copy = ruby_xmalloc(context->functions->state_size);
|
249
246
|
if (!state_copy) {
|
250
247
|
rb_raise(rb_eNoMemError, "failed to allocate memory for state copy");
|
251
248
|
}
|
@@ -256,23 +253,10 @@ VALUE sp800_185_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
256
253
|
VALUE dummy_output = rb_str_new(0, 0);
|
257
254
|
int result;
|
258
255
|
|
259
|
-
|
260
|
-
case SP800_185_CSHAKE_128:
|
261
|
-
case SP800_185_CSHAKE_256:
|
262
|
-
result = context->functions->cshake.final(state_copy, (BitSequence *)RSTRING_PTR(dummy_output));
|
263
|
-
break;
|
264
|
-
case SP800_185_KMAC_128:
|
265
|
-
case SP800_185_KMAC_256:
|
266
|
-
result = context->functions->kmac.final(state_copy, (BitSequence *)RSTRING_PTR(dummy_output));
|
267
|
-
break;
|
268
|
-
default:
|
269
|
-
free(state_copy);
|
270
|
-
rb_raise(context->error_class, "unknown algorithm");
|
271
|
-
return Qnil;
|
272
|
-
}
|
256
|
+
result = context->functions->final(state_copy, (BitSequence *)RSTRING_PTR(dummy_output));
|
273
257
|
|
274
258
|
if (result != 0) {
|
275
|
-
|
259
|
+
ruby_xfree(state_copy);
|
276
260
|
rb_raise(context->error_class, "failed to finalize %s state", context->functions->name);
|
277
261
|
}
|
278
262
|
|
@@ -280,23 +264,9 @@ VALUE sp800_185_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
280
264
|
str = rb_str_new(0, output_byte_len);
|
281
265
|
|
282
266
|
// Use the function table to call the appropriate squeeze function
|
283
|
-
|
284
|
-
case SP800_185_CSHAKE_128:
|
285
|
-
case SP800_185_CSHAKE_256:
|
286
|
-
result =
|
287
|
-
context->functions->cshake.squeeze(state_copy, (BitSequence *)RSTRING_PTR(str), output_byte_len * 8);
|
288
|
-
break;
|
289
|
-
case SP800_185_KMAC_128:
|
290
|
-
case SP800_185_KMAC_256:
|
291
|
-
result = context->functions->kmac.squeeze(state_copy, (BitSequence *)RSTRING_PTR(str), output_byte_len * 8);
|
292
|
-
break;
|
293
|
-
default:
|
294
|
-
free(state_copy);
|
295
|
-
rb_raise(context->error_class, "unknown algorithm");
|
296
|
-
return Qnil;
|
297
|
-
}
|
267
|
+
result = context->functions->squeeze(state_copy, (BitSequence *)RSTRING_PTR(str), output_byte_len * 8);
|
298
268
|
|
299
|
-
|
269
|
+
ruby_xfree(state_copy);
|
300
270
|
|
301
271
|
if (result != 0) {
|
302
272
|
rb_raise(context->error_class, "failed to squeeze %s", context->functions->name);
|
@@ -309,3 +279,24 @@ VALUE sp800_185_hex_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
309
279
|
VALUE binary_result = sp800_185_squeeze(context, length);
|
310
280
|
return rb_funcall(binary_result, rb_intern("unpack1"), 1, rb_str_new2("H*"));
|
311
281
|
}
|
282
|
+
|
283
|
+
/* Ruby wrapper functions for common method patterns */
|
284
|
+
|
285
|
+
VALUE sp800_185_rb_update(sp800_185_context_t *context, VALUE data) {
|
286
|
+
sp800_185_update(context, data);
|
287
|
+
return Qnil; // Caller will return self
|
288
|
+
}
|
289
|
+
|
290
|
+
VALUE sp800_185_rb_name(sp800_185_context_t *context) { return rb_str_new2(sp800_185_name(context)); }
|
291
|
+
|
292
|
+
VALUE sp800_185_rb_finish(sp800_185_context_t *context, VALUE output) { return sp800_185_finish(context, output); }
|
293
|
+
|
294
|
+
VALUE sp800_185_rb_digest(sp800_185_context_t *context, VALUE data) { return sp800_185_digest(context, data); }
|
295
|
+
|
296
|
+
VALUE sp800_185_rb_hexdigest(sp800_185_context_t *context, VALUE data) { return sp800_185_hexdigest(context, data); }
|
297
|
+
|
298
|
+
VALUE sp800_185_rb_squeeze(sp800_185_context_t *context, VALUE length) { return sp800_185_squeeze(context, length); }
|
299
|
+
|
300
|
+
VALUE sp800_185_rb_hex_squeeze(sp800_185_context_t *context, VALUE length) {
|
301
|
+
return sp800_185_hex_squeeze(context, length);
|
302
|
+
}
|
data/ext/sha3/sp800_185.h
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
#include <ruby.h>
|
5
5
|
#include <ruby/thread.h>
|
6
|
+
#include <stdbool.h>
|
6
7
|
|
7
8
|
#include "KeccakHash.h"
|
8
9
|
#include "SP800-185.h"
|
@@ -11,6 +12,12 @@
|
|
11
12
|
extern "C" {
|
12
13
|
#endif
|
13
14
|
|
15
|
+
/* Forward declarations for types from Keccak if not already defined */
|
16
|
+
#ifndef KECCAK_TYPES_DEFINED
|
17
|
+
typedef unsigned char BitSequence;
|
18
|
+
typedef size_t BitLength;
|
19
|
+
#endif
|
20
|
+
|
14
21
|
/* SP800-185 algorithm family */
|
15
22
|
typedef enum {
|
16
23
|
SP800_185_CSHAKE_128 = 0,
|
@@ -20,37 +27,49 @@ typedef enum {
|
|
20
27
|
} sp800_185_algorithm_t;
|
21
28
|
|
22
29
|
/* Common function pointer typedefs for SP800-185 algorithms */
|
23
|
-
typedef int (*sp800_185_init_fn)(void *state, size_t capacity, const BitSequence *N, size_t NLen, const BitSequence *S,
|
24
|
-
size_t SLen);
|
25
|
-
|
26
|
-
typedef int (*sp800_185_init_key_fn)(void *state, const BitSequence *key, BitLength keyBitLen, BitLength outputBitLen,
|
27
|
-
const BitSequence *customization, BitLength customBitLen);
|
28
|
-
|
29
30
|
typedef int (*sp800_185_update_fn)(void *state, const BitSequence *data, size_t dataLen);
|
30
31
|
typedef int (*sp800_185_final_fn)(void *state, BitSequence *output);
|
31
32
|
typedef int (*sp800_185_squeeze_fn)(void *state, BitSequence *output, size_t outputLen);
|
32
33
|
|
33
|
-
/*
|
34
|
+
/* Error codes for SP800-185 operations */
|
35
|
+
typedef enum {
|
36
|
+
SP800_185_SUCCESS = 0,
|
37
|
+
SP800_185_ERROR_INVALID_ALGORITHM = -1,
|
38
|
+
SP800_185_ERROR_INVALID_PARAMS = -2,
|
39
|
+
SP800_185_ERROR_INIT_FAILED = -3,
|
40
|
+
SP800_185_ERROR_INVALID_STATE = -4
|
41
|
+
} sp800_185_error_t;
|
42
|
+
|
43
|
+
/* Parameter structures for different algorithms */
|
44
|
+
typedef struct {
|
45
|
+
size_t capacity;
|
46
|
+
const BitSequence *N;
|
47
|
+
size_t NLen;
|
48
|
+
const BitSequence *S;
|
49
|
+
size_t SLen;
|
50
|
+
} cshake_init_params_t;
|
51
|
+
|
52
|
+
typedef struct {
|
53
|
+
const BitSequence *key;
|
54
|
+
BitLength keyBitLen;
|
55
|
+
BitLength outputBitLen;
|
56
|
+
const BitSequence *customization;
|
57
|
+
BitLength customBitLen;
|
58
|
+
} kmac_init_params_t;
|
59
|
+
|
34
60
|
typedef struct {
|
35
61
|
sp800_185_algorithm_t algorithm;
|
36
62
|
const char *name;
|
37
63
|
size_t state_size;
|
64
|
+
bool is_keyed; /* true for KMAC, false for CSHAKE */
|
65
|
+
|
66
|
+
/* All algorithms use these same signatures */
|
67
|
+
sp800_185_update_fn update;
|
68
|
+
sp800_185_final_fn final;
|
69
|
+
sp800_185_squeeze_fn squeeze;
|
38
70
|
|
39
|
-
|
40
|
-
|
41
|
-
sp800_185_init_fn init;
|
42
|
-
sp800_185_update_fn update;
|
43
|
-
sp800_185_final_fn final;
|
44
|
-
sp800_185_squeeze_fn squeeze;
|
45
|
-
} cshake;
|
46
|
-
|
47
|
-
struct {
|
48
|
-
sp800_185_init_key_fn init;
|
49
|
-
sp800_185_update_fn update;
|
50
|
-
sp800_185_final_fn final;
|
51
|
-
sp800_185_squeeze_fn squeeze;
|
52
|
-
} kmac;
|
53
|
-
};
|
71
|
+
/* Generic initialization - let the caller handle parameter differences */
|
72
|
+
int (*init)(void *state, void *params);
|
54
73
|
} sp800_185_function_table_t;
|
55
74
|
|
56
75
|
/* Base context structure for SP800-185 algorithms */
|
@@ -64,6 +83,34 @@ typedef struct {
|
|
64
83
|
/* Global variables */
|
65
84
|
extern sp800_185_function_table_t sp800_185_functions[];
|
66
85
|
|
86
|
+
/* Algorithm lookup functions */
|
87
|
+
const sp800_185_function_table_t *sp800_185_get_algorithm(sp800_185_algorithm_t algorithm);
|
88
|
+
const sp800_185_function_table_t *sp800_185_get_algorithm_by_name(const char *name);
|
89
|
+
|
90
|
+
/* Safe accessor functions for algorithm-specific operations */
|
91
|
+
static inline int sp800_185_init_cshake(const sp800_185_function_table_t *table, void *state, size_t capacity,
|
92
|
+
const BitSequence *N, size_t NLen, const BitSequence *S, size_t SLen) {
|
93
|
+
if (!table || table->is_keyed) {
|
94
|
+
return SP800_185_ERROR_INVALID_ALGORITHM;
|
95
|
+
}
|
96
|
+
cshake_init_params_t params = {capacity, N, NLen, S, SLen};
|
97
|
+
return table->init(state, ¶ms);
|
98
|
+
}
|
99
|
+
|
100
|
+
static inline int sp800_185_init_kmac(const sp800_185_function_table_t *table, void *state, const BitSequence *key,
|
101
|
+
BitLength keyBitLen, BitLength outputBitLen, const BitSequence *customization,
|
102
|
+
BitLength customBitLen) {
|
103
|
+
if (!table || !table->is_keyed) {
|
104
|
+
return SP800_185_ERROR_INVALID_ALGORITHM;
|
105
|
+
}
|
106
|
+
kmac_init_params_t params = {key, keyBitLen, outputBitLen, customization, customBitLen};
|
107
|
+
return table->init(state, ¶ms);
|
108
|
+
}
|
109
|
+
|
110
|
+
/* Validation and utility functions */
|
111
|
+
bool sp800_185_validate_table(const sp800_185_function_table_t *table);
|
112
|
+
const char *sp800_185_algorithm_name(sp800_185_algorithm_t algorithm);
|
113
|
+
|
67
114
|
extern sp800_185_context_t *sp800_185_alloc_context(size_t, size_t);
|
68
115
|
extern size_t sp800_185_context_size(const sp800_185_context_t *, size_t);
|
69
116
|
extern void sp800_185_free_context(sp800_185_context_t *);
|
data/lib/constants.rb
CHANGED
data/sha3.gemspec
CHANGED
@@ -9,11 +9,11 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ['Johanns Gregorian']
|
10
10
|
spec.email = ['io+sha3@jsg.io']
|
11
11
|
|
12
|
-
spec.description = <<~
|
12
|
+
spec.description = <<~DESC
|
13
13
|
A high-performance native binding to the SHA3 (FIPS 202) cryptographic hashing algorithms, based on the XKCP - eXtended Keccak Code Package.
|
14
14
|
This gem provides support for the standard SHA-3 fixed-length functions (224, 256, 384, and 512 bits),
|
15
15
|
as well as the SHAKE128/SHAKE256 extendable-output functions (XOFs), cSHAKE128/256, and KMAC as specified in NIST SP 800-185.'
|
16
|
-
|
16
|
+
DESC
|
17
17
|
spec.summary = 'SHA-3 (FIPS 202), SHAKE128/SHAKE256, cSHAKE128/cSHAKE256, and KMAC (NIST SP 800-185), powered by XKCP.'
|
18
18
|
|
19
19
|
spec.homepage = 'https://github.com/johanns/sha3'
|
@@ -24,11 +24,11 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.metadata['homepage_uri'] = spec.homepage
|
25
25
|
spec.metadata['documentation_uri'] = 'https://docs.jsg.io/sha3/index.html'
|
26
26
|
|
27
|
-
spec.post_install_message = <<-
|
27
|
+
spec.post_install_message = <<-NOTICE
|
28
28
|
[NOTICE] SHA3 version 2.0 introduces breaking changes to the API.
|
29
29
|
Please review the changelog and ensure compatibility with your application.
|
30
30
|
If you need the previous behavior, lock your Gemfile to version '~> 1.0'."
|
31
|
-
|
31
|
+
NOTICE
|
32
32
|
|
33
33
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
34
34
|
`git ls-files -z`.split("\x0").reject do |f|
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sha3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Johanns Gregorian
|
@@ -34,7 +34,7 @@ cert_chain:
|
|
34
34
|
UjZtrp/rHLfHln46RvB+a1NlMRWxtJ7mQc/CMEbT+cpHlzuYa9qGakA4TmMpK10h
|
35
35
|
uYUv/V6CD4iTEMby0dopwHt5NqE=
|
36
36
|
-----END CERTIFICATE-----
|
37
|
-
date:
|
37
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
38
38
|
dependencies: []
|
39
39
|
description: |
|
40
40
|
A high-performance native binding to the SHA3 (FIPS 202) cryptographic hashing algorithms, based on the XKCP - eXtended Keccak Code Package.
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- Rakefile
|
63
63
|
- certs/io+sha3@jsg.io.pem
|
64
64
|
- doc/sha3.rb
|
65
|
+
- ext/sha3/common.h
|
65
66
|
- ext/sha3/config.h
|
66
67
|
- ext/sha3/cshake.c
|
67
68
|
- ext/sha3/cshake.h
|
@@ -130,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
131
|
- !ruby/object:Gem::Version
|
131
132
|
version: '0'
|
132
133
|
requirements: []
|
133
|
-
rubygems_version: 3.
|
134
|
+
rubygems_version: 3.7.1
|
134
135
|
specification_version: 4
|
135
136
|
summary: SHA-3 (FIPS 202), SHAKE128/SHAKE256, cSHAKE128/cSHAKE256, and KMAC (NIST
|
136
137
|
SP 800-185), powered by XKCP.
|
metadata.gz.sig
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
n���,����e�/��K��ڒFɎ�~홭�,1S:���
|
2
|
+
��� �f<u���I�xs��
|