class SHA3::CSHAKE
CSHAKE (Customizable SHAKE) is a family of functions that allow for domain separation and customization of the output. It is based on the cSHAKE algorithm defined in NIST SP800-185.
Public Class Methods
Source
static VALUE rb_sha3_cshake_init(int argc, VALUE *argv, VALUE self) {
VALUE algorithm, length, keywords;
rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, argc, argv, "2:", &algorithm, &length, &keywords);
if (NIL_P(algorithm)) {
rb_raise(rb_eArgError, "missing keyword: algorithm");
}
Check_Type(algorithm, T_SYMBOL);
if (NIL_P(length)) {
rb_raise(rb_eArgError, "missing keyword: length");
}
Check_Type(length, T_FIXNUM);
if (NUM2INT(length) < 0) {
rb_raise(rb_eArgError, "output length must be non-negative");
}
ID table[] = {
rb_intern("name"),
rb_intern("customization"),
};
VALUE values[2];
rb_get_kwargs(keywords, table, 0, 2, values);
VALUE name_str = values[0] == Qundef ? rb_str_new2("") : values[0];
StringValue(name_str);
VALUE customization = values[1] == Qundef ? rb_str_new2("") : values[1];
StringValue(customization);
sha3_cshake_context_t *context;
TypedData_Get_Struct(self, sha3_cshake_context_t, &sha3_cshake_data_type, context);
// Store the output length in bits
context->base.output_length = NUM2INT(length) * 8;
context->base.error_class = _sha3_cshake_error_class;
// Find the appropriate function table based on the algorithm
sp800_185_algorithm_t alg_type;
if (algorithm == ID2SYM(_cshake_128_id)) {
alg_type = SP800_185_CSHAKE_128;
} else if (algorithm == ID2SYM(_cshake_256_id)) {
alg_type = SP800_185_CSHAKE_256;
} else {
rb_raise(rb_eArgError, "invalid algorithm: %s", rb_id2name(SYM2ID(algorithm)));
}
context->base.functions = sp800_185_get_algorithm(alg_type);
if (!context->base.functions) {
rb_raise(_sha3_cshake_error_class, "algorithm not available");
}
// Initialize using the safe accessor function
int result = sp800_185_init_cshake(context->base.functions, context->base.state, context->base.output_length,
(BitSequence *)RSTRING_PTR(name_str), RSTRING_LEN(name_str) * 8,
(BitSequence *)RSTRING_PTR(customization), RSTRING_LEN(customization) * 8);
if (result != 0) {
rb_raise(_sha3_cshake_error_class, "failed to initialize %s algorithm", context->base.functions->name);
}
return self;
}
Initializes a new CSHAKE instance with the specified algorithm and output length.
algorithm-
The
CSHAKEalgorithm to use (as a Symbol) - :cshake_128 or :cshake_256 output_length-
The length of the output in bytes. Set to 0 for an arbitrarily-long output using “squeeze” (XOF) methods.
name-
optional The name string to use for domain separation
customization-
optional The customization string to use
example¶ ↑
# Initialize instance for fix-ed-length operation cshake = SHA3::CSHAKE.new(:cshake_128, 32, name: 'my-app') cshake << 'data...' cshake.hexdigest # Initialize instance for XOF operation (arbitrary-long output) cshake = SHA3::CSHAKE.new(:cshake_256, 0, customization: 'Email Signature') cshask.update('data...') cshake.squeeze(64)
Public Instance Methods
Source
static VALUE rb_sha3_cshake_digest(int argc, VALUE *argv, VALUE self) {
sp800_185_context_t *context;
get_cshake_context(self, &context);
VALUE data = argc > 0 ? argv[0] : Qnil;
return sp800_185_digest(context, data);
}
Returns the digest of the CSHAKE instance.
data-
optional Additional data to include in the digest.
example¶ ↑
cshake.digest cshake.digest("final chunk")
Source
static VALUE rb_sha3_cshake_hex_squeeze(VALUE self, VALUE length) {
sp800_185_context_t *context;
get_cshake_context(self, &context);
return sp800_185_hex_squeeze(context, length);
}
Returns the hexadecimal CSHAKE digest with the specified length.
length-
The length of the output in bytes.
example¶ ↑
cshake.hex_squeeze(32)
Source
static VALUE rb_sha3_cshake_hexdigest(int argc, VALUE *argv, VALUE self) {
sp800_185_context_t *context;
get_cshake_context(self, &context);
VALUE data = argc > 0 ? argv[0] : Qnil;
return sp800_185_hexdigest(context, data);
}
Returns the hexadecimal digest of the CSHAKE instance.
data-
optional Additional data to include in the digest.
example¶ ↑
cshake.hexdigest cshake.hexdigest("final chunk")
Source
static VALUE rb_sha3_cshake_copy(VALUE self, VALUE other) {
sha3_cshake_context_t *context, *other_context;
rb_check_frozen(self);
if (self == other) {
return self;
}
if (!rb_obj_is_kind_of(other, _sha3_cshake_class)) {
rb_raise(rb_eTypeError, "wrong argument (%s)! (expected %s)", rb_obj_classname(other),
rb_class2name(_sha3_cshake_class));
}
TypedData_Get_Struct(other, sha3_cshake_context_t, &sha3_cshake_data_type, other_context);
TypedData_Get_Struct(self, sha3_cshake_context_t, &sha3_cshake_data_type, context);
// Copy the base context attributes
context->base.functions = other_context->base.functions;
context->base.output_length = other_context->base.output_length;
// Copy the algorithm-specific state
memcpy(context->base.state, other_context->base.state, context->base.functions->state_size);
return self;
}
Creates a copy of the CSHAKE instance.
other-
The
CSHAKEinstance to copy.
example¶ ↑
cshake2 = cshake.dup
Source
static VALUE rb_sha3_cshake_name(VALUE self) {
sp800_185_context_t *context;
get_cshake_context(self, &context);
return rb_str_new2(sp800_185_name(context));
}
Returns the name of the CSHAKE instance.
Source
Source
static VALUE rb_sha3_cshake_update(VALUE self, VALUE data) {
sp800_185_context_t *context;
get_cshake_context(self, &context);
sp800_185_update(context, data);
return self;
}
Updates the CSHAKE instance with the provided string.
string-
The string to update the
CSHAKEwith.
example¶ ↑
cshake.update("more data") cshake << "more data" # alias for update
Private Instance Methods
Source
static VALUE rb_sha3_cshake_finish(int argc, VALUE *argv, VALUE self) {
sp800_185_context_t *context;
get_cshake_context(self, &context);
VALUE output = argc > 0 ? argv[0] : Qnil;
return sp800_185_finish(context, output);
}
Returns the final CSHAKE digest as a binary string.
message-
optional Output buffer to receive the final
CSHAKEvalue.
example¶ ↑
cshake.finish