xs_encdec.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /* copyright (c) 2022 - 2023 grunfink / MIT license */
  2. #ifndef _XS_ENCDEC_H
  3. #define _XS_ENCDEC_H
  4. xs_str *xs_hex_enc(const xs_val *data, int size);
  5. xs_val *xs_hex_dec(const xs_str *hex, int *size);
  6. int xs_is_hex(const char *str);
  7. xs_str *xs_base32_enc(const xs_val *data, int sz);
  8. xs_str *xs_base32hex_enc(const xs_val *data, int sz);
  9. xs_val *xs_base32_dec(const xs_str *data, int *size);
  10. xs_val *xs_base32hex_dec(const xs_str *data, int *size);
  11. xs_str *xs_base64_enc(const xs_val *data, int sz);
  12. xs_val *xs_base64_dec(const xs_str *data, int *size);
  13. int xs_is_base64(const char *str);
  14. #ifdef XS_IMPLEMENTATION
  15. /** hex **/
  16. xs_str *xs_hex_enc(const xs_val *data, int size)
  17. /* returns an hexdump of data */
  18. {
  19. xs_str *s;
  20. char *p;
  21. int n;
  22. p = s = xs_realloc(NULL, _xs_blk_size(size * 2 + 1));
  23. for (n = 0; n < size; n++) {
  24. snprintf(p, 3, "%02x", (unsigned char)data[n]);
  25. p += 2;
  26. }
  27. *p = '\0';
  28. return s;
  29. }
  30. xs_val *xs_hex_dec(const xs_str *hex, int *size)
  31. /* decodes an hexdump into data */
  32. {
  33. int sz = strlen(hex);
  34. xs_val *s = NULL;
  35. char *p;
  36. int n;
  37. if (sz % 2)
  38. return NULL;
  39. p = s = xs_realloc(NULL, _xs_blk_size(sz / 2 + 1));
  40. for (n = 0; n < sz; n += 2) {
  41. int i;
  42. if (sscanf(&hex[n], "%02x", &i) == 0) {
  43. /* decoding error */
  44. return xs_free(s);
  45. }
  46. else
  47. *p = i;
  48. p++;
  49. }
  50. *p = '\0';
  51. *size = sz / 2;
  52. return s;
  53. }
  54. int xs_is_hex(const char *str)
  55. /* returns 1 if str is an hex string */
  56. {
  57. while (*str) {
  58. if (strchr("0123456789abcdefABCDEF", *str++) == NULL)
  59. return 0;
  60. }
  61. return 1;
  62. }
  63. /** base32 */
  64. static char *xs_b32_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  65. "234567=";
  66. static char *xs_b32hex_tbl = "0123456789"
  67. "ABCDEFGHIJKLMNOPQRSTUV=";
  68. /*
  69. 00000|00011|11111|12222|22223|33333|33444|44444
  70. */
  71. xs_str *xs_base32_enc_tbl(const xs_val *data, int sz, const char *b32_tbl)
  72. /* encodes data to base32 using a table */
  73. {
  74. xs_str *s = xs_str_new(NULL);
  75. unsigned char *p;
  76. int n;
  77. p = (unsigned char *)data;
  78. for (n = 0; n < sz; n += 5) {
  79. int l = sz - n;
  80. char enc[9] = "========";
  81. enc[0] = b32_tbl[(p[n] >> 3) & 0x1f];
  82. if (l > 1) {
  83. enc[1] = b32_tbl[(p[n] << 2 | p[n + 1] >> 6) & 0x1f];
  84. enc[2] = b32_tbl[(p[n + 1] >> 1) & 0x1f];
  85. if (l > 2) {
  86. enc[3] = b32_tbl[(p[n + 1] << 4 | p[n + 2] >> 4) & 0x1f];
  87. if (l > 3) {
  88. enc[4] = b32_tbl[(p[n + 2] << 1 | p[n + 3] >> 7) & 0x1f];
  89. enc[5] = b32_tbl[(p[n + 3] >> 2) & 0x1f];
  90. if (l > 4) {
  91. enc[6] = b32_tbl[(p[n + 3] << 3 | p[n + 4] >> 5) & 0x1f];
  92. enc[7] = b32_tbl[(p[n + 4]) & 0x1f];
  93. }
  94. else
  95. enc[6] = b32_tbl[(p[n + 3] << 3) & 0x1f];
  96. }
  97. else
  98. enc[4] = b32_tbl[(p[n + 2] << 1) & 0x1f];
  99. }
  100. else
  101. enc[3] = b32_tbl[(p[n + 1] << 4) & 0x1f];
  102. }
  103. else
  104. enc[1] = b32_tbl[(p[n] << 2) & 0x1f];
  105. s = xs_str_cat(s, enc);
  106. }
  107. return s;
  108. }
  109. xs_str *xs_base32_enc(const xs_val *data, int sz)
  110. /* encodes data to base32 */
  111. {
  112. return xs_base32_enc_tbl(data, sz, xs_b32_tbl);
  113. }
  114. xs_str *xs_base32hex_enc(const xs_val *data, int sz)
  115. /* encodes data to base32 with HEX alphabet (RFC4648) */
  116. {
  117. return xs_base32_enc_tbl(data, sz, xs_b32hex_tbl);
  118. }
  119. xs_val *xs_base32_dec_tbl(const xs_str *data, int *size, const char *b32_tbl)
  120. /* decodes data from base32 using a table */
  121. {
  122. xs_val *s = NULL;
  123. int sz = 0;
  124. char *p;
  125. p = (char *)data;
  126. /* size of data must be a multiple of 8 */
  127. if (strlen(p) % 8)
  128. return NULL;
  129. for (p = (char *)data; *p; p += 8) {
  130. int cs[8];
  131. int n;
  132. unsigned char tmp[5];
  133. for (n = 0; n < 8; n++) {
  134. char *ss = strchr(b32_tbl, p[n]);
  135. if (ss == NULL) {
  136. /* not a base32 char */
  137. return xs_free(s);
  138. }
  139. cs[n] = ss - b32_tbl;
  140. }
  141. n = 0;
  142. /* #0 byte */
  143. tmp[n++] = cs[0] << 3 | cs[1] >> 2;
  144. if (cs[2] != 32) {
  145. /* #1 byte */
  146. tmp[n++] = (cs[1] & 0x3) << 6 | cs[2] << 1 | (cs[3] & 0x10) >> 4;
  147. if (cs[4] != 32) {
  148. /* #2 byte */
  149. tmp[n++] = (cs[3] & 0xf) << 4 | cs[4] >> 1;
  150. if (cs[5] != 32) {
  151. /* #3 byte */
  152. tmp[n++] = (cs[4] & 0x1) << 7 | cs[5] << 2 | cs[6] >> 3;
  153. if (cs[7] != 32) {
  154. /* #4 byte */
  155. tmp[n++] = (cs[6] & 0x7) << 5 | cs[7];
  156. }
  157. }
  158. }
  159. }
  160. /* must be done manually because data can be pure binary */
  161. s = xs_realloc(s, _xs_blk_size(sz + n));
  162. memcpy(s + sz, tmp, n);
  163. sz += n;
  164. }
  165. /* asciiz it to use it as a string */
  166. s = xs_realloc(s, _xs_blk_size(sz + 1));
  167. s[sz] = '\0';
  168. *size = sz;
  169. return s;
  170. }
  171. xs_val *xs_base32_dec(const xs_str *data, int *size)
  172. /* decodes data from base32 */
  173. {
  174. return xs_base32_dec_tbl(data, size, xs_b32_tbl);
  175. }
  176. xs_val *xs_base32hex_dec(const xs_str *data, int *size)
  177. /* decodes data from base32 with HEX alphabet (RFC4648) */
  178. {
  179. return xs_base32_dec_tbl(data, size, xs_b32hex_tbl);
  180. }
  181. /** base64 */
  182. static char *xs_b64_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  183. "abcdefghijklmnopqrstuvwxyz"
  184. "0123456789+/=";
  185. xs_str *xs_base64_enc_tbl(const xs_val *data, int sz, const char *b64_tbl)
  186. /* encodes data to base64 using a table */
  187. {
  188. xs_str *s;
  189. unsigned char *p;
  190. char *i;
  191. int bsz, n;
  192. bsz = ((sz + 3 - 1) / 3) * 4;
  193. i = s = xs_realloc(NULL, _xs_blk_size(bsz + 1));
  194. p = (unsigned char *)data;
  195. for (n = 0; n < sz; n += 3) {
  196. int l = sz - n;
  197. if (l == 1) {
  198. *i++ = b64_tbl[(p[n] >> 2) & 0x3f];
  199. *i++ = b64_tbl[(p[n] << 4) & 0x3f];
  200. *i++ = '=';
  201. *i++ = '=';
  202. }
  203. else
  204. if (l == 2) {
  205. *i++ = b64_tbl[(p[n] >> 2) & 0x3f];
  206. *i++ = b64_tbl[(p[n] << 4 | p[n + 1] >> 4) & 0x3f];
  207. *i++ = b64_tbl[(p[n + 1] << 2) & 0x3f];
  208. *i++ = '=';
  209. }
  210. else {
  211. *i++ = b64_tbl[(p[n] >> 2) & 0x3f];
  212. *i++ = b64_tbl[(p[n] << 4 | p[n + 1] >> 4) & 0x3f];
  213. *i++ = b64_tbl[(p[n + 1] << 2 | p[n + 2] >> 6) & 0x3f];
  214. *i++ = b64_tbl[(p[n + 2]) & 0x3f];
  215. }
  216. }
  217. *i = '\0';
  218. return s;
  219. }
  220. xs_str *xs_base64_enc(const xs_val *data, int sz)
  221. /* encodes data to base64 */
  222. {
  223. return xs_base64_enc_tbl(data, sz, xs_b64_tbl);
  224. }
  225. xs_val *xs_base64_dec_tbl(const xs_str *data, int *size, const char *b64_tbl)
  226. /* decodes data from base64 using a table */
  227. {
  228. xs_val *s = NULL;
  229. int sz = 0;
  230. char *p;
  231. p = (char *)data;
  232. /* size of data must be a multiple of 4 */
  233. if (strlen(p) % 4)
  234. return NULL;
  235. for (p = (char *)data; *p; p += 4) {
  236. int cs[4];
  237. int n;
  238. unsigned char tmp[3];
  239. for (n = 0; n < 4; n++) {
  240. char *ss = strchr(b64_tbl, p[n]);
  241. if (ss == NULL) {
  242. /* not a base64 char */
  243. return xs_free(s);
  244. }
  245. cs[n] = ss - b64_tbl;
  246. }
  247. n = 0;
  248. /* first byte */
  249. tmp[n++] = cs[0] << 2 | ((cs[1] >> 4) & 0x0f);
  250. /* second byte */
  251. if (cs[2] != 64)
  252. tmp[n++] = cs[1] << 4 | ((cs[2] >> 2) & 0x3f);
  253. /* third byte */
  254. if (cs[3] != 64)
  255. tmp[n++] = cs[2] << 6 | (cs[3] & 0x3f);
  256. /* must be done manually because data can be pure binary */
  257. s = xs_realloc(s, _xs_blk_size(sz + n));
  258. memcpy(s + sz, tmp, n);
  259. sz += n;
  260. }
  261. /* asciiz it to use it as a string */
  262. s = xs_realloc(s, _xs_blk_size(sz + 1));
  263. s[sz] = '\0';
  264. *size = sz;
  265. return s;
  266. }
  267. xs_val *xs_base64_dec(const xs_str *data, int *size)
  268. /* decodes data from base64 */
  269. {
  270. return xs_base64_dec_tbl(data, size, xs_b64_tbl);
  271. }
  272. int xs_is_base64_tbl(const char *str, const char *b64_tbl)
  273. /* returns 1 if str is a base64 string, with table */
  274. {
  275. while (*str) {
  276. if (strchr(b64_tbl, *str++) == NULL)
  277. return 0;
  278. }
  279. return 1;
  280. }
  281. int xs_is_base64(const char *str)
  282. /* returns 1 if str is a base64 string */
  283. {
  284. return xs_is_base64_tbl(str, xs_b64_tbl);
  285. }
  286. #endif /* XS_IMPLEMENTATION */
  287. #endif /* _XS_ENCDEC_H */