diff --git a/docs/crypto.md b/docs/crypto.md index cbcb855..7b6c419 100644 --- a/docs/crypto.md +++ b/docs/crypto.md @@ -22,3 +22,22 @@ in case you need to know the size of the decoded data, otherwise you can just pa ```c unsigned char *b64_decode(const char *s, size_t sz, size_t *decode_sz); ``` + +### hex_decode + +Decodes a string of characters representing hexadecimal bytes into an array of `unsigned char`. +For example, converts `"DEADBEEF"` into `[0xDE, 0xAD, 0xBE, 0xEF]`. + +```c +unsigned char *hex_decode(const char *orig, size_t *sz); + +// Example +s = hex_decode("DEADBEEF", &s_sz); +unsigned char h[4] = { + 0xDE, 0xAD, 0xBE, 0xEF +}; +for (size_t i = 0; i < 4; ++i) { + assert(s[i] == h[i]); +} +free(s); +``` \ No newline at end of file diff --git a/include/lfcrypto.h b/include/lfcrypto.h index a124336..7a07405 100644 --- a/include/lfcrypto.h +++ b/include/lfcrypto.h @@ -3,7 +3,8 @@ #include -char *b64_encode(const unsigned char *s, size_t sz); +unsigned char *b64_encode(const unsigned char *s, size_t sz); unsigned char *b64_decode(const char *s, size_t sz, size_t *decode_sz); +unsigned char *hex_decode(const char *orig, size_t *sz); #endif // LIBFLINT_CRYPTO_H diff --git a/src/crypto.c b/src/crypto.c index b7e5892..9fc4dcc 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "lfcrypto.h" @@ -18,7 +19,7 @@ static const char b64_table[] = { }; typedef struct { - char *ptr; + unsigned char *ptr; int count; } b64_buf; @@ -44,7 +45,7 @@ static int resize_b64_buf(b64_buf *b, size_t sz) { return 0; } -char *b64_encode(const unsigned char *s, size_t sz) { +unsigned char *b64_encode(const unsigned char *s, size_t sz) { int i = 0; b64_buf encbuf; size_t size = 0; @@ -198,5 +199,28 @@ unsigned char *b64_decode(const char *s, size_t sz, size_t *decode_sz) { *decode_sz = size; } - return (unsigned char*)decbuf.ptr; + return decbuf.ptr; +} + +unsigned char *hex_decode(const char *orig, size_t *sz) { + size_t buf_sz = strlen(orig) + 1; + if (strlen(orig) % 2 != 0) { + buf_sz += 1; + } + + char *buf = malloc(sizeof(char) * buf_sz); + strcpy(buf, orig); + buf[buf_sz - 1] = '\0'; + + *sz = buf_sz / 2; + unsigned char *hex = malloc(sizeof(unsigned char) * *sz); + const char *pos = buf; + + for (size_t i = 0; i < *sz; ++i) { + sscanf(pos, "%2hhx", &hex[i]); + pos += 2; + } + + free(buf); + return hex; } diff --git a/tests/tests.c b/tests/tests.c index a7164f6..e88a1f9 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -311,7 +311,7 @@ void test_string() { void test_crypto() { char *in = "BUTT"; - char *s = b64_encode(in, strlen(in)); + unsigned char *s = b64_encode(in, strlen(in)); assert(strcmp(s, "QlVUVA==") == 0); free(s); @@ -326,6 +326,15 @@ void test_crypto() { assert(strcmp(s, "a longer base64 test, apparently") == 0); assert(strlen(s) == s_sz); free(s); + + s = hex_decode("DEADBEEF", &s_sz); + unsigned char h[4] = { + 0xDE, 0xAD, 0xBE, 0xEF + }; + for (size_t i = 0; i < 4; ++i) { + assert(s[i] == h[i]); + } + free(s); } #if defined(__APPLE__) || defined(__MACH__)