sha3 2.2.2 → 2.2.4
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/.document +1 -0
- data/.rubocop.yml +66 -0
- data/CHANGELOG.md +34 -0
- data/README.md +1 -0
- data/certs/io+sha3@jsg.io.pem +20 -20
- data/ext/sha3/common.h +118 -0
- data/ext/sha3/cshake.c +18 -95
- data/ext/sha3/digest.c +106 -79
- data/ext/sha3/kmac.c +18 -97
- data/ext/sha3/sp800_185.c +87 -47
- data/lib/constants.rb +1 -1
- data/sha3.gemspec +5 -5
- data.tar.gz.sig +0 -0
- metadata +24 -23
- metadata.gz.sig +0 -0
data/ext/sha3/sp800_185.c
CHANGED
|
@@ -22,38 +22,46 @@ static int kmac256_init_wrapper(void *state, void *params) {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/*** Function table for SP800-185 algorithms ***/
|
|
25
|
-
sp800_185_function_table_t sp800_185_functions[] = {{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
25
|
+
sp800_185_function_table_t sp800_185_functions[] = {{
|
|
26
|
+
.algorithm = SP800_185_CSHAKE_128,
|
|
27
|
+
.name = "CSHAKE128",
|
|
28
|
+
.state_size = sizeof(cSHAKE_Instance),
|
|
29
|
+
.is_keyed = false,
|
|
30
|
+
.init = cshake128_init_wrapper,
|
|
31
|
+
.update = (sp800_185_update_fn)cSHAKE128_Update,
|
|
32
|
+
.final = (sp800_185_final_fn)cSHAKE128_Final,
|
|
33
|
+
.squeeze = (sp800_185_squeeze_fn)cSHAKE128_Squeeze,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
.algorithm = SP800_185_CSHAKE_256,
|
|
37
|
+
.name = "CSHAKE256",
|
|
38
|
+
.state_size = sizeof(cSHAKE_Instance),
|
|
39
|
+
.is_keyed = false,
|
|
40
|
+
.init = cshake256_init_wrapper,
|
|
41
|
+
.update = (sp800_185_update_fn)cSHAKE256_Update,
|
|
42
|
+
.final = (sp800_185_final_fn)cSHAKE256_Final,
|
|
43
|
+
.squeeze = (sp800_185_squeeze_fn)cSHAKE256_Squeeze,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
.algorithm = SP800_185_KMAC_128,
|
|
47
|
+
.name = "KMAC128",
|
|
48
|
+
.state_size = sizeof(KMAC_Instance),
|
|
49
|
+
.is_keyed = true,
|
|
50
|
+
.init = kmac128_init_wrapper,
|
|
51
|
+
.update = (sp800_185_update_fn)KMAC128_Update,
|
|
52
|
+
.final = (sp800_185_final_fn)KMAC128_Final,
|
|
53
|
+
.squeeze = (sp800_185_squeeze_fn)KMAC128_Squeeze,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
.algorithm = SP800_185_KMAC_256,
|
|
57
|
+
.name = "KMAC256",
|
|
58
|
+
.state_size = sizeof(KMAC_Instance),
|
|
59
|
+
.is_keyed = true,
|
|
60
|
+
.init = kmac256_init_wrapper,
|
|
61
|
+
.update = (sp800_185_update_fn)KMAC256_Update,
|
|
62
|
+
.final = (sp800_185_final_fn)KMAC256_Final,
|
|
63
|
+
.squeeze = (sp800_185_squeeze_fn)KMAC256_Squeeze,
|
|
64
|
+
}};
|
|
57
65
|
|
|
58
66
|
/* Algorithm lookup functions */
|
|
59
67
|
const sp800_185_function_table_t *sp800_185_get_algorithm(sp800_185_algorithm_t algorithm) {
|
|
@@ -74,12 +82,12 @@ const sp800_185_function_table_t *sp800_185_get_algorithm_by_name(const char *na
|
|
|
74
82
|
|
|
75
83
|
// Generic context allocation function
|
|
76
84
|
sp800_185_context_t *sp800_185_alloc_context(size_t context_size, size_t state_size) {
|
|
77
|
-
sp800_185_context_t *context = (sp800_185_context_t *)
|
|
85
|
+
sp800_185_context_t *context = (sp800_185_context_t *)ruby_xmalloc(context_size);
|
|
78
86
|
if (!context) return NULL;
|
|
79
87
|
|
|
80
|
-
context->state =
|
|
88
|
+
context->state = ruby_xcalloc(1, state_size);
|
|
81
89
|
if (!context->state) {
|
|
82
|
-
|
|
90
|
+
ruby_xfree(context);
|
|
83
91
|
return NULL;
|
|
84
92
|
}
|
|
85
93
|
|
|
@@ -92,9 +100,9 @@ sp800_185_context_t *sp800_185_alloc_context(size_t context_size, size_t state_s
|
|
|
92
100
|
void sp800_185_free_context(sp800_185_context_t *context) {
|
|
93
101
|
if (context) {
|
|
94
102
|
if (context->state) {
|
|
95
|
-
|
|
103
|
+
ruby_xfree(context->state);
|
|
96
104
|
}
|
|
97
|
-
|
|
105
|
+
ruby_xfree(context);
|
|
98
106
|
}
|
|
99
107
|
}
|
|
100
108
|
|
|
@@ -112,7 +120,7 @@ void *sp800_185_copy_state(sp800_185_context_t *context) {
|
|
|
112
120
|
if (context->functions->state_size <= 0) {
|
|
113
121
|
rb_raise(context->error_class, "invalid state size");
|
|
114
122
|
}
|
|
115
|
-
void *state_copy =
|
|
123
|
+
void *state_copy = ruby_xmalloc(context->functions->state_size);
|
|
116
124
|
|
|
117
125
|
if (!state_copy) {
|
|
118
126
|
rb_raise(rb_eNoMemError, "failed to allocate memory for state copy");
|
|
@@ -125,6 +133,12 @@ void *sp800_185_copy_state(sp800_185_context_t *context) {
|
|
|
125
133
|
|
|
126
134
|
VALUE sp800_185_update(sp800_185_context_t *context, VALUE data) {
|
|
127
135
|
StringValue(data);
|
|
136
|
+
|
|
137
|
+
// Check for NULL data pointer
|
|
138
|
+
if (RSTRING_PTR(data) == NULL && RSTRING_LEN(data) > 0) {
|
|
139
|
+
rb_raise(context->error_class, "cannot update with NULL data");
|
|
140
|
+
}
|
|
141
|
+
|
|
128
142
|
size_t data_len = (RSTRING_LEN(data) * 8);
|
|
129
143
|
|
|
130
144
|
if (data_len == 0) {
|
|
@@ -172,7 +186,7 @@ VALUE sp800_185_digest(sp800_185_context_t *context, VALUE data) {
|
|
|
172
186
|
}
|
|
173
187
|
|
|
174
188
|
// Create a copy of the state for processing
|
|
175
|
-
void *state_copy =
|
|
189
|
+
void *state_copy = ruby_xmalloc(context->functions->state_size);
|
|
176
190
|
if (!state_copy) {
|
|
177
191
|
rb_raise(rb_eNoMemError, "failed to allocate memory for state copy");
|
|
178
192
|
}
|
|
@@ -190,7 +204,7 @@ VALUE sp800_185_digest(sp800_185_context_t *context, VALUE data) {
|
|
|
190
204
|
result = context->functions->update(state_copy, (const BitSequence *)RSTRING_PTR(data), data_len);
|
|
191
205
|
|
|
192
206
|
if (result != 0) {
|
|
193
|
-
|
|
207
|
+
ruby_xfree(state_copy);
|
|
194
208
|
rb_raise(context->error_class, "failed to update %s state", context->functions->name);
|
|
195
209
|
}
|
|
196
210
|
}
|
|
@@ -201,7 +215,7 @@ VALUE sp800_185_digest(sp800_185_context_t *context, VALUE data) {
|
|
|
201
215
|
|
|
202
216
|
result = context->functions->final(state_copy, (BitSequence *)RSTRING_PTR(output));
|
|
203
217
|
|
|
204
|
-
|
|
218
|
+
ruby_xfree(state_copy);
|
|
205
219
|
|
|
206
220
|
if (result != 0) {
|
|
207
221
|
rb_raise(context->error_class, "failed to finalize %s state", context->functions->name);
|
|
@@ -220,18 +234,23 @@ VALUE sp800_185_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
|
220
234
|
rb_raise(context->error_class, "use digest methods for fixed-length output");
|
|
221
235
|
}
|
|
222
236
|
|
|
223
|
-
|
|
237
|
+
long output_byte_len;
|
|
224
238
|
VALUE str;
|
|
225
239
|
|
|
226
240
|
Check_Type(length, T_FIXNUM);
|
|
227
|
-
output_byte_len =
|
|
241
|
+
output_byte_len = NUM2LONG(length);
|
|
228
242
|
|
|
229
243
|
if (output_byte_len <= 0) {
|
|
230
|
-
rb_raise(context->error_class, "output length must be
|
|
244
|
+
rb_raise(context->error_class, "output length must be positive");
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Limit output to 1MB for safety
|
|
248
|
+
if (output_byte_len > (1L << 20)) {
|
|
249
|
+
rb_raise(context->error_class, "output length too large (max 1MB)");
|
|
231
250
|
}
|
|
232
251
|
|
|
233
252
|
// Create a copy of the state for processing
|
|
234
|
-
void *state_copy =
|
|
253
|
+
void *state_copy = ruby_xmalloc(context->functions->state_size);
|
|
235
254
|
if (!state_copy) {
|
|
236
255
|
rb_raise(rb_eNoMemError, "failed to allocate memory for state copy");
|
|
237
256
|
}
|
|
@@ -245,7 +264,7 @@ VALUE sp800_185_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
|
245
264
|
result = context->functions->final(state_copy, (BitSequence *)RSTRING_PTR(dummy_output));
|
|
246
265
|
|
|
247
266
|
if (result != 0) {
|
|
248
|
-
|
|
267
|
+
ruby_xfree(state_copy);
|
|
249
268
|
rb_raise(context->error_class, "failed to finalize %s state", context->functions->name);
|
|
250
269
|
}
|
|
251
270
|
|
|
@@ -255,7 +274,7 @@ VALUE sp800_185_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
|
255
274
|
// Use the function table to call the appropriate squeeze function
|
|
256
275
|
result = context->functions->squeeze(state_copy, (BitSequence *)RSTRING_PTR(str), output_byte_len * 8);
|
|
257
276
|
|
|
258
|
-
|
|
277
|
+
ruby_xfree(state_copy);
|
|
259
278
|
|
|
260
279
|
if (result != 0) {
|
|
261
280
|
rb_raise(context->error_class, "failed to squeeze %s", context->functions->name);
|
|
@@ -268,3 +287,24 @@ VALUE sp800_185_hex_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
|
268
287
|
VALUE binary_result = sp800_185_squeeze(context, length);
|
|
269
288
|
return rb_funcall(binary_result, rb_intern("unpack1"), 1, rb_str_new2("H*"));
|
|
270
289
|
}
|
|
290
|
+
|
|
291
|
+
/* Ruby wrapper functions for common method patterns */
|
|
292
|
+
|
|
293
|
+
VALUE sp800_185_rb_update(sp800_185_context_t *context, VALUE data) {
|
|
294
|
+
sp800_185_update(context, data);
|
|
295
|
+
return Qnil; // Caller will return self
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
VALUE sp800_185_rb_name(sp800_185_context_t *context) { return rb_str_new2(sp800_185_name(context)); }
|
|
299
|
+
|
|
300
|
+
VALUE sp800_185_rb_finish(sp800_185_context_t *context, VALUE output) { return sp800_185_finish(context, output); }
|
|
301
|
+
|
|
302
|
+
VALUE sp800_185_rb_digest(sp800_185_context_t *context, VALUE data) { return sp800_185_digest(context, data); }
|
|
303
|
+
|
|
304
|
+
VALUE sp800_185_rb_hexdigest(sp800_185_context_t *context, VALUE data) { return sp800_185_hexdigest(context, data); }
|
|
305
|
+
|
|
306
|
+
VALUE sp800_185_rb_squeeze(sp800_185_context_t *context, VALUE length) { return sp800_185_squeeze(context, length); }
|
|
307
|
+
|
|
308
|
+
VALUE sp800_185_rb_hex_squeeze(sp800_185_context_t *context, VALUE length) {
|
|
309
|
+
return sp800_185_hex_squeeze(context, length);
|
|
310
|
+
}
|
data/lib/constants.rb
CHANGED
data/sha3.gemspec
CHANGED
|
@@ -9,26 +9,26 @@ 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'
|
|
20
20
|
spec.license = 'MIT'
|
|
21
21
|
spec.required_ruby_version = '>= 2.7.0'
|
|
22
22
|
|
|
23
|
-
spec.metadata['changelog_uri'] = "#{spec.homepage}/CHANGELOG.md"
|
|
23
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
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.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Johanns Gregorian
|
|
@@ -11,28 +11,28 @@ cert_chain:
|
|
|
11
11
|
-----BEGIN CERTIFICATE-----
|
|
12
12
|
MIIEYDCCAsigAwIBAgIBATANBgkqhkiG9w0BAQsFADA7MRAwDgYDVQQDDAdpb19z
|
|
13
13
|
aGEzMRMwEQYKCZImiZPyLGQBGRYDanNnMRIwEAYKCZImiZPyLGQBGRYCaW8wHhcN
|
|
14
|
-
|
|
14
|
+
MjYwNTE3MjAwNTE1WhcNMjgwNTE2MjAwNTE1WjA7MRAwDgYDVQQDDAdpb19zaGEz
|
|
15
15
|
MRMwEQYKCZImiZPyLGQBGRYDanNnMRIwEAYKCZImiZPyLGQBGRYCaW8wggGiMA0G
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC16QqqWL49C7rqtj8HoYMippjH6T4A
|
|
17
|
+
MvK8w1nXPsGOhIP0BYcjNajdFxzOXZ9NcYPxosQAvY97THO7zEGsM2VrvPzsPL8J
|
|
18
|
+
8DqRS6wHUezA2ZffGpUvsesNlIpzSkEXXXRTe/8dq2/TnIeKEyx4dhu1cKL6h/22
|
|
19
|
+
Mng14M25QJK0JI5xhQ/+i9UXeNCwFjwINbOzJD1XZ2VtOJkMm/yHZvB6ww8qu+gS
|
|
20
|
+
N4J2iiCbFRsbYRPuoVFVuSOD0lgX1tvwOtUucSdF1EzvEX5XW2avzOWsKab0V3ET
|
|
21
|
+
puZ9F36dmkfNan5n5GApyKkOZ/mfC8s9brjRXVlp4YPHBK3zFEU6VsCtIa08dPXI
|
|
22
|
+
axUZlmwQLhvtsnX3nkgvbGpvFZmhBs4JBssEur7Gf9bgLbXYngfmgIZv5WFRravJ
|
|
23
|
+
qvHCehkpVgqi+ebW15UzhPwQ5wNxdm/I+tAt/u08m0R4m6kQYbk2yAimjrVLx0f/
|
|
24
|
+
JPcoi+4QXrmYZujkhqhIw2lDPOCD2oKPUVECAwEAAaNvMG0wCQYDVR0TBAIwADAL
|
|
25
|
+
BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFKuRt91muWm/9XZBRDt8Nkm1IdjdMBkGA1Ud
|
|
26
26
|
EQQSMBCBDmlvK3NoYTNAanNnLmlvMBkGA1UdEgQSMBCBDmlvK3NoYTNAanNnLmlv
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
+
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
MA0GCSqGSIb3DQEBCwUAA4IBgQBI38LgcqdqpfkaiEGfr3fLtsOBkE1Q7mEHjeIS
|
|
28
|
+
JcEiu16sP0iR/0QzN/DS0vPMQUhl4dvkUl7euVOo8rp0mwzUyaSvq+MSQlpxwgjb
|
|
29
|
+
AQ5A8VAkkIMbTbCqRU9q9KQObmO8/NaFFFGgmRegp8eBEGdixbiIsReEeWzEICe1
|
|
30
|
+
TOmXWl1X7EBUF7CdSIHxBAjF16YXJoDJp16DonZ/pzbgeO85OzFmfnA+B9nsHXS4
|
|
31
|
+
3CeJ/lKznIM8XWSXA1ruSkZeB5ouNtauqSAaBJoMkAB0DbOrZ6yo/mP8x3WtSLKY
|
|
32
|
+
SdQdy412nPewWa08VXIjZqd1Q+rI9Wq2pY6TOqML1Iu5nB2VMAr9PoHcIPz1P9N8
|
|
33
|
+
sM8XX4fXOsMtSc4SzMOqlkg2qRdo4/1eIjVSxCM84VqppRnH8syAzny6COQ0Xo+z
|
|
34
|
+
/PqqO8TUsynEGVsjIkBIa8Y5zoXBfcQ6PQpSbeY0bXhhsxclL3fKWSQQC4MN/OFE
|
|
35
|
+
5aeBE+xHYdmI3UoIAXt1xB0hU9w=
|
|
36
36
|
-----END CERTIFICATE-----
|
|
37
37
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
38
38
|
dependencies: []
|
|
@@ -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
|
|
@@ -108,7 +109,7 @@ homepage: https://github.com/johanns/sha3
|
|
|
108
109
|
licenses:
|
|
109
110
|
- MIT
|
|
110
111
|
metadata:
|
|
111
|
-
changelog_uri: https://github.com/johanns/sha3/CHANGELOG.md
|
|
112
|
+
changelog_uri: https://github.com/johanns/sha3/blob/main/CHANGELOG.md
|
|
112
113
|
homepage_uri: https://github.com/johanns/sha3
|
|
113
114
|
documentation_uri: https://docs.jsg.io/sha3/index.html
|
|
114
115
|
rubygems_mfa_required: 'true'
|
|
@@ -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:
|
|
134
|
+
rubygems_version: 4.0.11
|
|
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
|
Binary file
|