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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b25d248bf32a3f2971ddf97235ce8549de783fb01624c2ae70d8e82aa78754fd
4
- data.tar.gz: fa3842d268143da115070c236d181a67bbeef4f2ac3cfe41eb0a50b7049c2721
3
+ metadata.gz: 9efe4158e87ea949852977b7791cf56838a9fefdbe226ebf7fdb4c5e962e927b
4
+ data.tar.gz: 6f41a24a48b714a33f846e6458aad350be5168f33202c51a95bda7a364cffc5f
5
5
  SHA512:
6
- metadata.gz: 16c197fb78685b2ed46fd7b3de1bc7ae6305a4da07afd118d3b986377cd03e414d363da8416c2951aed334ca1e35a267c9ba1f815ad7b352812a47312b5dbddb
7
- data.tar.gz: 5f13f5dde1b91a2635c3f7db660fbbcb6e162053d5597db3e64db72ca780f095922d63e13da3475b1cb77a7c1bd7dab5d0cfafa70ed884e13237a58b1ed75809
6
+ metadata.gz: 21086756d157c20bd8f74fde996cabfc8c2a8975b913cab0da03a311d41eb3d44427e344419344e7d8729b21edf0c1d550732c583df8a1f2797b700b64468464
7
+ data.tar.gz: fd6dacfcb827ecbdf8d3d60cd1b9dfacd6f50fc9c4440100890fbac7302d26f8119da33f95b67c270c73b6f75789a7b5e569e04c638a834dce9ff99a5b2050a7
checksums.yaml.gz.sig CHANGED
Binary file
data/.rubocop.yml CHANGED
@@ -6,8 +6,74 @@ AllCops:
6
6
  NewCops: enable
7
7
  TargetRubyVersion: 2.7
8
8
 
9
+ Exclude:
10
+ - ext/**/*.rb
11
+
9
12
  Layout/LineLength:
10
13
  Max: 120
11
14
 
15
+ # Metrics
16
+
17
+ Metrics/AbcSize:
18
+ Exclude:
19
+ - spec/**/*_spec.rb
20
+
21
+ Metrics/CyclomaticComplexity:
22
+ Exclude:
23
+ - spec/**/*_spec.rb
24
+
25
+ Metrics/PerceivedComplexity:
26
+ Exclude:
27
+ - spec/**/*_spec.rb
28
+
29
+ Metrics/MethodLength:
30
+ Max: 15
31
+ Exclude:
32
+ - spec/**/*_spec.rb
33
+
34
+ # Naming
35
+
36
+ Naming/ClassAndModuleCamelCase:
37
+ Enabled: false
38
+
12
39
  Naming/VariableNumber:
13
40
  EnforcedStyle: snake_case
41
+ Exclude:
42
+ - spec/**/*.rb
43
+
44
+ # Security
45
+
46
+ # Allow URI.open for test vector downloads
47
+ Security/Open:
48
+ Exclude:
49
+ - spec/sha3_digest_vectors_spec.rb
50
+
51
+ # RSpec configuration
52
+
53
+ RSpec/ExampleLength:
54
+ Max: 15
55
+ CountAsOne:
56
+ - array
57
+ - hash
58
+ - heredoc
59
+
60
+ RSpec/MultipleExpectations:
61
+ Max: 8
62
+
63
+ RSpec/SpecFilePathFormat:
64
+ Enabled: false
65
+
66
+ RSpec/LeakyConstantDeclaration:
67
+ Enabled: false
68
+
69
+ RSpec/BeforeAfterAll:
70
+ Enabled: false
71
+
72
+ RSpec/MultipleDescribes:
73
+ Enabled: false
74
+
75
+ RSpec/NamedSubject:
76
+ Enabled: false
77
+
78
+ RSpec/DescribeClass:
79
+ Enabled: false
data/ext/sha3/common.h ADDED
@@ -0,0 +1,118 @@
1
+ // Copyright (c) 2025 Johanns Gregorian <io+sha3@jsg.io>
2
+
3
+ #ifndef _SHA3_COMMON_H_
4
+ #define _SHA3_COMMON_H_
5
+
6
+ #include <ruby.h>
7
+
8
+ #include "sp800_185.h"
9
+
10
+ #ifdef __cplusplus
11
+ extern "C" {
12
+ #endif
13
+
14
+ /* Common macros for SP800-185 based implementations (CSHAKE, KMAC) */
15
+
16
+ /* Define a simple method that just calls an sp800_185 function */
17
+ #define DEFINE_SP800_185_SIMPLE_METHOD(method_name, sp_func, get_ctx_func) \
18
+ static VALUE method_name(VALUE self, VALUE data) { \
19
+ sp800_185_context_t *context; \
20
+ get_ctx_func(self, &context); \
21
+ sp_func(context, data); \
22
+ return self; \
23
+ }
24
+
25
+ /* Define a method that returns a value from sp800_185 function */
26
+ #define DEFINE_SP800_185_RETURN_METHOD(method_name, sp_func, get_ctx_func) \
27
+ static VALUE method_name(VALUE self) { \
28
+ sp800_185_context_t *context; \
29
+ get_ctx_func(self, &context); \
30
+ return sp_func(context); \
31
+ }
32
+
33
+ /* Define a method with single VALUE parameter that returns VALUE */
34
+ #define DEFINE_SP800_185_VALUE_METHOD(method_name, sp_func, get_ctx_func) \
35
+ static VALUE method_name(VALUE self, VALUE param) { \
36
+ sp800_185_context_t *context; \
37
+ get_ctx_func(self, &context); \
38
+ return sp_func(context, param); \
39
+ }
40
+
41
+ /* Define a method with variable arguments */
42
+ #define DEFINE_SP800_185_VARARGS_METHOD(method_name, sp_func, get_ctx_func) \
43
+ static VALUE method_name(int argc, VALUE *argv, VALUE self) { \
44
+ sp800_185_context_t *context; \
45
+ get_ctx_func(self, &context); \
46
+ VALUE param = argc > 0 ? argv[0] : Qnil; \
47
+ return sp_func(context, param); \
48
+ }
49
+
50
+ /* Define common memory management functions */
51
+ #define DEFINE_SP800_185_MEMORY_FUNCS(prefix, context_type) \
52
+ static void prefix##_free_context(void *ptr) { sp800_185_free_context((sp800_185_context_t *)ptr); } \
53
+ \
54
+ static size_t prefix##_context_size(const void *ptr) { \
55
+ return sp800_185_context_size((const sp800_185_context_t *)ptr, sizeof(context_type)); \
56
+ }
57
+
58
+ /* Define common allocation function */
59
+ #define DEFINE_SP800_185_ALLOC(prefix, context_type, instance_type, error_class) \
60
+ static VALUE rb_##prefix##_alloc(VALUE klass) { \
61
+ context_type *context = (context_type *)sp800_185_alloc_context(sizeof(context_type), sizeof(instance_type)); \
62
+ \
63
+ if (!context) { \
64
+ rb_raise(error_class, "failed to allocate memory"); \
65
+ } \
66
+ \
67
+ VALUE obj = TypedData_Wrap_Struct(klass, &prefix##_data_type, context); \
68
+ return obj; \
69
+ }
70
+
71
+ /* Define common copy method */
72
+ #define DEFINE_SP800_185_COPY_METHOD(method_name, context_type, data_type, class_var) \
73
+ static VALUE method_name(VALUE self, VALUE other) { \
74
+ context_type *context, *other_context; \
75
+ \
76
+ rb_check_frozen(self); \
77
+ if (self == other) { \
78
+ return self; \
79
+ } \
80
+ \
81
+ if (!rb_obj_is_kind_of(other, class_var)) { \
82
+ rb_raise(rb_eTypeError, "wrong argument (%s)! (expected %s)", rb_obj_classname(other), \
83
+ rb_class2name(class_var)); \
84
+ } \
85
+ \
86
+ TypedData_Get_Struct(other, context_type, &data_type, other_context); \
87
+ TypedData_Get_Struct(self, context_type, &data_type, context); \
88
+ \
89
+ /* Copy the base context attributes */ \
90
+ context->base.functions = other_context->base.functions; \
91
+ context->base.output_length = other_context->base.output_length; \
92
+ context->base.error_class = other_context->base.error_class; \
93
+ \
94
+ /* Copy the algorithm-specific state */ \
95
+ if (context->base.functions && other_context->base.state) { \
96
+ memcpy(context->base.state, other_context->base.state, context->base.functions->state_size); \
97
+ } \
98
+ \
99
+ return self; \
100
+ }
101
+
102
+ /* Ruby wrapper functions for SP800-185 operations */
103
+ VALUE sp800_185_rb_update(sp800_185_context_t *context, VALUE data);
104
+ VALUE sp800_185_rb_name(sp800_185_context_t *context);
105
+ VALUE sp800_185_rb_finish(sp800_185_context_t *context, VALUE output);
106
+ VALUE sp800_185_rb_digest(sp800_185_context_t *context, VALUE data);
107
+ VALUE sp800_185_rb_hexdigest(sp800_185_context_t *context, VALUE data);
108
+ VALUE sp800_185_rb_squeeze(sp800_185_context_t *context, VALUE length);
109
+ VALUE sp800_185_rb_hex_squeeze(sp800_185_context_t *context, VALUE length);
110
+
111
+ /* Helper function to register common methods */
112
+ void register_sp800_185_common_methods(VALUE klass);
113
+
114
+ #ifdef __cplusplus
115
+ }
116
+ #endif
117
+
118
+ #endif /* _SHA3_COMMON_H_ */
data/ext/sha3/cshake.c CHANGED
@@ -1,5 +1,6 @@
1
1
  #include "cshake.h"
2
2
 
3
+ #include "common.h"
3
4
  #include "sha3.h"
4
5
  #include "sp800_185.h"
5
6
 
@@ -42,10 +43,9 @@ static ID _cshake_256_id;
42
43
  static const rb_data_type_t sha3_cshake_data_type = {
43
44
  "SHA3::CSHAKE",
44
45
  {
45
- NULL,
46
- sha3_cshake_free_context, // Use our free function directly
47
- sha3_cshake_context_size, /* We'll do our own size calculation */
48
- NULL, /* dcompact field */
46
+ NULL, sha3_cshake_free_context, // Use our free function directly
47
+ sha3_cshake_context_size, /* We'll do our own size calculation */
48
+ NULL, /* dcompact field */
49
49
  },
50
50
  NULL,
51
51
  NULL,
@@ -77,7 +77,7 @@ void Init_sha3_cshake(void) {
77
77
  /*
78
78
  * Document-class: SHA3::CSHAKE::Error
79
79
  *
80
- * All KMAC methods raise this exception on error.
80
+ * All CSHAKE methods raise this exception on error.
81
81
  *
82
82
  * It is a subclass of the StandardError class -- see the Ruby documentation
83
83
  * for more information.
@@ -105,25 +105,11 @@ void Init_sha3_cshake(void) {
105
105
  return;
106
106
  }
107
107
 
108
- static void sha3_cshake_free_context(void *ptr) { sp800_185_free_context((sp800_185_context_t *)ptr); }
108
+ /* Use common memory management functions */
109
+ DEFINE_SP800_185_MEMORY_FUNCS(sha3_cshake, sha3_cshake_context_t)
109
110
 
110
- static size_t sha3_cshake_context_size(const void *ptr) {
111
- return sp800_185_context_size((const sp800_185_context_t *)ptr, sizeof(sha3_cshake_context_t));
112
- }
113
-
114
- static VALUE rb_sha3_cshake_alloc(VALUE klass) {
115
- sha3_cshake_context_t *context =
116
- (sha3_cshake_context_t *)sp800_185_alloc_context(sizeof(sha3_cshake_context_t), sizeof(cSHAKE_Instance));
117
-
118
- if (!context) {
119
- rb_raise(_sha3_cshake_error_class, "failed to allocate memory");
120
- }
121
-
122
- // Create the Ruby object with TypedData - this will automatically handle freeing
123
- VALUE obj = TypedData_Wrap_Struct(klass, &sha3_cshake_data_type, context);
124
-
125
- return obj;
126
- }
111
+ /* Use common allocation function */
112
+ DEFINE_SP800_185_ALLOC(sha3_cshake, sha3_cshake_context_t, cSHAKE_Instance, _sha3_cshake_error_class)
127
113
 
128
114
  /*
129
115
  * :call-seq:
@@ -145,14 +131,14 @@ static VALUE rb_sha3_cshake_alloc(VALUE klass) {
145
131
  * _optional_ The customization string to use
146
132
  *
147
133
  * = example
148
- * # Initialize instance for fix-ed-length operation
134
+ * # Initialize instance for fixed-length operation
149
135
  * cshake = SHA3::CSHAKE.new(:cshake_128, 32, name: 'my-app')
150
136
  * cshake << 'data...'
151
137
  * cshake.hexdigest
152
138
  *
153
139
  * # Initialize instance for XOF operation (arbitrary-long output)
154
140
  * cshake = SHA3::CSHAKE.new(:cshake_256, 0, customization: 'Email Signature')
155
- * cshask.update('data...')
141
+ * cshake.update('data...')
156
142
  * cshake.squeeze(64)
157
143
  */
158
144
  static VALUE rb_sha3_cshake_init(int argc, VALUE *argv, VALUE self) {
@@ -187,7 +173,7 @@ static VALUE rb_sha3_cshake_init(int argc, VALUE *argv, VALUE self) {
187
173
 
188
174
  VALUE customization = values[1] == Qundef ? rb_str_new2("") : values[1];
189
175
  StringValue(customization);
190
-
176
+
191
177
  sha3_cshake_context_t *context;
192
178
  TypedData_Get_Struct(self, sha3_cshake_context_t, &sha3_cshake_data_type, context);
193
179
 
@@ -196,18 +182,24 @@ static VALUE rb_sha3_cshake_init(int argc, VALUE *argv, VALUE self) {
196
182
  context->base.error_class = _sha3_cshake_error_class;
197
183
 
198
184
  // Find the appropriate function table based on the algorithm
185
+ sp800_185_algorithm_t alg_type;
199
186
  if (algorithm == ID2SYM(_cshake_128_id)) {
200
- context->base.functions = &sp800_185_functions[SP800_185_CSHAKE_128];
187
+ alg_type = SP800_185_CSHAKE_128;
201
188
  } else if (algorithm == ID2SYM(_cshake_256_id)) {
202
- context->base.functions = &sp800_185_functions[SP800_185_CSHAKE_256];
189
+ alg_type = SP800_185_CSHAKE_256;
203
190
  } else {
204
191
  rb_raise(rb_eArgError, "invalid algorithm: %s", rb_id2name(SYM2ID(algorithm)));
205
192
  }
206
193
 
207
- // Initialize the state using the function table
208
- int result = context->base.functions->cshake.init(
209
- context->base.state, context->base.output_length, (BitSequence *)RSTRING_PTR(name_str),
210
- RSTRING_LEN(name_str) * 8, (BitSequence *)RSTRING_PTR(customization), RSTRING_LEN(customization) * 8);
194
+ context->base.functions = sp800_185_get_algorithm(alg_type);
195
+ if (!context->base.functions) {
196
+ rb_raise(_sha3_cshake_error_class, "algorithm not available");
197
+ }
198
+
199
+ // Initialize using the safe accessor function
200
+ int result = sp800_185_init_cshake(context->base.functions, context->base.state, context->base.output_length,
201
+ (BitSequence *)RSTRING_PTR(name_str), RSTRING_LEN(name_str) * 8,
202
+ (BitSequence *)RSTRING_PTR(customization), RSTRING_LEN(customization) * 8);
211
203
 
212
204
  if (result != 0) {
213
205
  rb_raise(_sha3_cshake_error_class, "failed to initialize %s algorithm", context->base.functions->name);
@@ -228,31 +220,7 @@ static VALUE rb_sha3_cshake_init(int argc, VALUE *argv, VALUE self) {
228
220
  * = example
229
221
  * cshake2 = cshake.dup
230
222
  */
231
- static VALUE rb_sha3_cshake_copy(VALUE self, VALUE other) {
232
- sha3_cshake_context_t *context, *other_context;
233
-
234
- rb_check_frozen(self);
235
- if (self == other) {
236
- return self;
237
- }
238
-
239
- if (!rb_obj_is_kind_of(other, _sha3_cshake_class)) {
240
- rb_raise(rb_eTypeError, "wrong argument (%s)! (expected %s)", rb_obj_classname(other),
241
- rb_class2name(_sha3_cshake_class));
242
- }
243
-
244
- TypedData_Get_Struct(other, sha3_cshake_context_t, &sha3_cshake_data_type, other_context);
245
- TypedData_Get_Struct(self, sha3_cshake_context_t, &sha3_cshake_data_type, context);
246
-
247
- // Copy the base context attributes
248
- context->base.functions = other_context->base.functions;
249
- context->base.output_length = other_context->base.output_length;
250
-
251
- // Copy the algorithm-specific state
252
- memcpy(context->base.state, other_context->base.state, context->base.functions->state_size);
253
-
254
- return self;
255
- }
223
+ DEFINE_SP800_185_COPY_METHOD(rb_sha3_cshake_copy, sha3_cshake_context_t, sha3_cshake_data_type, _sha3_cshake_class)
256
224
 
257
225
  /*
258
226
  * :call-seq:
@@ -267,13 +235,7 @@ static VALUE rb_sha3_cshake_copy(VALUE self, VALUE other) {
267
235
  * cshake.update("more data")
268
236
  * cshake << "more data" # alias for update
269
237
  */
270
- static VALUE rb_sha3_cshake_update(VALUE self, VALUE data) {
271
- sp800_185_context_t *context;
272
- get_cshake_context(self, &context);
273
- sp800_185_update(context, data);
274
-
275
- return self;
276
- }
238
+ DEFINE_SP800_185_SIMPLE_METHOD(rb_sha3_cshake_update, sp800_185_rb_update, get_cshake_context)
277
239
 
278
240
  /*
279
241
  * :call-seq:
@@ -281,12 +243,7 @@ static VALUE rb_sha3_cshake_update(VALUE self, VALUE data) {
281
243
  *
282
244
  * Returns the name of the CSHAKE instance.
283
245
  */
284
- static VALUE rb_sha3_cshake_name(VALUE self) {
285
- sp800_185_context_t *context;
286
- get_cshake_context(self, &context);
287
-
288
- return rb_str_new2(sp800_185_name(context));
289
- }
246
+ DEFINE_SP800_185_RETURN_METHOD(rb_sha3_cshake_name, sp800_185_rb_name, get_cshake_context)
290
247
 
291
248
  /*
292
249
  * :call-seq:
@@ -300,13 +257,7 @@ static VALUE rb_sha3_cshake_name(VALUE self) {
300
257
  * = example
301
258
  * cshake.finish
302
259
  */
303
- static VALUE rb_sha3_cshake_finish(int argc, VALUE *argv, VALUE self) {
304
- sp800_185_context_t *context;
305
- get_cshake_context(self, &context);
306
-
307
- VALUE output = argc > 0 ? argv[0] : Qnil;
308
- return sp800_185_finish(context, output);
309
- }
260
+ DEFINE_SP800_185_VARARGS_METHOD(rb_sha3_cshake_finish, sp800_185_rb_finish, get_cshake_context)
310
261
 
311
262
  /*
312
263
  * :call-seq:
@@ -321,14 +272,7 @@ static VALUE rb_sha3_cshake_finish(int argc, VALUE *argv, VALUE self) {
321
272
  * cshake.digest
322
273
  * cshake.digest("final chunk")
323
274
  */
324
- static VALUE rb_sha3_cshake_digest(int argc, VALUE *argv, VALUE self) {
325
- sp800_185_context_t *context;
326
- get_cshake_context(self, &context);
327
-
328
- VALUE data = argc > 0 ? argv[0] : Qnil;
329
-
330
- return sp800_185_digest(context, data);
331
- }
275
+ DEFINE_SP800_185_VARARGS_METHOD(rb_sha3_cshake_digest, sp800_185_rb_digest, get_cshake_context)
332
276
 
333
277
  /*
334
278
  * :call-seq:
@@ -343,14 +287,7 @@ static VALUE rb_sha3_cshake_digest(int argc, VALUE *argv, VALUE self) {
343
287
  * cshake.hexdigest
344
288
  * cshake.hexdigest("final chunk")
345
289
  */
346
- static VALUE rb_sha3_cshake_hexdigest(int argc, VALUE *argv, VALUE self) {
347
- sp800_185_context_t *context;
348
- get_cshake_context(self, &context);
349
-
350
- VALUE data = argc > 0 ? argv[0] : Qnil;
351
-
352
- return sp800_185_hexdigest(context, data);
353
- }
290
+ DEFINE_SP800_185_VARARGS_METHOD(rb_sha3_cshake_hexdigest, sp800_185_rb_hexdigest, get_cshake_context)
354
291
 
355
292
  /*
356
293
  * :call-seq:
@@ -364,12 +301,7 @@ static VALUE rb_sha3_cshake_hexdigest(int argc, VALUE *argv, VALUE self) {
364
301
  * = example
365
302
  * cshake.squeeze(32)
366
303
  */
367
- static VALUE rb_sha3_cshake_squeeze(VALUE self, VALUE length) {
368
- sp800_185_context_t *context;
369
- get_cshake_context(self, &context);
370
-
371
- return sp800_185_squeeze(context, length);
372
- }
304
+ DEFINE_SP800_185_VALUE_METHOD(rb_sha3_cshake_squeeze, sp800_185_rb_squeeze, get_cshake_context)
373
305
 
374
306
  /*
375
307
  * :call-seq:
@@ -383,9 +315,4 @@ static VALUE rb_sha3_cshake_squeeze(VALUE self, VALUE length) {
383
315
  * = example
384
316
  * cshake.hex_squeeze(32)
385
317
  */
386
- static VALUE rb_sha3_cshake_hex_squeeze(VALUE self, VALUE length) {
387
- sp800_185_context_t *context;
388
- get_cshake_context(self, &context);
389
-
390
- return sp800_185_hex_squeeze(context, length);
391
- }
318
+ DEFINE_SP800_185_VALUE_METHOD(rb_sha3_cshake_hex_squeeze, sp800_185_rb_hex_squeeze, get_cshake_context)
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 _SHA3_CSHAKE_H
4
- #define _SHA3_CSHAKE_H
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 /* SHA3_CSHAKE_H */
17
+ #endif /* _SHA3_CSHAKE_H_ */