class SHA3::Digest
It is a subclass of the Digest::Class class, which provides a framework for creating and manipulating hash digest. Supported Algorithms are:
-
SHA3-224 (:sha3_224)
-
SHA3-256 (:sha3_256)
-
SHA3-384 (:sha3_384)
-
SHA3-512 (:sha3_512)
-
SHAKE128 (:shake_128)
-
SHAKE256 (:shake_256)
Public Class Methods
Source
static VALUE rb_sha3_digest_self_digest(VALUE klass, VALUE name, VALUE data) { // Add null checks if (NIL_P(name) || NIL_P(data)) { rb_raise(_sha3_digest_error_class, "algorithm name and data cannot be nil"); } // Add type validation for name if (TYPE(name) != T_SYMBOL) { rb_raise(_sha3_digest_error_class, "algorithm name must be a symbol"); } // Existing code... VALUE args[2]; // Need to add type checking for the data parameter StringValue(data); /* For SHAKE algorithms, we need to handle them differently */ if (TYPE(name) == T_SYMBOL) { ID symid = SYM2ID(name); if (symid == _shake_128_id || symid == _shake_256_id) { /* Create a new digest instance with the specified algorithm */ VALUE digest = rb_class_new_instance(1, &name, klass); /* Update it with the data */ rb_sha3_digest_update(digest, data); /* For SHAKE algorithms, use a default output length based on the security strength */ int output_length = (symid == _shake_128_id) ? 16 : 32; /* 128/8 or 256/8 */ /* Return the squeezed output */ return rb_sha3_digest_squeeze(digest, INT2NUM(output_length)); } } /* Call the superclass method with arguments in reverse order */ args[0] = data; args[1] = name; return rb_call_super(2, args); }
Returns the binary digest of the given data
using the algorithm specified by name
.
name
-
The hash algorithm to use (as a Symbol). Valid algorithms are:
-
:sha3_224
-
:sha3_256
-
:sha3_384
-
:sha3_512
-
:shake_128
-
:shake_256
-
data
-
The data to hash.
example¶ ↑
SHA3::Digest.digest(:sha3_256, "data to hash")
note¶ ↑
This method defaults to squeezing 16 bytes for SHAKE128 and 32 bytes for SHAKE256. To squeeze a different length, use squeeze
instance method.
Source
static VALUE rb_sha3_digest_self_hexdigest(VALUE klass, VALUE name, VALUE data) { VALUE args[2]; // Need to add type checking for the data parameter StringValue(data); /* For SHAKE algorithms, we need to handle them differently */ if (TYPE(name) == T_SYMBOL) { ID symid = SYM2ID(name); if (symid == _shake_128_id || symid == _shake_256_id) { /* Create a new digest instance with the specified algorithm */ VALUE digest = rb_class_new_instance(1, &name, klass); /* Update it with the data */ rb_sha3_digest_update(digest, data); /* For SHAKE algorithms, use a default output length based on the security strength */ int output_length = (symid == _shake_128_id) ? 16 : 32; /* 128/8 or 256/8 */ /* Return the hexadecimal representation of the squeezed output */ return rb_sha3_digest_hex_squeeze(digest, INT2NUM(output_length)); } } /* Call the superclass method with arguments in reverse order */ args[0] = data; args[1] = name; return rb_call_super(2, args); }
Returns the hexadecimal representation of the given data
using the algorithm specified by name
.
name
-
The hash algorithm to use (as a Symbol). Valid algorithms are:
-
:sha3_224
-
:sha3_256
-
:sha3_384
-
:sha3_512
-
:shake_128
-
:shake_256
-
data
-
The data to hash.
example¶ ↑
SHA3::Digest.hexdigest(:sha3_256, "data to hash")
note¶ ↑
This method defaults to squeezing 16 bytes for SHAKE128 and 32 bytes for SHAKE256. To squeeze a different length, use hex_squeeze
instance method.
Source
static VALUE rb_sha3_digest_init(int argc, VALUE *argv, VALUE self) { sha3_digest_context_t *context; VALUE hlen, data; rb_scan_args(argc, argv, "02", &hlen, &data); get_sha3_digest_context(self, &context); if (NIL_P(hlen)) { context->algorithm = SHA3_256; context->hashbitlen = 256; } else { context->hashbitlen = get_hashbit_length(hlen, &context->algorithm); } if (keccak_hash_initialize(context) != KECCAK_SUCCESS) { rb_raise(_sha3_digest_error_class, "failed to initialize algorithm state"); } if (!NIL_P(data)) { return rb_sha3_digest_update(self, data); } return self; }
Creates a new digest object.
algorithm
-
optional The algorithm to use. Valid algorithms are:
-
:sha3_224
-
:sha3_256
-
:sha3_384
-
:sha3_512
-
:shake_128
-
:shake_256
-
message
-
optional The message to hash.
example¶ ↑
SHA3::Digest.new(:sha3_256) SHA3::Digest.new(:shake_128, "initial data")
Public Instance Methods
Source
Source
static VALUE rb_sha3_digest_digest(int argc, VALUE *argv, VALUE self) { sha3_digest_context_t *context; get_sha3_digest_context(self, &context); if (context->algorithm != SHAKE_128 && context->algorithm != SHAKE_256) { return rb_call_super(argc, argv); } return prepare_shake_output(self, argc, argv, 0); }
Returns the binary representation of the digest.
length
-
The length of the output to squeeze when using SHAKE algorithms. This parameter is required for SHAKE algorithms.
data
-
optional Update state with additional data before returning digest.
example¶ ↑
digest.digest() digest.digest('compute me') digest.digest(12) # For SHAKE algorithms digest.digest(12, 'compute me') # For SHAKE algorithms
Source
Source
static VALUE rb_sha3_digest_hex_squeeze(VALUE self, VALUE length) { // Get the binary output using the existing squeeze function VALUE bin_str = rb_sha3_digest_squeeze(self, length); // Use Ruby's built-in unpack method to convert to hex return rb_funcall(bin_str, rb_intern("unpack1"), 1, rb_str_new2("H*")); }
Returns the hexadecimal representation of the squeezed output. Only available for SHAKE algorithms.
length
-
The length in bytes of the output to squeeze.
example¶ ↑
digest.hex_squeeze(32) # Get 64 hex characters (32 bytes)
Source
static VALUE rb_sha3_digest_hexdigest(int argc, VALUE *argv, VALUE self) { sha3_digest_context_t *context; get_sha3_digest_context(self, &context); if (context->algorithm != SHAKE_128 && context->algorithm != SHAKE_256) { return rb_call_super(argc, argv); } return prepare_shake_output(self, argc, argv, 1); }
Returns the hexadecimal representation of the digest.
length
-
The length of the output to squeeze when using SHAKE algorithms. This parameter is required for SHAKE algorithms.
data
-
optional Update state with additional data before returning digest.
example¶ ↑
digest.hexdigest() digest.hexdigest('compute me') digest.hexdigest(12) # For SHAKE algorithms digest.hexdigest(12, 'compute me') # For SHAKE algorithms
Source
static VALUE rb_sha3_digest_copy(VALUE self, VALUE other) { sha3_digest_context_t *context; sha3_digest_context_t *other_context; rb_check_frozen(self); if (self == other) { return self; } if (!rb_obj_is_kind_of(other, _sha3_digest_class)) { rb_raise(rb_eTypeError, "wrong argument (%s)! (expected %s)", rb_obj_classname(other), rb_class2name(_sha3_digest_class)); } safe_get_sha3_digest_context(other, &other_context); get_sha3_digest_context(self, &context); context->hashbitlen = other_context->hashbitlen; context->algorithm = other_context->algorithm; memcpy(context->state, other_context->state, sizeof(Keccak_HashInstance)); if (!compare_contexts(context, other_context)) { rb_raise(_sha3_digest_error_class, "failed to copy state"); } return self; }
Initializes the digest with the state of another digest.
other
-
The digest to copy the state from.
example¶ ↑
new_digest = digest.dup
Source
static VALUE rb_sha3_digest_name(VALUE self) { sha3_digest_context_t *context; get_sha3_digest_context(self, &context); switch (context->algorithm) { case SHA3_224: return rb_str_new2("SHA3-224"); case SHA3_256: return rb_str_new2("SHA3-256"); case SHA3_384: return rb_str_new2("SHA3-384"); case SHA3_512: return rb_str_new2("SHA3-512"); case SHAKE_128: return rb_str_new2("SHAKE128"); case SHAKE_256: return rb_str_new2("SHAKE256"); default: rb_raise(_sha3_digest_error_class, "unknown algorithm"); } }
Returns the name of the algorithm.
example¶ ↑
digest.name #=> "SHA3-256"
Source
static VALUE rb_sha3_digest_reset(VALUE self) { sha3_digest_context_t *context; get_sha3_digest_context(self, &context); memset(context->state, 0, sizeof(Keccak_HashInstance)); if (keccak_hash_initialize(context) != KECCAK_SUCCESS) { rb_raise(_sha3_digest_error_class, "failed to reset internal state"); } return self; }
Resets the digest to its initial state.
example¶ ↑
digest.reset
Source
static VALUE rb_sha3_digest_squeeze(VALUE self, VALUE length) { sha3_digest_context_t *context; VALUE str, copy; int output_bytes; Check_Type(length, T_FIXNUM); output_bytes = NUM2INT(length); if (output_bytes <= 0) { rb_raise(_sha3_digest_error_class, "output length must be positive"); } get_sha3_digest_context(self, &context); // Only SHAKE algorithms support arbitrary-length output if (!is_shake_algorithm(context->algorithm)) { rb_raise(_sha3_digest_error_class, "squeeze is only supported for SHAKE algorithms"); } // Create a copy of the digest object to avoid modifying the original copy = rb_obj_clone(self); // Get the sha3_digest_context_t struct from the copy sha3_digest_context_t *context_copy; get_sha3_digest_context(copy, &context_copy); str = rb_str_new(0, output_bytes); // Finalize the hash on the copy if (Keccak_HashFinal(context_copy->state, NULL) != KECCAK_SUCCESS) { rb_raise(_sha3_digest_error_class, "failed to finalize digest"); } // Then squeeze out the desired number of bytes if (Keccak_HashSqueeze(context_copy->state, (BitSequence *)RSTRING_PTR(str), output_bytes * 8) != KECCAK_SUCCESS) { rb_raise(_sha3_digest_error_class, "failed to squeeze output"); } return str; }
Returns the squeezed output as a binary string. Only available for SHAKE algorithms. This method creates a copy of the current instance to preserve the original state.
length
-
The length in bytes of the output to squeeze.
example¶ ↑
digest.squeeze(32) # Get 32 bytes of output
Source
static VALUE rb_sha3_digest_update(VALUE self, VALUE data) { sha3_digest_context_t *context; BitLength dlen; StringValue(data); get_sha3_digest_context(self, &context); // Check for empty data if (RSTRING_LEN(data) == 0) { return self; } // Check for NULL data pointer if (RSTRING_PTR(data) == NULL) { rb_raise(_sha3_digest_error_class, "cannot update with NULL data"); } dlen = (RSTRING_LEN(data) * 8); if (Keccak_HashUpdate(context->state, (BitSequence *)RSTRING_PTR(data), dlen) != KECCAK_SUCCESS) { rb_raise(_sha3_digest_error_class, "failed to update hash data"); } return self; }
Updates the digest with the given string.
string
-
The string to update the digest with.
example¶ ↑
digest.update("more data") digest << "more data" # alias for update
Private Instance Methods
Source
static VALUE rb_sha3_digest_finish(int argc, VALUE *argv, VALUE self) { sha3_digest_context_t *context; VALUE str; int digest_bytes; rb_scan_args(argc, argv, "01", &str); get_sha3_digest_context(self, &context); // For both SHA3 and SHAKE algorithms, use the security strength (hashbitlen) // as the default output length digest_bytes = context->hashbitlen / 8; if (NIL_P(str)) { str = rb_str_new(0, digest_bytes); } else { StringValue(str); rb_str_resize(str, digest_bytes); } if (Keccak_HashFinal(context->state, (BitSequence *)RSTRING_PTR(str)) != KECCAK_SUCCESS) { rb_raise(_sha3_digest_error_class, "failed to finalize digest"); } return str; }
Returns the final digest as a binary string.
message
-
optional Update state with additional data before finalizing.
example¶ ↑
digest.finish digest.finish("final chunk")