sha3 2.0.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 +5 -52
- data/.document +1 -2
- data/.rdoc_options +1 -0
- data/.rubocop.yml +3 -0
- data/.vscode/launch.json +15 -0
- data/.vscode/settings.json +9 -0
- data/.vscode/tasks.json +29 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +1 -0
- data/README.md +116 -33
- data/Rakefile +4 -2
- data/doc/sha3.rb +2 -0
- data/ext/sha3/config.h +2 -2
- data/ext/sha3/cshake.c +391 -0
- data/ext/sha3/cshake.h +17 -0
- data/ext/sha3/digest.c +320 -231
- data/ext/sha3/digest.h +3 -71
- data/ext/sha3/extconf.rb +14 -8
- data/ext/sha3/kmac.c +474 -0
- data/ext/sha3/kmac.h +14 -0
- data/ext/sha3/sha3.c +35 -0
- data/ext/sha3/sha3.h +17 -0
- data/ext/sha3/sp800_185.c +311 -0
- data/ext/sha3/sp800_185.h +94 -0
- data/lib/constants.rb +5 -0
- data/lib/sha3.rb +28 -24
- data.tar.gz.sig +0 -0
- metadata +22 -21
- metadata.gz.sig +0 -0
data/ext/sha3/digest.h
CHANGED
@@ -1,81 +1,13 @@
|
|
1
1
|
// Copyright (c) 2012 - 2025 Johanns Gregorian <io+sha3@jsg.io>
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
5
|
-
|
6
|
-
#include <ruby.h>
|
7
|
-
#include <ruby/encoding.h>
|
8
|
-
#include <string.h>
|
9
|
-
|
10
|
-
#include "KeccakHash.h"
|
3
|
+
#ifndef _SHA3_DIGEST_H_
|
4
|
+
#define _SHA3_DIGEST_H_
|
11
5
|
|
12
6
|
#ifdef __cplusplus
|
13
7
|
extern "C" {
|
14
8
|
#endif
|
15
9
|
|
16
|
-
|
17
|
-
|
18
|
-
typedef HashReturn (*keccak_init_func)(Keccak_HashInstance*);
|
19
|
-
|
20
|
-
typedef struct {
|
21
|
-
Keccak_HashInstance* state;
|
22
|
-
int hashbitlen;
|
23
|
-
algorithm_type algorithm;
|
24
|
-
} MDX;
|
25
|
-
|
26
|
-
VALUE sha3_module;
|
27
|
-
VALUE digest_class;
|
28
|
-
VALUE digest_error_class;
|
29
|
-
|
30
|
-
/* Static IDs for faster symbol lookup */
|
31
|
-
static ID sha3_224_id;
|
32
|
-
static ID sha3_256_id;
|
33
|
-
static ID sha3_384_id;
|
34
|
-
static ID sha3_512_id;
|
35
|
-
static ID shake_128_id;
|
36
|
-
static ID shake_256_id;
|
37
|
-
|
38
|
-
// TypedData functions
|
39
|
-
extern const rb_data_type_t mdx_type;
|
40
|
-
|
41
|
-
// Static inline functions replacing macros
|
42
|
-
static inline void get_mdx(VALUE obj, MDX** mdx) {
|
43
|
-
TypedData_Get_Struct((obj), MDX, &mdx_type, (*mdx));
|
44
|
-
if (!(*mdx)) {
|
45
|
-
rb_raise(rb_eRuntimeError, "Digest data not initialized!");
|
46
|
-
}
|
47
|
-
}
|
48
|
-
|
49
|
-
static inline void safe_get_mdx(VALUE obj, MDX** mdx) {
|
50
|
-
if (!rb_obj_is_kind_of(obj, digest_class)) {
|
51
|
-
rb_raise(rb_eTypeError, "wrong argument (%s)! (expected %s)", rb_obj_classname(obj),
|
52
|
-
rb_class2name(digest_class));
|
53
|
-
}
|
54
|
-
get_mdx(obj, mdx);
|
55
|
-
}
|
56
|
-
|
57
|
-
/* Allocation and initialization */
|
58
|
-
static VALUE rb_digest_alloc(VALUE);
|
59
|
-
static VALUE rb_digest_init(int, VALUE*, VALUE);
|
60
|
-
|
61
|
-
/* Core digest operations */
|
62
|
-
static VALUE rb_digest_copy(VALUE, VALUE);
|
63
|
-
static VALUE rb_digest_finish(int, VALUE*, VALUE);
|
64
|
-
static VALUE rb_digest_reset(VALUE);
|
65
|
-
static VALUE rb_digest_update(VALUE, VALUE);
|
66
|
-
|
67
|
-
/* Digest properties */
|
68
|
-
static VALUE rb_digest_block_length(VALUE);
|
69
|
-
static VALUE rb_digest_length(VALUE);
|
70
|
-
static VALUE rb_digest_name(VALUE);
|
71
|
-
|
72
|
-
/* Output methods */
|
73
|
-
static VALUE rb_digest_digest(int, VALUE*, VALUE);
|
74
|
-
static VALUE rb_digest_hexdigest(int, VALUE*, VALUE);
|
75
|
-
static VALUE rb_digest_hex_squeeze(VALUE, VALUE);
|
76
|
-
static VALUE rb_digest_squeeze(VALUE, VALUE);
|
77
|
-
static VALUE rb_digest_self_digest(VALUE, VALUE, VALUE);
|
78
|
-
static VALUE rb_digest_self_hexdigest(VALUE, VALUE, VALUE);
|
10
|
+
extern void Init_sha3_digest(void);
|
79
11
|
|
80
12
|
#ifdef __cplusplus
|
81
13
|
}
|
data/ext/sha3/extconf.rb
CHANGED
@@ -4,7 +4,7 @@ require 'mkmf'
|
|
4
4
|
require 'rbconfig'
|
5
5
|
|
6
6
|
b64 = 8.size == 8
|
7
|
-
extension_name = '
|
7
|
+
extension_name = 'sha3_ext'
|
8
8
|
ref_dir = b64 ? 'ref-64bits' : 'ref-32bits'
|
9
9
|
|
10
10
|
dir_config(extension_name)
|
@@ -12,6 +12,9 @@ dir_config(extension_name)
|
|
12
12
|
# Set compiler flags
|
13
13
|
$CFLAGS << ' -fomit-frame-pointer -O3 -g0 -fms-extensions'
|
14
14
|
|
15
|
+
# Add vectorization flags for better performance on supported platforms
|
16
|
+
$CFLAGS << ' -ftree-vectorize' if RUBY_PLATFORM =~ /x86_64|amd64|arm64/
|
17
|
+
|
15
18
|
# Add architecture-specific optimizations if enabled
|
16
19
|
$CFLAGS << ' -march=native' if enable_config('march-tune-native', false)
|
17
20
|
|
@@ -21,9 +24,6 @@ $CFLAGS << ' -D_FORTIFY_SOURCE=2 -fstack-protector-strong'
|
|
21
24
|
# Add warning flags to catch potential issues
|
22
25
|
$CFLAGS << ' -Wall -Wextra -Wformat -Wformat-security'
|
23
26
|
|
24
|
-
# Add vectorization flags for better performance on supported platforms
|
25
|
-
$CFLAGS << ' -ftree-vectorize' if RUBY_PLATFORM =~ /x86_64|amd64|arm64/
|
26
|
-
|
27
27
|
# Find all relevant subdirectories and filter appropriately
|
28
28
|
vpath_dirs = Dir.glob("#{$srcdir}/lib/**/*")
|
29
29
|
.select { |path| File.directory?(path) }
|
@@ -40,10 +40,16 @@ $VPATH << vpath_dirs_processed
|
|
40
40
|
# Add include flags
|
41
41
|
$INCFLAGS << vpath_dirs_processed
|
42
42
|
.map { |dir| " -I$(srcdir)#{dir}" }
|
43
|
-
.join
|
44
|
-
|
45
|
-
#
|
46
|
-
$srcs = [
|
43
|
+
.join
|
44
|
+
|
45
|
+
# Define source files
|
46
|
+
$srcs = %w[
|
47
|
+
cshake.c
|
48
|
+
digest.c
|
49
|
+
kmac.c
|
50
|
+
sha3.c
|
51
|
+
sp800_185.c
|
52
|
+
]
|
47
53
|
|
48
54
|
# Find and add all .c files from the filtered directories
|
49
55
|
$srcs += vpath_dirs
|
data/ext/sha3/kmac.c
ADDED
@@ -0,0 +1,474 @@
|
|
1
|
+
#include "kmac.h"
|
2
|
+
|
3
|
+
#include "sha3.h"
|
4
|
+
#include "sp800_185.h"
|
5
|
+
|
6
|
+
/*** Types and structs ***/
|
7
|
+
typedef struct {
|
8
|
+
sp800_185_context_t base;
|
9
|
+
} sha3_kmac_context_t;
|
10
|
+
|
11
|
+
/*** Function prototypes ***/
|
12
|
+
static void sha3_kmac_free_context(void *);
|
13
|
+
static size_t sha3_kmac_context_size(const void *);
|
14
|
+
|
15
|
+
/* Allocation and initialization */
|
16
|
+
static VALUE rb_sha3_kmac_alloc(VALUE);
|
17
|
+
static VALUE rb_sha3_kmac_init(int, VALUE *, VALUE);
|
18
|
+
static VALUE rb_sha3_kmac_copy(VALUE, VALUE);
|
19
|
+
|
20
|
+
/* Core digest operations */
|
21
|
+
static VALUE rb_sha3_kmac_finish(int, VALUE *, VALUE);
|
22
|
+
static VALUE rb_sha3_kmac_update(VALUE, VALUE);
|
23
|
+
|
24
|
+
/* Digest properties */
|
25
|
+
static VALUE rb_sha3_kmac_name(VALUE);
|
26
|
+
|
27
|
+
/* Output methods */
|
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);
|
32
|
+
|
33
|
+
static VALUE rb_sha3_kmac_squeeze(VALUE, VALUE);
|
34
|
+
static VALUE rb_sha3_kmac_hex_squeeze(VALUE, VALUE);
|
35
|
+
|
36
|
+
/*** Global variables ***/
|
37
|
+
VALUE _sha3_kmac_class;
|
38
|
+
VALUE _sha3_kmac_error_class;
|
39
|
+
|
40
|
+
/* Define the ID variables */
|
41
|
+
static ID _kmac_128_id;
|
42
|
+
static ID _kmac_256_id;
|
43
|
+
|
44
|
+
/* TypedData structure for sha3_kmac_context_t */
|
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
|
+
}
|
61
|
+
|
62
|
+
void Init_sha3_kmac(void) {
|
63
|
+
_kmac_128_id = rb_intern("kmac_128");
|
64
|
+
_kmac_256_id = rb_intern("kmac_256");
|
65
|
+
|
66
|
+
if (!_sha3_module) {
|
67
|
+
_sha3_module = rb_define_module("SHA3");
|
68
|
+
}
|
69
|
+
|
70
|
+
/*
|
71
|
+
* Document-class: SHA3::KMAC
|
72
|
+
*
|
73
|
+
* It is a subclass of the Digest::Class class, which provides a framework for
|
74
|
+
* creating and manipulating hash digests.
|
75
|
+
*/
|
76
|
+
_sha3_kmac_class = rb_define_class_under(_sha3_module, "KMAC", rb_cObject);
|
77
|
+
|
78
|
+
/*
|
79
|
+
* Document-class: SHA3::KMAC::KMACError
|
80
|
+
*
|
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
|
+
*/
|
86
|
+
_sha3_kmac_error_class = rb_define_class_under(_sha3_kmac_class, "Error", rb_eStandardError);
|
87
|
+
|
88
|
+
rb_define_alloc_func(_sha3_kmac_class, rb_sha3_kmac_alloc);
|
89
|
+
rb_define_method(_sha3_kmac_class, "initialize", rb_sha3_kmac_init, -1);
|
90
|
+
rb_define_method(_sha3_kmac_class, "initialize_copy", rb_sha3_kmac_copy, 1);
|
91
|
+
rb_define_method(_sha3_kmac_class, "update", rb_sha3_kmac_update, 1);
|
92
|
+
rb_define_method(_sha3_kmac_class, "name", rb_sha3_kmac_name, 0);
|
93
|
+
|
94
|
+
rb_define_method(_sha3_kmac_class, "digest", rb_sha3_kmac_digest, -1);
|
95
|
+
rb_define_method(_sha3_kmac_class, "hexdigest", rb_sha3_kmac_hexdigest, -1);
|
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
|
+
|
100
|
+
rb_define_private_method(_sha3_kmac_class, "finish", rb_sha3_kmac_finish, -1);
|
101
|
+
|
102
|
+
rb_define_alias(_sha3_kmac_class, "<<", "update");
|
103
|
+
|
104
|
+
rb_define_singleton_method(_sha3_kmac_class, "digest", rb_sha3_kmac_self_digest, -1);
|
105
|
+
rb_define_singleton_method(_sha3_kmac_class, "hexdigest", rb_sha3_kmac_self_hexdigest, -1);
|
106
|
+
|
107
|
+
return;
|
108
|
+
}
|
109
|
+
|
110
|
+
static void sha3_kmac_free_context(void *ptr) { sp800_185_free_context((sp800_185_context_t *)ptr); }
|
111
|
+
|
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));
|
114
|
+
}
|
115
|
+
|
116
|
+
static VALUE rb_sha3_kmac_alloc(VALUE klass) {
|
117
|
+
sha3_kmac_context_t *context =
|
118
|
+
(sha3_kmac_context_t *)sp800_185_alloc_context(sizeof(sha3_kmac_context_t), sizeof(KMAC_Instance));
|
119
|
+
|
120
|
+
if (!context) {
|
121
|
+
rb_raise(_sha3_kmac_error_class, "failed to allocate memory");
|
122
|
+
}
|
123
|
+
|
124
|
+
// Create the Ruby object with TypedData - this will automatically handle freeing
|
125
|
+
VALUE obj = TypedData_Wrap_Struct(klass, &sha3_kmac_data_type_t, context);
|
126
|
+
|
127
|
+
return obj;
|
128
|
+
}
|
129
|
+
|
130
|
+
/*
|
131
|
+
* :call-seq:
|
132
|
+
* ::new(algorithm, output_length, key, [customization]) -> instance
|
133
|
+
*
|
134
|
+
* Creates a new KMAC object.
|
135
|
+
*
|
136
|
+
* +algorithm+::
|
137
|
+
* The KMAC algorithm to use (as a Symbol).
|
138
|
+
* Valid algorithms are:
|
139
|
+
* - :kmac_128
|
140
|
+
* - :kmac_256
|
141
|
+
*
|
142
|
+
* +output_length+::
|
143
|
+
* The length of the output in bytes. Set to 0 for an arbitrarily-long output using "squeeze" (XOF) methods.
|
144
|
+
*
|
145
|
+
* +key+::
|
146
|
+
* The key to use for the KMAC.
|
147
|
+
*
|
148
|
+
* +customization+::
|
149
|
+
* _optional_ The customization string to use.
|
150
|
+
*
|
151
|
+
* = example
|
152
|
+
* SHA3::KMAC.new(:kmac_128, 32, "key")
|
153
|
+
* SHA3::KMAC.new(:kmac_256, 64, "key", "customization")
|
154
|
+
* SHA3::KMAC.new(:kmac_128, 0, "key", "customization")
|
155
|
+
*
|
156
|
+
*/
|
157
|
+
static VALUE rb_sha3_kmac_init(int argc, VALUE *argv, VALUE self) {
|
158
|
+
VALUE algorithm, output_length, key, customization;
|
159
|
+
|
160
|
+
rb_scan_args(argc, argv, "31", &algorithm, &output_length, &key, &customization);
|
161
|
+
|
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);
|
177
|
+
|
178
|
+
if (!NIL_P(customization)) {
|
179
|
+
StringValue(customization);
|
180
|
+
} else {
|
181
|
+
customization = rb_str_new2("");
|
182
|
+
}
|
183
|
+
|
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));
|
199
|
+
}
|
200
|
+
|
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);
|
211
|
+
}
|
212
|
+
|
213
|
+
return self;
|
214
|
+
}
|
215
|
+
|
216
|
+
/*
|
217
|
+
* :call-seq:
|
218
|
+
* ::copy(other) -> kmac
|
219
|
+
*
|
220
|
+
* Creates a copy of the KMAC instance.
|
221
|
+
*
|
222
|
+
* +other+::
|
223
|
+
* The KMAC to copy the state from.
|
224
|
+
*
|
225
|
+
* = example
|
226
|
+
* new_kmac = kmac.dup
|
227
|
+
*/
|
228
|
+
static VALUE rb_sha3_kmac_copy(VALUE self, VALUE other) {
|
229
|
+
sha3_kmac_context_t *context, *other_context;
|
230
|
+
|
231
|
+
rb_check_frozen(self);
|
232
|
+
if (self == other) {
|
233
|
+
return self;
|
234
|
+
}
|
235
|
+
|
236
|
+
if (!rb_obj_is_kind_of(other, _sha3_kmac_class)) {
|
237
|
+
rb_raise(rb_eTypeError, "wrong argument (%s)! (expected %s)", rb_obj_classname(other),
|
238
|
+
rb_class2name(_sha3_kmac_class));
|
239
|
+
}
|
240
|
+
|
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);
|
243
|
+
|
244
|
+
// Copy the base context attributes
|
245
|
+
context->base.functions = other_context->base.functions;
|
246
|
+
context->base.output_length = other_context->base.output_length;
|
247
|
+
|
248
|
+
// Copy the algorithm-specific state
|
249
|
+
memcpy(context->base.state, other_context->base.state, context->base.functions->state_size);
|
250
|
+
|
251
|
+
return self;
|
252
|
+
}
|
253
|
+
|
254
|
+
/*
|
255
|
+
* :call-seq:
|
256
|
+
* update(string) -> kmac
|
257
|
+
*
|
258
|
+
* Updates the KMAC with the given string.
|
259
|
+
*
|
260
|
+
* +string+::
|
261
|
+
* The string to update the KMAC with.
|
262
|
+
*
|
263
|
+
* = example
|
264
|
+
* kmac.update("more data")
|
265
|
+
* kmac << "more data" # alias for update
|
266
|
+
*/
|
267
|
+
static VALUE rb_sha3_kmac_update(VALUE self, VALUE data) {
|
268
|
+
sp800_185_context_t *context;
|
269
|
+
get_kmac_context(self, &context);
|
270
|
+
sp800_185_update(context, data);
|
271
|
+
|
272
|
+
return self;
|
273
|
+
}
|
274
|
+
|
275
|
+
/*
|
276
|
+
* :call-seq:
|
277
|
+
* name -> String
|
278
|
+
*
|
279
|
+
* Returns the name of the algorithm.
|
280
|
+
*
|
281
|
+
* = example
|
282
|
+
* kmac.name #=> "KMAC128" or "KMAC256"
|
283
|
+
*/
|
284
|
+
static VALUE rb_sha3_kmac_name(VALUE self) {
|
285
|
+
sp800_185_context_t *context;
|
286
|
+
get_kmac_context(self, &context);
|
287
|
+
|
288
|
+
return rb_str_new2(sp800_185_name(context));
|
289
|
+
}
|
290
|
+
|
291
|
+
/*
|
292
|
+
* :call-seq:
|
293
|
+
* finish([message]) -> String
|
294
|
+
*
|
295
|
+
* Returns the final KMAC as a binary string.
|
296
|
+
*
|
297
|
+
* +message+::
|
298
|
+
* _optional_ Output buffer to receive the final KMAC value.
|
299
|
+
*
|
300
|
+
* = example
|
301
|
+
* kmac.finish
|
302
|
+
*/
|
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);
|
306
|
+
|
307
|
+
VALUE output = argc > 0 ? argv[0] : Qnil;
|
308
|
+
|
309
|
+
return sp800_185_finish(context, output);
|
310
|
+
}
|
311
|
+
|
312
|
+
/*
|
313
|
+
* :call-seq:
|
314
|
+
* digest() -> string
|
315
|
+
* digest([data]) -> string
|
316
|
+
*
|
317
|
+
* Returns the binary representation of the KMAC.
|
318
|
+
* This method creates a copy of the current instance so that
|
319
|
+
* the original state is preserved for future updates.
|
320
|
+
*
|
321
|
+
* +data+::
|
322
|
+
* _optional_ Update state with additional data before returning KMAC.
|
323
|
+
*
|
324
|
+
* = example
|
325
|
+
* kmac.digest
|
326
|
+
* kmac.digest('final chunk')
|
327
|
+
*/
|
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);
|
331
|
+
|
332
|
+
VALUE data = argc > 0 ? argv[0] : Qnil;
|
333
|
+
|
334
|
+
return sp800_185_digest(context, data);
|
335
|
+
}
|
336
|
+
|
337
|
+
/*
|
338
|
+
* :call-seq:
|
339
|
+
* hexdigest() -> string
|
340
|
+
* hexdigest([data]) -> string
|
341
|
+
*
|
342
|
+
* Returns the hexadecimal representation of the KMAC.
|
343
|
+
* This method creates a copy of the current instance so that
|
344
|
+
* the original state is preserved for future updates.
|
345
|
+
*
|
346
|
+
* +data+::
|
347
|
+
* _optional_ Update state with additional data before returning KMAC.
|
348
|
+
*
|
349
|
+
* = example
|
350
|
+
* kmac.hexdigest
|
351
|
+
* kmac.hexdigest('final chunk')
|
352
|
+
*/
|
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);
|
402
|
+
}
|
403
|
+
|
404
|
+
/*
|
405
|
+
* :call-seq:
|
406
|
+
* ::digest(algorithm, data, output_length, key, [customization]) -> string
|
407
|
+
*
|
408
|
+
* One-shot operation to return the binary KMAC digest without explicitly creating an instance.
|
409
|
+
*
|
410
|
+
* +algorithm+::
|
411
|
+
* The KMAC algorithm to use (as a Symbol) - :kmac_128 or :kmac_256
|
412
|
+
* +data+::
|
413
|
+
* The data to digest
|
414
|
+
* +output_length+::
|
415
|
+
* The length of the output in bytes
|
416
|
+
* +key+::
|
417
|
+
* The key to use for the KMAC
|
418
|
+
* +customization+::
|
419
|
+
* _optional_ The customization string to use
|
420
|
+
*
|
421
|
+
* = example
|
422
|
+
* SHA3::KMAC.digest(:kmac_128, "data", 32, "key")
|
423
|
+
* SHA3::KMAC.digest(:kmac_128, "data", 32, "key", "customization")
|
424
|
+
*/
|
425
|
+
static VALUE rb_sha3_kmac_self_digest(int argc, VALUE *argv, VALUE klass) {
|
426
|
+
VALUE algorithm, data, output_length, key, customization;
|
427
|
+
|
428
|
+
rb_scan_args(argc, argv, "41", &algorithm, &data, &output_length, &key, &customization);
|
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
|
+
|
435
|
+
VALUE kmac = rb_funcall(klass, rb_intern("new"), 4, algorithm, output_length, key, customization);
|
436
|
+
|
437
|
+
return rb_funcall(kmac, rb_intern("digest"), 1, data);
|
438
|
+
}
|
439
|
+
|
440
|
+
/*
|
441
|
+
* :call-seq:
|
442
|
+
* ::hexdigest(algorithm, data, output_length, key, [customization]) -> string
|
443
|
+
*
|
444
|
+
* One-shot operation to return the hexadecimal KMAC digest without explicitly creating an instance.
|
445
|
+
*
|
446
|
+
* +algorithm+::
|
447
|
+
* The KMAC algorithm to use (as a Symbol) - :kmac_128 or :kmac_256
|
448
|
+
* +data+::
|
449
|
+
* The data to digest
|
450
|
+
* +output_length+::
|
451
|
+
* The length of the output in bytes
|
452
|
+
* +key+::
|
453
|
+
* The key to use for the KMAC
|
454
|
+
* +customization+::
|
455
|
+
* _optional_ The customization string to use
|
456
|
+
*
|
457
|
+
* = example
|
458
|
+
* SHA3::KMAC.hexdigest(:kmac_128, "data", 32, "key")
|
459
|
+
* SHA3::KMAC.hexdigest(:kmac_128, "data", 32, "key", "customization")
|
460
|
+
*/
|
461
|
+
static VALUE rb_sha3_kmac_self_hexdigest(int argc, VALUE *argv, VALUE klass) {
|
462
|
+
VALUE algorithm, data, output_length, key, customization;
|
463
|
+
|
464
|
+
rb_scan_args(argc, argv, "41", &algorithm, &data, &output_length, &key, &customization);
|
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
|
+
|
471
|
+
VALUE kmac = rb_funcall(klass, rb_intern("new"), 4, algorithm, output_length, key, customization);
|
472
|
+
|
473
|
+
return rb_funcall(kmac, rb_intern("hexdigest"), 1, data);
|
474
|
+
}
|
data/ext/sha3/kmac.h
ADDED
data/ext/sha3/sha3.c
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#include "sha3.h"
|
2
|
+
|
3
|
+
#include "cshake.h"
|
4
|
+
#include "digest.h"
|
5
|
+
#include "kmac.h"
|
6
|
+
|
7
|
+
VALUE _sha3_module;
|
8
|
+
|
9
|
+
void Init_sha3_ext(void) {
|
10
|
+
/*
|
11
|
+
* Document-module: SHA3
|
12
|
+
*
|
13
|
+
* This module provides implementations of the SHA-3 family of cryptographic hash functions
|
14
|
+
* and the SHAKE extendable-output functions.
|
15
|
+
*
|
16
|
+
* It includes the SHA3::Digest and SHA3::KMAC classes, which offer methods for computing digests and keyed message
|
17
|
+
* authentication codes (KMAC).
|
18
|
+
*
|
19
|
+
* == Classes
|
20
|
+
* SHA3::Digest
|
21
|
+
* SHA3::Digest::Error
|
22
|
+
* SHA3::KMAC
|
23
|
+
* SHA3::KMAC::Error
|
24
|
+
* SHA3::CSHAKE
|
25
|
+
* SHA3::CSHAKE::Error
|
26
|
+
*
|
27
|
+
*/
|
28
|
+
_sha3_module = rb_define_module("SHA3");
|
29
|
+
|
30
|
+
Init_sha3_digest();
|
31
|
+
Init_sha3_cshake();
|
32
|
+
Init_sha3_kmac();
|
33
|
+
|
34
|
+
return;
|
35
|
+
}
|
data/ext/sha3/sha3.h
ADDED