blob: 9f501a756321eadb15577287d8c124757a4f2af1 [file] [log] [blame] [raw]
/*
Copyright: Boaz segev, 2016-2017
License: MIT except for any non-public-domain algorithms (none that I'm aware
of), which might be subject to their own licenses.
Feel free to copy, use and enjoy in accordance with to the license(s).
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "hex.h"
#include <ctype.h>
/* ***************************************************************************
Hex Conversion
*/
/*
#define hex2i(h) \
(((h) >= '0' && (h) <= '9') ? ((h) - '0') : (((h) | 32) - 'a' + 10))
*/
#define i2hex(hi) (((hi) < 10) ? ('0' + (hi)) : ('A' + ((hi)-10)))
/* Credit to Jonathan Leffler for the idea */
#define hex2i(c) \
(((c) >= '0' && (c) <= '9') \
? ((c)-48) \
: (((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) \
? (((c) | 32) - 87) \
: ({ \
return -1; \
0; \
}))
/**
Returns 1 if the string is HEX encoded (no non-valid hex values). Returns 0 if
it isn't.
*/
int bscrypt_is_hex(const char *string, size_t length) {
// for (size_t i = 0; i < length; i++) {
// if (isxdigit(string[i]) == 0)
// return 0;
char c;
for (size_t i = 0; i < length; i++) {
c = string[i];
if ((!isspace(c)) &&
(c < '0' || c > 'z' ||
!((c >= 'a') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))))
return 0;
}
return 1;
}
/**
This will convert the string (byte stream) to a Hex string. This is not
cryptography, just conversion for pretty print.
The target buffer MUST have enough room for the expected data. The expected
data is double the length of the string + 1 byte for the NULL terminator
byte.
A NULL byte will be appended to the target buffer. The function will return
the number of bytes written to the target buffer.
Returns the number of bytes actually written to the target buffer (excluding
the NULL terminator byte).
*/
int bscrypt_str2hex(char *target, const char *string, size_t length) {
if (!target)
return -1;
size_t i = length;
target[(length << 1) + 1] = 0;
// go in reverse, so that target could be same as string.
while (i) {
--i;
target[(i << 1) + 1] = i2hex(string[i] & 0x0F);
target[(i << 1)] = i2hex(((uint8_t *)string)[i] >> 4);
}
return (length << 1);
}
/**
This will convert a Hex string to a byte string. This is not cryptography,
just conversion for pretty print.
The target buffer MUST have enough room for the expected data. The expected
data is half the length of the Hex string + 1 byte for the NULL terminator
byte.
A NULL byte will be appended to the target buffer. The function will return
the number of bytes written to the target buffer.
If the target buffer is NULL, the encoded string will be destructively
edited
and the decoded data will be placed in the original string's buffer.
Returns the number of bytes actually written to the target buffer (excluding
the NULL terminator byte).
*/
int bscrypt_hex2str(char *target, char *hex, size_t length) {
if (!target)
target = hex;
size_t i = 0;
size_t written = 0;
while (i + 1 < length) {
if (isspace(hex[i])) {
++i;
continue;
}
target[written] = (hex2i(hex[i]) << 4) | hex2i(hex[i + 1]);
++written;
i += 2;
}
if (i < length && !isspace(hex[i])) {
target[written] = hex2i(hex[i + 1]);
++written;
}
target[written] = 0;
return written;
}
#undef hex2i
#undef i2hex