├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── include └── mh │ ├── .gitignore │ ├── errors.h │ ├── generic.h │ ├── hashes.h │ └── multihash.h ├── src ├── .gitignore ├── errors.c ├── hashes.c ├── main.c └── multihash.c └── tests └── c ├── .gitignore ├── minunit.h ├── test_errors_string.c ├── test_hashes_code.c ├── test_hashes_length.c ├── test_multihash_decoding.c └── test_multihash_new.c /.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | 3 | !.gitignore 4 | !Makefile 5 | !**/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Protocol Labs, Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | RM = rm -f 3 | CFLAGS = -fPIC -g -O2 -std=c99 \ 4 | -Wall -Wextra -pedantic -Werror \ 5 | -Wdeclaration-after-statement \ 6 | -Wno-format-zero-length \ 7 | -Wold-style-definition \ 8 | -Woverflow \ 9 | -Wpointer-arith \ 10 | -Wunused \ 11 | -Wvla 12 | 13 | LDFLAGS = -g 14 | LDLIBS = 15 | 16 | TARGET_LIB = mulithash.a 17 | TARGET_BIN = multihash 18 | 19 | MAIN = src/main.c 20 | MAIN_O = $(MAIN:.c=.o) 21 | 22 | SRCS = src/hashes.c src/errors.c src/multihash.c 23 | OBJS = $(SRCS:.c=.o) 24 | 25 | src/%.o: src/%.c 26 | $(CC) $(CFLAGS) -c -I include $< -o $@ 27 | 28 | all: $(TARGET_LIB) $(TARGET_BIN) 29 | 30 | $(TARGET_LIB): $(OBJS) 31 | ar rcs $@ $^ 32 | 33 | $(TARGET_BIN): $(MAIN_O) $(TARGET_LIB) 34 | $(CC) $(LDFLAGS) $^ -o $@ 35 | 36 | # Tests 37 | 38 | TEST_SRCS = $(wildcard tests/c/test_*.c) 39 | TEST_OBJS = $(TEST_SRCS:.c=.o) 40 | TEST_BINS = $(TEST_OBJS:.o=) 41 | 42 | PHONY += test 43 | test: $(TEST_BINS) 44 | @for t in $^; do \ 45 | echo; \ 46 | echo '***' "$$t.c" '***'; \ 47 | "./$$t" || ERROR=1; \ 48 | done; \ 49 | echo; \ 50 | exit $$ERROR 51 | 52 | tests/c/test_%.o: tests/c/test_%.c tests/c/minunit.h 53 | $(CC) $(CFLAGS) -c -I include $< -o $@ 54 | 55 | tests/c/test_%: tests/c/test_%.o $(TARGET_LIB) 56 | $(CC) $(LDFLAGS) $^ -o $@ 57 | 58 | # Utils 59 | 60 | PHONY += clean dist-clean 61 | 62 | clean: 63 | $(RM) $(OBJS) 64 | $(RM) $(TEST_BINS) 65 | $(RM) $(TARGET_LIB) 66 | $(RM) $(TARGET_BIN) 67 | $(RM) $(MAIN_O) 68 | 69 | dist-clean: clean 70 | 71 | PHONY += build 72 | build: all 73 | 74 | .PHONY: $(PHONY) 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **This project is no longer maintained and has been archived.** 2 | 3 | # c-multihash 4 | 5 | [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) 6 | [![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats) 7 | [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs) 8 | [![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) 9 | 10 | > C implementation of Multihash parsing and encoding (but not hashing) 11 | 12 | This is an implementation of [multihash](https://github.com/multiformats/multihash). 13 | 14 | ## Install 15 | 16 | ``` 17 | > TODO 18 | ``` 19 | 20 | ## Usage 21 | 22 | ``` 23 | > TODO 24 | ``` 25 | 26 | ## Maintainers 27 | 28 | Captain: [@Kubuxu](https://github.com/Kubuxu). 29 | 30 | ## Contribute 31 | 32 | Contributions welcome. Please check out [the issues](https://github.com/multiformats/c-multihash/issues). 33 | 34 | Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). 35 | 36 | Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. 37 | 38 | ## License 39 | 40 | [MIT](LICENSE) © 2016 Protocol Labs Inc. 41 | -------------------------------------------------------------------------------- /include/mh/.gitignore: -------------------------------------------------------------------------------- 1 | !*.h 2 | 3 | -------------------------------------------------------------------------------- /include/mh/errors.h: -------------------------------------------------------------------------------- 1 | #ifndef ERROR_H 2 | #define ERROR_H 3 | 4 | 5 | #define MH_E_NO_ERROR 0 6 | #define MH_E_UNKNOWN_CODE -1 7 | #define MH_E_TOO_SHORT -2 8 | #define MH_E_TOO_LONG -3 9 | #define MH_E_VARINT_NOT_SUPPORTED -4 10 | #define MH_E_DIGSET_TOO_LONG -5 11 | 12 | #define MH_E_LAST -5 13 | 14 | const char *mh_error_string(int code); 15 | 16 | #endif /* end of include guard */ 17 | -------------------------------------------------------------------------------- /include/mh/generic.h: -------------------------------------------------------------------------------- 1 | #ifndef MH_GENERIC 2 | #define MH_GENERIC 3 | 4 | #define mh_assert_static(isTrue) void mh_assert_static(char x[1 - (!(isTrue))]) 5 | 6 | #define UNUSED(x) (void)(x) 7 | 8 | #endif /* end of include guard */ 9 | -------------------------------------------------------------------------------- /include/mh/hashes.h: -------------------------------------------------------------------------------- 1 | #include "errors.h" 2 | 3 | // definitions of hash functions 4 | #define MH_H_SHA1 0x11 5 | #define MH_H_SHA2_256 0x12 6 | #define MH_H_SHA2_512 0x13 7 | #define MH_H_SHA3_512 0x14 8 | #define MH_H_SHA3_384 0x15 9 | #define MH_H_SHA3_256 0x16 10 | #define MH_H_SHA3_224 0x17 11 | #define MH_H_SHAKE_128 0x18 12 | #define MH_H_SHAKE_256 0x19 13 | #define MH_H_BLAKE2B 0x40 14 | #define MH_H_BLAKE2S 0x41 15 | 16 | 17 | // list of avaliable hash functions. 18 | static const int mh_all_hashes[] = { 19 | MH_H_SHA1, 20 | MH_H_SHA2_256, 21 | MH_H_SHA2_512, 22 | MH_H_SHA3_512, 23 | MH_H_SHA3_384, 24 | MH_H_SHA3_256, 25 | MH_H_SHA3_224, 26 | MH_H_SHAKE_128, 27 | MH_H_SHAKE_256, 28 | MH_H_BLAKE2B, 29 | MH_H_BLAKE2S, 30 | }; 31 | 32 | #define MH_H_COUNT (int)(sizeof(mh_all_hashes) / sizeof(mh_all_hashes[0])) 33 | 34 | const char *mh_hash_name(int hash); 35 | 36 | // returns length in bytes or if returns is < 0 it is an error 37 | int mh_hash_default_length(int hash); 38 | -------------------------------------------------------------------------------- /include/mh/multihash.h: -------------------------------------------------------------------------------- 1 | #ifndef MH_HULTIHASH_H 2 | #define MH_HULTIHASH_H 3 | 4 | #include 5 | 6 | // returns hash code or error (which is < 0) 7 | int mh_multihash_hash(const unsigned char *multihash, size_t len); 8 | 9 | // returns length of multihash or error (which is < 0) 10 | int mh_multihash_length(const unsigned char *multihash, size_t len); 11 | 12 | // gives access to raw digest inside multihash buffer 13 | // returns 0 or negative error 14 | int mh_multihash_digest(unsigned char *multihash, size_t len, 15 | unsigned char **digest, size_t *digest_len); 16 | 17 | // returns length in bytes of buffer needed to store multihash 18 | // with given hashcode and with given digest length 19 | // returns length or negative error code 20 | int mh_new_length(int code, size_t digest_len); 21 | 22 | // writes multihash into a buffer, the buffer needs to be at least 23 | // mh_new_length() bytes long. 24 | // returns negative error code or 0 25 | int mh_new(unsigned char *buffer, int code, const unsigned char *digest, 26 | size_t digest_len); 27 | 28 | #endif /* end of include guard */ 29 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | !*.c 2 | -------------------------------------------------------------------------------- /src/errors.c: -------------------------------------------------------------------------------- 1 | #include "mh/errors.h" 2 | 3 | const char *mh_error_string(int code) { 4 | switch (code) { 5 | case MH_E_NO_ERROR: 6 | return "no error"; 7 | case MH_E_UNKNOWN_CODE: 8 | return "unknown multihash code"; 9 | case MH_E_TOO_SHORT: 10 | return "multihash too short. must be > 2 bytes"; 11 | case MH_E_TOO_LONG: 12 | return "multihash too long. must be < 129 bytes"; 13 | case MH_E_VARINT_NOT_SUPPORTED: 14 | return "c-multihash does not yet support" 15 | " varint encoding"; 16 | case MH_E_DIGSET_TOO_LONG: 17 | return "c-multihash does not support digsets" 18 | " longer than 127 bytes yet"; 19 | default: 20 | return "unknown error code"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/hashes.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "mh/hashes.h" 4 | 5 | #include "mh/errors.h" 6 | #include "mh/generic.h" 7 | 8 | 9 | static const struct hash_info { 10 | int hash; 11 | const char *name; 12 | int length; 13 | } hash_infos[] = { 14 | { MH_H_SHA1, "sha1", 20}, 15 | { MH_H_SHA2_256, "sha2-256", 32 }, 16 | { MH_H_SHA2_512, "sha2-512", 64 }, 17 | { MH_H_SHA3_512, "sha3-512", 64 }, 18 | { MH_H_SHA3_384, "sha3-384", 45 }, 19 | { MH_H_SHA3_256, "sha3-256", 32 }, 20 | { MH_H_SHA3_224, "sha3-224", 28 }, 21 | { MH_H_SHAKE_128, "shake-128", 16 }, 22 | { MH_H_SHAKE_256, "shake-256", 32 }, 23 | { MH_H_BLAKE2B, "blake2b", 64 }, 24 | { MH_H_BLAKE2S, "blake2s", 32 } 25 | }; 26 | 27 | mh_assert_static(sizeof(hash_infos) / sizeof(hash_infos[0]) == MH_H_COUNT); 28 | 29 | // Searches for given hash in hash info table 30 | static const struct hash_info *find_hash(int hash) { 31 | // naive search, could be replaced with binary 32 | unsigned int i = 0; 33 | for (; i < MH_H_COUNT; i++) { 34 | if (hash_infos[i].hash == hash) 35 | return &hash_infos[i]; 36 | } 37 | 38 | return NULL; 39 | } 40 | 41 | const char *mh_hash_name(int hash) { 42 | const struct hash_info *info = find_hash(hash); 43 | return (info != NULL) ? info->name : NULL; 44 | } 45 | 46 | 47 | int mh_hash_default_length(int hash) { 48 | const struct hash_info *info = find_hash(hash); 49 | return (info != NULL) ? info->length : MH_E_UNKNOWN_CODE; 50 | } 51 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) { 4 | printf("Hello World\n"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /src/multihash.c: -------------------------------------------------------------------------------- 1 | #include "mh/multihash.h" 2 | 3 | #include "mh/hashes.h" 4 | #include "mh/errors.h" 5 | #include "mh/generic.h" 6 | 7 | #include 8 | #include 9 | 10 | #define VARINT_MASK (1 << 7) 11 | 12 | static int check_len(size_t len) { 13 | if (len < 1) 14 | return MH_E_TOO_SHORT; 15 | else if (len >= 128) 16 | return MH_E_TOO_LONG; 17 | 18 | return MH_E_NO_ERROR; 19 | } 20 | 21 | static int check_multihash(const unsigned char mh[], size_t len) { 22 | int err; 23 | 24 | if (len < 3) 25 | return MH_E_TOO_SHORT; 26 | 27 | if (mh[0] & VARINT_MASK) { 28 | // This value is a varint, but there are currently no supported 29 | // values that require more than a single byte to represent. 30 | return MH_E_VARINT_NOT_SUPPORTED; 31 | } else if (mh[1] & VARINT_MASK) { 32 | return MH_E_VARINT_NOT_SUPPORTED; 33 | } 34 | 35 | err = check_len(mh[1]); 36 | if (err) 37 | return err; 38 | 39 | return 0; 40 | } 41 | 42 | 43 | // returns hash code or error (which is < 0) 44 | int mh_multihash_hash(const unsigned char *mh, size_t len) { 45 | int err = check_multihash(mh, len); 46 | if (err) 47 | return err; 48 | 49 | return (int) mh[0]; 50 | } 51 | 52 | 53 | // returns length of multihash or error (which is < 0) 54 | int mh_multihash_length(const unsigned char *mh, size_t len) { 55 | int err = check_multihash(mh, len); 56 | if (err) 57 | return err; 58 | 59 | return (int) mh[1]; 60 | } 61 | 62 | // gives access to raw digest inside multihash buffer 63 | // returns 0 or negative error 64 | int mh_multihash_digest(unsigned char *multihash, size_t len, unsigned char **digest, 65 | size_t *digest_len) { 66 | int err = check_multihash(multihash, len); 67 | if (err) 68 | return err; 69 | 70 | (*digest_len) = (size_t) mh_multihash_length(multihash, len); 71 | (*digest) = multihash + 2; // Always true without varint 72 | 73 | return 0; 74 | } 75 | 76 | int mh_new_length(int code, size_t hash_len) { 77 | // right now there is no varint support 78 | // so length required is 2 + hash_len 79 | UNUSED(code); 80 | return 2 + hash_len; 81 | } 82 | 83 | int mh_new(unsigned char *buffer, int code, const unsigned char *digest, 84 | size_t digest_len) { 85 | if (code & VARINT_MASK) 86 | return MH_E_VARINT_NOT_SUPPORTED; 87 | if (digest_len > 127) 88 | return MH_E_DIGSET_TOO_LONG; 89 | 90 | buffer[0] = (unsigned char) ((unsigned int) code) & 255; 91 | buffer[1] = (unsigned char) digest_len; 92 | memcpy(buffer + 2, digest, digest_len); 93 | 94 | return 0; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /tests/c/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !minunit.h 4 | !*.c 5 | -------------------------------------------------------------------------------- /tests/c/minunit.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define mu_assert(message, test) do { if (!(test)) return message; } while (0) 4 | #define mu_run_test(test) do { char *message; printf(" - run: %s\n", #test); \ 5 | message = test(); tests_run++; \ 6 | if (message) return message; } while (0) 7 | 8 | int tests_run = 0; 9 | static char *mu_all_tests(void); 10 | 11 | int main(void) { 12 | char *result = mu_all_tests(); 13 | if (result != NULL) { 14 | printf("error: %s\n", result); 15 | printf("!!! TEST FAILURE !!!\n"); 16 | } 17 | else { 18 | printf("ALL TESTS PASSED\n"); 19 | } 20 | printf("Tests run: %d\n", tests_run); 21 | 22 | return result != 0; 23 | } 24 | 25 | void dump(const unsigned char *data, size_t size) { 26 | char ascii[17]; 27 | size_t i, j; 28 | ascii[16] = '\0'; 29 | for (i = 0; i < size; ++i) { 30 | printf("%02X ", ((unsigned char*)data)[i]); 31 | if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') { 32 | ascii[i % 16] = ((unsigned char*)data)[i]; 33 | } else { 34 | ascii[i % 16] = '.'; 35 | } 36 | if ((i+1) % 8 == 0 || i+1 == size) { 37 | printf(" "); 38 | if ((i+1) % 16 == 0) { 39 | printf("| %s \n", ascii); 40 | } else if (i+1 == size) { 41 | ascii[(i+1) % 16] = '\0'; 42 | if ((i+1) % 16 <= 8) { 43 | printf(" "); 44 | } 45 | for (j = (i+1) % 16; j < 16; ++j) { 46 | printf(" "); 47 | } 48 | printf("| %s \n", ascii); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/c/test_errors_string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "minunit.h" 3 | 4 | #include "mh/errors.h" 5 | 6 | char error_buf[256]; 7 | 8 | static char *test_error_messages_exist(void) { 9 | int i = -1; 10 | for (; i > MH_E_LAST; i--) { 11 | sprintf(error_buf, "error code %d has no message", i); 12 | mu_assert(error_buf, strlen(mh_error_string(i)) > 0); 13 | mu_assert(error_buf, 14 | strcmp(mh_error_string(-10000), mh_error_string(i)) != 0); 15 | } 16 | 17 | return NULL; 18 | } 19 | 20 | static char *mu_all_tests(void) { 21 | mu_run_test(test_error_messages_exist); 22 | return NULL; 23 | } 24 | -------------------------------------------------------------------------------- /tests/c/test_hashes_code.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "minunit.h" 3 | 4 | #include "mh/errors.h" 5 | #include "mh/hashes.h" 6 | 7 | char error_buf[256]; 8 | 9 | static char *test_all_hashes_have_names(void) { 10 | int i = 0; 11 | for (; i < MH_H_COUNT; i++) { 12 | sprintf(error_buf, "hash code %d does not have name mapping", 13 | i); 14 | mu_assert(error_buf, mh_hash_name(mh_all_hashes[i]) != NULL); 15 | } 16 | return NULL; 17 | } 18 | 19 | static char *test_name_is_null_when_out_of_bands(void) { 20 | mu_assert("hash code out of range does not have name", 21 | mh_hash_name(0) == NULL); 22 | return NULL; 23 | } 24 | 25 | static char *mu_all_tests(void) { 26 | mu_run_test(test_name_is_null_when_out_of_bands); 27 | mu_run_test(test_all_hashes_have_names); 28 | return NULL; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /tests/c/test_hashes_length.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "minunit.h" 3 | 4 | #include "mh/errors.h" 5 | #include "mh/hashes.h" 6 | 7 | char error_buf[256]; 8 | 9 | static char *test_all_hashes_have_lengths(void) { 10 | int i = 0; 11 | int length = 0; 12 | for (; i < MH_H_COUNT; i++) { 13 | length = mh_hash_default_length(mh_all_hashes[i]); 14 | sprintf(error_buf, "mh_hash_default_length: hash %d" 15 | " returned invalid (%d) default length", 16 | i, length); 17 | mu_assert(error_buf, length > 0); 18 | } 19 | return NULL; 20 | } 21 | 22 | static char *test_error_when_out_of_bands(void) { 23 | mu_assert("out of bands index should give error", 24 | mh_hash_default_length(1 << 20) == MH_E_UNKNOWN_CODE); 25 | return NULL; 26 | } 27 | 28 | static char *test_lengths_are_correct_for_known_codes(void) { 29 | #define hlen mh_hash_default_length 30 | mu_assert("sha1 has valid length", hlen(MH_H_SHA1) == 20); 31 | mu_assert("sha3-512 has valid length", hlen(MH_H_SHA3_256) == 32); 32 | mu_assert("shake-128 has valid length", hlen(MH_H_SHAKE_128) == 16); 33 | 34 | #undef hlen 35 | return NULL; 36 | } 37 | 38 | 39 | 40 | static char *mu_all_tests(void) { 41 | mu_run_test(test_all_hashes_have_lengths); 42 | mu_run_test(test_error_when_out_of_bands); 43 | mu_run_test(test_lengths_are_correct_for_known_codes); 44 | return NULL; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /tests/c/test_multihash_decoding.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "minunit.h" 3 | #include "mh/multihash.h" 4 | 5 | #include "mh/hashes.h" 6 | 7 | #include "examples.h" 8 | 9 | char error_buf[256]; 10 | 11 | static char *test_multihash_hash_decoding_works(void) { 12 | mu_assert("sha1 multihash is detected as sha1", 13 | mh_multihash_hash(sha1_example, sizeof(sha1_example)) 14 | == MH_H_SHA1); 15 | mu_assert("sha2 multihash is detected as sha2", 16 | mh_multihash_hash(sha2_example, sizeof(sha2_example)) 17 | == MH_H_SHA2_256); 18 | mu_assert("sha3 multihash is detected as sha3", 19 | mh_multihash_hash(sha3_example, sizeof(sha3_example)) 20 | == MH_H_SHA3_512); 21 | return NULL; 22 | } 23 | 24 | static char *test_multihash_length_decoding_works(void) { 25 | mu_assert("sha1 multihash has correct length", 26 | mh_multihash_length(sha1_example, sizeof(sha1_example)) 27 | == mh_hash_default_length(MH_H_SHA1)); 28 | mu_assert("sha2 multihash has correct length", 29 | mh_multihash_length(sha2_example, sizeof(sha2_example)) 30 | == mh_hash_default_length(MH_H_SHA2_256)); 31 | mu_assert("sha3-512 multihash has correct length", 32 | mh_multihash_length(sha3_example, sizeof(sha3_example)) 33 | == mh_hash_default_length(MH_H_SHA3_512)); 34 | return NULL; 35 | } 36 | 37 | static char *mu_all_tests(void) { 38 | mu_run_test(test_multihash_hash_decoding_works); 39 | mu_run_test(test_multihash_length_decoding_works); 40 | return NULL; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /tests/c/test_multihash_new.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "minunit.h" 3 | #include "mh/multihash.h" 4 | 5 | #include "mh/hashes.h" 6 | 7 | #include "examples.h" 8 | 9 | char error_buf[256]; 10 | 11 | static char *test_multihash_new_crafts_right_multihash(void) { 12 | int error; 13 | unsigned char buf[256]; // much bigger than needed 14 | size_t digest_len = -1; 15 | const unsigned char *digest = NULL; 16 | 17 | error = mh_multihash_digest(sha1_example, sha1_example_length, 18 | &digest, &digest_len); 19 | mu_assert("getting digest", error == MH_E_NO_ERROR); 20 | 21 | error = mh_new(buf, MH_H_SHA1, digest, digest_len); 22 | mu_assert("creating multihash", error == MH_E_NO_ERROR); 23 | 24 | mu_assert("crafted multihash is the same", memcmp(sha1_example, buf, 25 | sha1_example_length) == 0); 26 | 27 | return NULL; 28 | } 29 | 30 | static char *test_multihash_new_is_reversible(void) { 31 | int error = MH_E_NO_ERROR; 32 | int code = MH_H_SHA3_512; 33 | const unsigned char *digest = random_512; 34 | const size_t digest_len = 512 / 8; 35 | 36 | unsigned char mh[256]; 37 | const size_t mh_len = mh_new_length(code, digest_len); 38 | 39 | error = mh_new(mh, MH_H_SHA3_512, digest, digest_len); 40 | mu_assert("creating multihash", error == MH_E_NO_ERROR); 41 | 42 | mu_assert("reading code", mh_multihash_hash(mh, mh_len) == MH_H_SHA3_512); 43 | mu_assert("reading length", mh_multihash_length(mh, mh_len) == 44 | (int) digest_len); 45 | 46 | return NULL; 47 | } 48 | 49 | static char *mu_all_tests(void) { 50 | mu_run_test(test_multihash_new_crafts_right_multihash); 51 | mu_run_test(test_multihash_new_is_reversible); 52 | return NULL; 53 | } 54 | 55 | --------------------------------------------------------------------------------