Add sodium_hex2bin()

This commit is contained in:
Frank Denis 2014-04-15 00:39:14 -07:00
parent aec630132c
commit 219db714cf
4 changed files with 71 additions and 3 deletions

View File

@ -26,9 +26,15 @@ SODIUM_EXPORT
int sodium_memcmp(const void * const b1_, const void * const b2_, size_t size);
SODIUM_EXPORT
char *sodium_bin2hex(char * const hex, const size_t hex_len,
char *sodium_bin2hex(char * const hex, const size_t hex_maxlen,
const unsigned char * const bin, const size_t bin_len);
SODIUM_EXPORT
int sodium_hex2bin(unsigned char * const bin, const size_t bin_maxlen,
const char * const hex, const size_t hex_len,
const char * const ignore, size_t * const bin_len,
const char ** const hex_end);
#ifdef __cplusplus
}
#endif

View File

@ -2,6 +2,7 @@
#ifndef __STDC_WANT_LIB_EXT1__
# define __STDC_WANT_LIB_EXT1__ 1
#endif
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
@ -77,7 +78,7 @@ _sodium_alignedcalloc(unsigned char ** const unaligned_p, const size_t len)
}
char *
sodium_bin2hex(char * const hex, const size_t hex_len,
sodium_bin2hex(char * const hex, const size_t hex_maxlen,
const unsigned char * const bin, const size_t bin_len)
{
static const char hexdigits[16] = {
@ -87,7 +88,7 @@ sodium_bin2hex(char * const hex, const size_t hex_len,
size_t i = (size_t) 0U;
size_t j = (size_t) 0U;
if (bin_len >= SIZE_MAX / 2 || hex_len < bin_len * 2U) {
if (bin_len >= SIZE_MAX / 2 || hex_maxlen < bin_len * 2U) {
abort();
}
while (i < bin_len) {
@ -99,3 +100,55 @@ sodium_bin2hex(char * const hex, const size_t hex_len,
return hex;
}
int
sodium_hex2bin(unsigned char * const bin, const size_t bin_maxlen,
const char * const hex, const size_t hex_len,
const char * const ignore, size_t * const bin_len,
const char ** const hex_end)
{
size_t bin_pos = (size_t) 0U;
size_t hex_pos = (size_t) 0U;
int ret = 0;
unsigned char c;
unsigned char c_acc = 0U;
unsigned char c_num;
unsigned char c_val;
unsigned char state = 0U;
while (hex_pos < hex_len) {
c = (unsigned char) hex[hex_pos];
if ((c_num = c ^ 48U) < 10U) {
c_val = c_num;
} else if ((c_num = (c & ~32U)) > 64 && c_num < 71U) {
c_val = c_num - 55U;
} else if (ignore != NULL && strchr(ignore, c) != NULL && state == 0U) {
hex_pos++;
continue;
} else {
break;
}
if (bin_pos >= bin_maxlen) {
ret = -1;
errno = ERANGE;
break;
}
if (state == 0U) {
c_acc = c_val * 16U;
} else {
bin[bin_pos++] = c_acc | c_val;
}
state = ~state;
hex_pos++;
}
if (state != 0U) {
hex_pos--;
}
if (hex_end != NULL) {
*hex_end = &hex[hex_pos];
}
if (bin_len != NULL) {
*bin_len = bin_pos;
}
return ret;
}

View File

@ -9,6 +9,9 @@ int main(void)
unsigned char buf1[1000];
unsigned char buf2[1000];
char buf3[33];
unsigned char buf4[4];
const char *hex;
size_t bin_len;
randombytes(buf1, sizeof buf1);
memcpy(buf2, buf1, sizeof buf2);
@ -23,5 +26,10 @@ int main(void)
printf("%s\n", sodium_bin2hex(buf3, 33U,
(const unsigned char *)
"0123456789ABCDEF", 16U));
hex = "Cafe : 6942";
sodium_hex2bin(buf4, sizeof buf4, hex, strlen(hex), ": ", &bin_len, NULL);
printf("%zu:%02x%02x%02x%02x\n", bin_len,
buf4[0], buf4[1], buf4[2], buf4[3]);
return 0;
}

View File

@ -4,3 +4,4 @@
0
0
30313233343536373839414243444546
4:cafe6942