sha3 2.2.0 → 2.2.2
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/ext/sha3/cshake.c +17 -12
- data/ext/sha3/cshake.h +3 -3
- data/ext/sha3/kmac.c +16 -12
- data/ext/sha3/kmac.h +5 -2
- data/ext/sha3/sp800_185.c +63 -104
- data/ext/sha3/sp800_185.h +69 -32
- data/lib/constants.rb +1 -1
- data/sha3.gemspec +44 -0
- data.tar.gz.sig +0 -0
- metadata +4 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5da48a8f70ea2746484300e05125b21ab1fcd5837d0f194d8b12fac46a46602
|
4
|
+
data.tar.gz: 7be8cf46c2e1e4bc38dedb64b25654f70806d6c761427b062c171bf0df359caa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57e70a0c38eb04f0aab1fe81f0c3ee60a6eb2bc7ea6c6f2e57f8712f23084139bd4a494cde70ad99eca7e20fe1534adb7f91b9986a4ad31ac1127ffa4a115d07
|
7
|
+
data.tar.gz: 0b7cdd43dc7167e3e92f4ec2adfb947c00f0b8827aaaeafb9383213bdd1bc09771c0b17efec3d28667b1bb383646f006360496abf3dfd43a2a6cd54f8e1dd4c2
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/ext/sha3/cshake.c
CHANGED
@@ -42,10 +42,9 @@ static ID _cshake_256_id;
|
|
42
42
|
static const rb_data_type_t sha3_cshake_data_type = {
|
43
43
|
"SHA3::CSHAKE",
|
44
44
|
{
|
45
|
-
NULL,
|
46
|
-
|
47
|
-
|
48
|
-
NULL, /* dcompact field */
|
45
|
+
NULL, sha3_cshake_free_context, // Use our free function directly
|
46
|
+
sha3_cshake_context_size, /* We'll do our own size calculation */
|
47
|
+
NULL, /* dcompact field */
|
49
48
|
},
|
50
49
|
NULL,
|
51
50
|
NULL,
|
@@ -179,8 +178,8 @@ static VALUE rb_sha3_cshake_init(int argc, VALUE *argv, VALUE self) {
|
|
179
178
|
rb_intern("customization"),
|
180
179
|
};
|
181
180
|
|
182
|
-
VALUE values[
|
183
|
-
rb_get_kwargs(keywords, table, 0,
|
181
|
+
VALUE values[2];
|
182
|
+
rb_get_kwargs(keywords, table, 0, 2, values);
|
184
183
|
|
185
184
|
VALUE name_str = values[0] == Qundef ? rb_str_new2("") : values[0];
|
186
185
|
StringValue(name_str);
|
@@ -196,18 +195,24 @@ static VALUE rb_sha3_cshake_init(int argc, VALUE *argv, VALUE self) {
|
|
196
195
|
context->base.error_class = _sha3_cshake_error_class;
|
197
196
|
|
198
197
|
// Find the appropriate function table based on the algorithm
|
198
|
+
sp800_185_algorithm_t alg_type;
|
199
199
|
if (algorithm == ID2SYM(_cshake_128_id)) {
|
200
|
-
|
200
|
+
alg_type = SP800_185_CSHAKE_128;
|
201
201
|
} else if (algorithm == ID2SYM(_cshake_256_id)) {
|
202
|
-
|
202
|
+
alg_type = SP800_185_CSHAKE_256;
|
203
203
|
} else {
|
204
204
|
rb_raise(rb_eArgError, "invalid algorithm: %s", rb_id2name(SYM2ID(algorithm)));
|
205
205
|
}
|
206
206
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
207
|
+
context->base.functions = sp800_185_get_algorithm(alg_type);
|
208
|
+
if (!context->base.functions) {
|
209
|
+
rb_raise(_sha3_cshake_error_class, "algorithm not available");
|
210
|
+
}
|
211
|
+
|
212
|
+
// Initialize using the safe accessor function
|
213
|
+
int result = sp800_185_init_cshake(context->base.functions, context->base.state, context->base.output_length,
|
214
|
+
(BitSequence *)RSTRING_PTR(name_str), RSTRING_LEN(name_str) * 8,
|
215
|
+
(BitSequence *)RSTRING_PTR(customization), RSTRING_LEN(customization) * 8);
|
211
216
|
|
212
217
|
if (result != 0) {
|
213
218
|
rb_raise(_sha3_cshake_error_class, "failed to initialize %s algorithm", context->base.functions->name);
|
data/ext/sha3/cshake.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2012 - 2025 Johanns Gregorian <io+sha3@jsg.io>
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef _SHA3_CSHAKE_H_
|
4
|
+
#define _SHA3_CSHAKE_H_
|
5
5
|
|
6
6
|
#ifdef __cplusplus
|
7
7
|
extern "C" {
|
@@ -14,4 +14,4 @@ void Init_sha3_cshake(void);
|
|
14
14
|
}
|
15
15
|
#endif
|
16
16
|
|
17
|
-
#endif /*
|
17
|
+
#endif /* _SHA3_CSHAKE_H_ */
|
data/ext/sha3/kmac.c
CHANGED
@@ -70,18 +70,15 @@ void Init_sha3_kmac(void) {
|
|
70
70
|
/*
|
71
71
|
* Document-class: SHA3::KMAC
|
72
72
|
*
|
73
|
-
*
|
74
|
-
*
|
73
|
+
* KMAC (Keccak Message Authentication Code) is a MAC algorithm based on the Keccak permutation.
|
74
|
+
* It is defined in NIST SP800-185 and provides both fixed-length and XOF (arbitrary-length) output modes.
|
75
75
|
*/
|
76
76
|
_sha3_kmac_class = rb_define_class_under(_sha3_module, "KMAC", rb_cObject);
|
77
77
|
|
78
78
|
/*
|
79
|
-
* Document-class: SHA3::KMAC::
|
79
|
+
* Document-class: SHA3::KMAC::Error
|
80
80
|
*
|
81
81
|
* All KMAC methods raise this exception on error.
|
82
|
-
*
|
83
|
-
* It is a subclass of the StandardError class -- see the Ruby documentation
|
84
|
-
* for more information.
|
85
82
|
*/
|
86
83
|
_sha3_kmac_error_class = rb_define_class_under(_sha3_kmac_class, "Error", rb_eStandardError);
|
87
84
|
|
@@ -190,21 +187,28 @@ static VALUE rb_sha3_kmac_init(int argc, VALUE *argv, VALUE self) {
|
|
190
187
|
|
191
188
|
// Find the appropriate function table based on the algorithm
|
192
189
|
ID sym_id = SYM2ID(algorithm);
|
190
|
+
sp800_185_algorithm_t alg_type;
|
191
|
+
|
193
192
|
if (sym_id == _kmac_128_id) {
|
194
|
-
|
193
|
+
alg_type = SP800_185_KMAC_128;
|
195
194
|
} else if (sym_id == _kmac_256_id) {
|
196
|
-
|
195
|
+
alg_type = SP800_185_KMAC_256;
|
197
196
|
} else {
|
198
197
|
rb_raise(rb_eArgError, "invalid algorithm: %s", rb_id2name(sym_id));
|
199
198
|
}
|
200
199
|
|
201
|
-
|
200
|
+
context->base.functions = sp800_185_get_algorithm(alg_type);
|
201
|
+
if (!context->base.functions) {
|
202
|
+
rb_raise(_sha3_kmac_error_class, "algorithm not available: %s", rb_id2name(sym_id));
|
203
|
+
}
|
204
|
+
|
205
|
+
// Initialize using the safe accessor function
|
202
206
|
size_t key_len = RSTRING_LEN(key) * 8;
|
203
207
|
size_t customization_len = RSTRING_LEN(customization) * 8;
|
204
208
|
|
205
|
-
int result = context->base.functions
|
206
|
-
|
207
|
-
|
209
|
+
int result = sp800_185_init_kmac(context->base.functions, context->base.state,
|
210
|
+
(const BitSequence *)RSTRING_PTR(key), key_len, context->base.output_length,
|
211
|
+
(const BitSequence *)RSTRING_PTR(customization), customization_len);
|
208
212
|
|
209
213
|
if (result != 0) {
|
210
214
|
rb_raise(_sha3_kmac_error_class, "failed to initialize %s", context->base.functions->name);
|
data/ext/sha3/kmac.h
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
// Copyright (c) 2012 - 2025 Johanns Gregorian <io+sha3@jsg.io>
|
2
|
+
|
1
3
|
#ifndef _SHA3_KMAC_H_
|
2
4
|
#define _SHA3_KMAC_H_
|
3
5
|
|
@@ -5,10 +7,11 @@
|
|
5
7
|
extern "C" {
|
6
8
|
#endif
|
7
9
|
|
8
|
-
|
10
|
+
/* Function prototypes */
|
11
|
+
void Init_sha3_kmac(void);
|
9
12
|
|
10
13
|
#ifdef __cplusplus
|
11
14
|
}
|
12
15
|
#endif
|
13
16
|
|
14
|
-
#endif
|
17
|
+
#endif /* _SHA3_KMAC_H_ */
|
data/ext/sha3/sp800_185.c
CHANGED
@@ -1,36 +1,76 @@
|
|
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) {
|
@@ -94,21 +134,7 @@ VALUE sp800_185_update(sp800_185_context_t *context, VALUE data) {
|
|
94
134
|
// Use the function table to call the appropriate update function
|
95
135
|
int result;
|
96
136
|
|
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
|
-
}
|
137
|
+
result = context->functions->update(context->state, (const BitSequence *)RSTRING_PTR(data), data_len);
|
112
138
|
|
113
139
|
if (result != 0) {
|
114
140
|
rb_raise(context->error_class, "failed to update %s state", context->functions->name);
|
@@ -129,19 +155,7 @@ VALUE sp800_185_finish(sp800_185_context_t *context, VALUE output) {
|
|
129
155
|
// Use the function table to call the appropriate final function
|
130
156
|
int result;
|
131
157
|
|
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
|
-
}
|
158
|
+
result = context->functions->final(context->state, (BitSequence *)RSTRING_PTR(output));
|
145
159
|
|
146
160
|
if (result != 0) {
|
147
161
|
rb_raise(context->error_class, "failed to finalize %s state", context->functions->name);
|
@@ -173,22 +187,7 @@ VALUE sp800_185_digest(sp800_185_context_t *context, VALUE data) {
|
|
173
187
|
size_t data_len = (RSTRING_LEN(data) * 8);
|
174
188
|
|
175
189
|
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
|
-
}
|
190
|
+
result = context->functions->update(state_copy, (const BitSequence *)RSTRING_PTR(data), data_len);
|
192
191
|
|
193
192
|
if (result != 0) {
|
194
193
|
free(state_copy);
|
@@ -200,20 +199,7 @@ VALUE sp800_185_digest(sp800_185_context_t *context, VALUE data) {
|
|
200
199
|
// Prepare output and finalize
|
201
200
|
VALUE output = rb_str_new(0, context->output_length / 8);
|
202
201
|
|
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
|
-
}
|
202
|
+
result = context->functions->final(state_copy, (BitSequence *)RSTRING_PTR(output));
|
217
203
|
|
218
204
|
free(state_copy);
|
219
205
|
|
@@ -256,20 +242,7 @@ VALUE sp800_185_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
256
242
|
VALUE dummy_output = rb_str_new(0, 0);
|
257
243
|
int result;
|
258
244
|
|
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
|
-
}
|
245
|
+
result = context->functions->final(state_copy, (BitSequence *)RSTRING_PTR(dummy_output));
|
273
246
|
|
274
247
|
if (result != 0) {
|
275
248
|
free(state_copy);
|
@@ -280,21 +253,7 @@ VALUE sp800_185_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
280
253
|
str = rb_str_new(0, output_byte_len);
|
281
254
|
|
282
255
|
// 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
|
-
}
|
256
|
+
result = context->functions->squeeze(state_copy, (BitSequence *)RSTRING_PTR(str), output_byte_len * 8);
|
298
257
|
|
299
258
|
free(state_copy);
|
300
259
|
|
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 */
|
38
65
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
};
|
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;
|
70
|
+
|
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 *);
|
@@ -77,16 +124,6 @@ VALUE sp800_185_squeeze(sp800_185_context_t *context, VALUE length);
|
|
77
124
|
VALUE sp800_185_hex_squeeze(sp800_185_context_t *context, VALUE length);
|
78
125
|
const char *sp800_185_name(sp800_185_context_t *context);
|
79
126
|
|
80
|
-
// Macro to define common Ruby methods
|
81
|
-
#define DEFINE_SP800_185_METHOD(name) static VALUE rb_sp800_185_##name(int argc, VALUE *argv, VALUE self);
|
82
|
-
|
83
|
-
DEFINE_SP800_185_METHOD(update)
|
84
|
-
DEFINE_SP800_185_METHOD(finish)
|
85
|
-
DEFINE_SP800_185_METHOD(digest)
|
86
|
-
DEFINE_SP800_185_METHOD(hexdigest)
|
87
|
-
DEFINE_SP800_185_METHOD(squeeze)
|
88
|
-
DEFINE_SP800_185_METHOD(hex_squeeze)
|
89
|
-
|
90
127
|
#ifdef __cplusplus
|
91
128
|
}
|
92
129
|
#endif
|
data/lib/constants.rb
CHANGED
data/sha3.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/constants'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'sha3'
|
7
|
+
spec.version = SHA3::VERSION
|
8
|
+
|
9
|
+
spec.authors = ['Johanns Gregorian']
|
10
|
+
spec.email = ['io+sha3@jsg.io']
|
11
|
+
|
12
|
+
spec.description = <<~EOF
|
13
|
+
A high-performance native binding to the SHA3 (FIPS 202) cryptographic hashing algorithms, based on the XKCP - eXtended Keccak Code Package.
|
14
|
+
This gem provides support for the standard SHA-3 fixed-length functions (224, 256, 384, and 512 bits),
|
15
|
+
as well as the SHAKE128/SHAKE256 extendable-output functions (XOFs), cSHAKE128/256, and KMAC as specified in NIST SP 800-185.'
|
16
|
+
EOF
|
17
|
+
spec.summary = 'SHA-3 (FIPS 202), SHAKE128/SHAKE256, cSHAKE128/cSHAKE256, and KMAC (NIST SP 800-185), powered by XKCP.'
|
18
|
+
|
19
|
+
spec.homepage = 'https://github.com/johanns/sha3'
|
20
|
+
spec.license = 'MIT'
|
21
|
+
spec.required_ruby_version = '>= 2.7.0'
|
22
|
+
|
23
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/CHANGELOG.md"
|
24
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
25
|
+
spec.metadata['documentation_uri'] = 'https://docs.jsg.io/sha3/index.html'
|
26
|
+
|
27
|
+
spec.post_install_message = <<-EOF
|
28
|
+
[NOTICE] SHA3 version 2.0 introduces breaking changes to the API.
|
29
|
+
Please review the changelog and ensure compatibility with your application.
|
30
|
+
If you need the previous behavior, lock your Gemfile to version '~> 1.0'."
|
31
|
+
EOF
|
32
|
+
|
33
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
34
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
35
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git))})
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
spec.extensions = ['ext/sha3/extconf.rb']
|
40
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
41
|
+
|
42
|
+
spec.cert_chain = ['certs/io+sha3@jsg.io.pem']
|
43
|
+
spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem') if $PROGRAM_NAME =~ /gem\z/
|
44
|
+
end
|
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.2
|
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.
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- ext/sha3/sp800_185.h
|
104
104
|
- lib/constants.rb
|
105
105
|
- lib/sha3.rb
|
106
|
+
- sha3.gemspec
|
106
107
|
homepage: https://github.com/johanns/sha3
|
107
108
|
licenses:
|
108
109
|
- MIT
|
@@ -129,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
130
|
- !ruby/object:Gem::Version
|
130
131
|
version: '0'
|
131
132
|
requirements: []
|
132
|
-
rubygems_version: 3.6.
|
133
|
+
rubygems_version: 3.6.9
|
133
134
|
specification_version: 4
|
134
135
|
summary: SHA-3 (FIPS 202), SHAKE128/SHAKE256, cSHAKE128/cSHAKE256, and KMAC (NIST
|
135
136
|
SP 800-185), powered by XKCP.
|
metadata.gz.sig
CHANGED
Binary file
|