Hashing Utilities
May 26, 2025 ยท View on GitHub
This document provides an overview of the hashing utilities provided by the library for generating SHA-256 hashes and creating custom hash digests. These tools are useful for tasks such as file integrity verification, dynamic programming, and avoiding recomputation in compilers or bundlers.
SHA-256 Hash Generation
The library supports generating SHA-256 hashes directly from files. This is particularly useful for verifying file integrity or creating unique identifiers for file contents.
Example: Generating SHA-256 Hash from a File
The following example demonstrates how to generate an SHA-256 hash from a file using the dtw_generate_sha_from_file function.
#include "doTheWorldOne.c"
int main(int argc, char *argv[]) {
// Generate SHA-256 hash from a file
char *hash = dtw_generate_sha_from_file("tests/target/blob.png");
printf("SHA: %s\n", hash);
// Free the allocated memory for the hash
free(hash);
return 0;
}
Explanation:
- The
dtw_generate_sha_from_filefunction takes a file path as input and returns a dynamically allocated string containing the SHA-256 hash of the file's contents. - Ensure the file exists at the specified path; otherwise, the function may return
NULLor an error. - Always free the returned hash string to prevent memory leaks.
Custom Hashing with DtwHash
The DtwHash object provides a flexible way to create custom hash digests by combining various types of data (strings, numbers, booleans, arrays, files, and folders). This is particularly useful in scenarios like dynamic programming or caching, where a unique hash is needed to represent a combination of inputs or states.
Creating and Freeing a DtwHash Object
To use the DtwHash object, initialize it with newDtwHash() and free it with DtwHash_free() when done.
DtwHash *my_hash = newDtwHash();
// Use the hash object for digest operations
DtwHash_free(my_hash);
Digesting Basic Data Types
You can digest various data types into the hash object. Each digest operation updates the internal hash value, which can be accessed via my_hash->hash.
Example: Digesting Strings, Numbers, and Booleans
#include "doTheWorldOne.c"
int main() {
DtwHash *my_hash = newDtwHash();
// Digest a string
DtwHash_digest_string(my_hash, "my string");
printf("Value after digesting string: %s\n", my_hash->hash);
// Digest a long integer
DtwHash_digest_long(my_hash, 10);
printf("Value after digesting long: %s\n", my_hash->hash);
// Digest a double
DtwHash_digest_double(my_hash, 15.6);
printf("Value after digesting double: %s\n", my_hash->hash);
// Digest a boolean
DtwHash_digest_bool(my_hash, true);
printf("Value after digesting boolean: %s\n", my_hash->hash);
// Free the hash object
DtwHash_free(my_hash);
return 0;
}
Explanation:
- Each
DtwHash_digest_*function updates the internal hash value by incorporating the provided data. - The
my_hash->hashfield contains the current hash as a string, which can be printed or used for comparisons.
Example: Digesting a String Array
#include "doTheWorldOne.c"
int main() {
DtwHash *my_hash = newDtwHash();
// Create and populate a string array
DtwStringArray *test = newDtwStringArray();
DtwStringArray_append(test, "b");
DtwStringArray_append(test, "a");
// Digest the string array
DtwHash_digest_string_array(my_hash, test);
printf("Value after digesting string array: %s\n", my_hash->hash);
// Free resources
DtwStringArray_free(test);
DtwHash_free(my_hash);
return 0;
}
Explanation:
- The
DtwHash_digest_string_arrayfunction processes all elements in the providedDtwStringArrayand updates the hash accordingly. - The order of elements in the array may affect the resulting hash, depending on the implementation.
Digesting Files and Folders by Content
You can also digest the contents of files and folders to create a hash representing their data.
Example: Digesting a File and Folder by Content
#include "doTheWorldOne.c"
int main() {
DtwHash *my_hash = newDtwHash();
// Digest a file's content
DtwHash_digest_file(my_hash, "tests/target/a.txt");
printf("After digesting a file: %s\n", my_hash->hash);
// Digest a folder's content recursively
DtwHash_digest_folder_by_content(my_hash, "tests/target");
printf("After digesting a folder: %s\n", my_hash->hash);
// Free the hash object
DtwHash_free(my_hash);
return 0;
}
Explanation:
DtwHash_digest_filereads the content of the specified file and incorporates it into the hash.DtwHash_digest_folder_by_contentrecursively processes all files in the specified folder, digesting their contents into the hash. The order of processing may affect the final hash value.
Digesting Files and Folders by Last Modification Time
Instead of digesting content, you can create a hash based on the last modification times of files and folders. This is useful for detecting changes without reading file contents.
Example: Digesting a File and Folder by Last Modification Time
#include "doTheWorldOne.c"
int main() {
DtwHash *my_hash = newDtwHash();
// Digest a file's last modification time
DtwHash_digest_entity_last_modification(my_hash, "tests/target/a.txt");
printf("After digesting a file's modification time: %s\n", my_hash->hash);
// Digest a folder's last modification times recursively
DtwHash_digest_folder_by_last_modification(my_hash, "tests/target");
printf("After digesting a folder's modification times: %s\n", my_hash->hash);
// Free the hash object
DtwHash_free(my_hash);
return 0;
}
Explanation:
DtwHash_digest_entity_last_modificationincorporates the last modification time of a single file or entity into the hash.DtwHash_digest_folder_by_last_modificationrecursively processes all files in the specified folder, digesting their modification times into the hash.
Best Practices
- Memory Management: Always free dynamically allocated resources like
DtwHash,DtwStringArray, and hash strings returned by functions likedtw_generate_sha_from_fileto avoid memory leaks. - Error Handling: Check for
NULLreturns or errors when working with file paths or digest operations, especially when files or folders may not exist. - Hash Consistency: Be aware that the order of digest operations affects the final hash value. Ensure consistent ordering if reproducibility is required.
Use Cases
- File Integrity: Use SHA-256 hashing to verify that files have not been altered.
- Caching: Use
DtwHashto create unique identifiers for complex data structures or inputs, enabling efficient caching in compilers or bundlers. - Change Detection: Use modification time-based hashing to detect changes in files or directories without reading their contents.