changeset 740:12be3c54727b

base64: add base64url encoder/decoder Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sun, 31 Mar 2019 15:03:58 +0300
parents c70b925f6484
children 7a839d21735a
files base64.c include/jeffpc/base64.h mapfile-vers tests/CMakeLists.txt tests/base64/valid/1kB-random.b64url tests/base64/valid/a.b64url tests/base64/valid/ab.b64url tests/base64/valid/abc.b64url tests/base64/valid/abcd.b64url tests/base64/valid/abcde.b64url tests/base64/valid/abcdef.b64url tests/base64/valid/abcdefg.b64url tests/base64/valid/empty.b64url tests/base64/valid/f.b64url tests/base64/valid/ff.b64url tests/base64/valid/fo.b64url tests/base64/valid/foo.b64url tests/base64/valid/foob.b64url tests/base64/valid/fooba.b64url tests/base64/valid/foobar.b64url tests/base64/valid/nul.b64url tests/test_base64_decode.c tests/test_base64_encode.c
diffstat 23 files changed, 89 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/base64.c	Sun Mar 31 14:53:30 2019 +0300
+++ b/base64.c	Sun Mar 31 15:03:58 2019 +0300
@@ -27,6 +27,11 @@
 	"abcdefghijklmnopqrstuvwxyz"
 	"0123456789+/";
 
+static const char b64url_encode_table[64] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	"abcdefghijklmnopqrstuvwxyz"
+	"0123456789-_";
+
 #define INV	0xff
 static const uint8_t b64_decode_table[256] = {
 	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x00..0x07 */
@@ -63,6 +68,41 @@
 	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xf8..0xff */
 };
 
+static const uint8_t b64url_decode_table[256] = {
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x00..0x07 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x08..0x0f */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x10..0x17 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x18..0x1f */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x20..0x27 */
+	 INV,  INV,  INV,  INV,  INV, 0x3e,  INV,  INV, /* 0x28..0x2f */
+	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, /* 0x30..0x37 */
+	0x3c, 0x3d,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x38..0x3f */
+	 INV, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* 0x40..0x47 */
+	0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /* 0x48..0x4f */
+	0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* 0x50..0x57 */
+	0x17, 0x18, 0x19,  INV,  INV,  INV,  INV, 0x3f, /* 0x58..0x5f */
+	 INV, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, /* 0x60..0x67 */
+	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /* 0x68..0x6f */
+	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, /* 0x70..0x77 */
+	0x31, 0x32, 0x33,  INV,  INV,  INV,  INV,  INV, /* 0x78..0x7f */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x80..0x87 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x88..0x8f */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x90..0x97 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0x98..0x9f */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xa0..0xa7 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xa8..0xaf */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xb0..0xb7 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xb8..0xbf */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xc0..0xc7 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xc8..0xcf */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xd0..0xd7 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xd8..0xdf */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xe0..0xe7 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xe8..0xef */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xf0..0xf7 */
+	 INV,  INV,  INV,  INV,  INV,  INV,  INV,  INV, /* 0xf8..0xff */
+};
+
 __attribute__((always_inline))
 static inline void __b64_encode(char *out, const void *_in, size_t inlen,
 				const char *table)
@@ -120,6 +160,11 @@
 	__b64_encode(out, in, inlen, b64_encode_table);
 }
 
+void base64url_encode(char *out, const void *in, size_t inlen)
+{
+	__b64_encode(out, in, inlen, b64url_encode_table);
+}
+
 __attribute__((always_inline))
 static inline ssize_t __b64_decode(void *_out, const char *_in, size_t inlen,
 				   const uint8_t *table)
@@ -193,3 +238,8 @@
 {
 	return __b64_decode(out, in, inlen, b64_decode_table);
 }
+
+ssize_t base64url_decode(void *out, const char *in, size_t inlen)
+{
+	return __b64_decode(out, in, inlen, b64url_decode_table);
+}
--- a/include/jeffpc/base64.h	Sun Mar 31 14:53:30 2019 +0300
+++ b/include/jeffpc/base64.h	Sun Mar 31 15:03:58 2019 +0300
@@ -30,6 +30,9 @@
 extern ssize_t base64_decode(void *out, const char *in, size_t inlen);
 extern void base64_encode(char *out, const void *in, size_t inlen);
 
+extern ssize_t base64url_decode(void *out, const char *in, size_t inlen);
+extern void base64url_encode(char *out, const void *in, size_t inlen);
+
 /* returns number of bytes needed to encode an input of @inlen bytes */
 static inline size_t base64_required_length(size_t inlen)
 {
--- a/mapfile-vers	Sun Mar 31 14:53:30 2019 +0300
+++ b/mapfile-vers	Sun Mar 31 15:03:58 2019 +0300
@@ -31,6 +31,8 @@
 		# base64
 		base64_decode;
 		base64_encode;
+		base64url_decode;
+		base64url_encode;
 
 		# bst
 		bst_add;
--- a/tests/CMakeLists.txt	Sun Mar 31 14:53:30 2019 +0300
+++ b/tests/CMakeLists.txt	Sun Mar 31 15:03:58 2019 +0300
@@ -22,8 +22,8 @@
 
 build_perf_bin(tree)
 
-build_test_bin_and_run_files(base64_encode raw b64 base64/valid)
-build_test_bin_and_run_files(base64_decode b64 raw base64/valid)
+build_test_bin_and_run_files(base64_encode raw "b64;b64url" base64/valid)
+build_test_bin_and_run_files(base64_decode "b64;b64url" raw base64/valid)
 build_test_bin_and_run_files(cbor_pack lisp cbor cbor-common/valid)
 build_test_bin_and_run_files(cbor_unpack cbor lisp
 	"cbor-common/valid;cbor-common/valid-unpack")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/1kB-random.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+3sgHmxdfbKlVGHyuC2T8qY_ZTNkVnc8tYlGs5WqS1PnVt4pUUsZzeulRCj2KVNNt6oI85FxRfFgZgJ0eyHSADyivtjRY4a8HbiolJ7oBlETXpMIjthCbUo4j89cPnLvcYmqYcBF0diuRji9_aeYujCAQTzRnoccelM6CyrrkIjjG9QhPEidC5LDmPClWn34FIIO7Us2cjW1FWjQG_NGUPoaSKsFhu2wEM9cLM9jI9-e8PldQhnfUFplPShKAVPzj-v2NvN695icjVAti4-g1T-MNfZPge1PVm_by71SUjho4OrdpSt-Zpbw9ZVxUDG8NzmmAjVk0Of2nieYeLaANHihUM5dl2QAg9cxXkLyIBHuBCgyU-cVTU82ld-RpV7n0Q-nWUtd4lVqm6Tzxcv5UDzRHx3lp7QhFgvLWlK3bd6edMJbKZHDXfPFuOWzmEDxqgu5NtePoFAW3OgbZ_OyuONeUphBqlyevdwIVAZ_B2D1_hkZ665m_CPJ8GJ9f3FUR_vyGIkmTQm2m9w-AQOL776uWch_untbh8_2miKuZ1MYzBgWUtmAk_sGJTm58o2Ss00cnAVPwYliyrhnDqspuHd2dg_lQv9GciUcrVSxnRxQCG8usLZLkXPEKv-rBNC04WFRt89WTVPMSU0qXz9xuCrhrfgykcmcTzSx8YESDGVfoCucMQ-HfPqoKSqXXSsycBSg5XAMwA8S8cOFNIUiRQr4cwxi00GvWpvyP995CEZNpCDgh14h5zfAzFZYrXqDD_yX39Rag6ulcMuXaqt3M2DzsbzLCURXL9LIZBLISgWg94ryE0rr5zCwRxx6X7vWltWWQjFJs382l5wyX2JNxXgRHxbwCka5NPAwCmbDRz47RDAcVsEyyQO_p6-JoUgVZwX44rEYQRh5PYzzUGMN9or8W3hL31j9GAd346o2VWXifFH4JH3ZPKH7A_th3s5pV3qRCIN50Do8w-TerlmFkErXAo2tfxc7ksS6aWeNV875_aIrrBGJUulftPoaXw9gGcyh1wCHv4olKA4eAT3_EfFR6fXQiIAkRvyllRVky2BaLmKmoMI4yCHYoNaPFh-QJJqA8PMSEmw1P-P6eUP-hnhHEzKHDSd3fOEiIUKid62-q4P9wHJOO3_lU_iZ-n2s9yEx6qwV3cCnnbsYZ-pGPvkR8Y3VgOM6iwV23S0J5NRVSXo5VP3u4W89EU6Zqbam31ycJl9I2FcA1efTpms7G14G1kKhINj48siCKczSHhAbUrgcjpbhkxkJ9DbOBJk7SkPMK1LfaPFfxQWXa7ovPqVvTpTcDIynl50RTcli4uXUriLXuY_SrXGIAD57XjEVHE5j2QAKffPlh2cEldo6rEw==
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/a.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+a.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/ab.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+ab.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/abc.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+abc.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/abcd.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+abcd.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/abcde.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+abcde.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/abcdef.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+abcdef.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/abcdefg.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+abcdefg.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/empty.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+empty.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/f.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+f.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/ff.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+_w==
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/fo.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+fo.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/foo.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+foo.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/foob.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+foob.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/fooba.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+fooba.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/foobar.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+foobar.b64
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/base64/valid/nul.b64url	Sun Mar 31 15:03:58 2019 +0300
@@ -0,0 +1,1 @@
+nul.b64
\ No newline at end of file
--- a/tests/test_base64_decode.c	Sun Mar 31 14:53:30 2019 +0300
+++ b/tests/test_base64_decode.c	Sun Mar 31 15:03:58 2019 +0300
@@ -35,7 +35,8 @@
 	fprintf(stderr, "%s", tmp);
 }
 
-static void check(const void *raw, size_t rawlen, const char *b64, size_t b64len)
+static void check(const void *raw, size_t rawlen, const char *b64, size_t b64len,
+		  bool url)
 {
 	/* +10 as a redzone to catch out of bounds writes */
 	uint8_t out[rawlen + 10];
@@ -48,7 +49,11 @@
 	dumpraw(raw, rawlen);
 	fprintf(stderr, "\n");
 
-	ret = base64_decode(out, b64, b64len);
+	if (!url)
+		ret = base64_decode(out, b64, b64len);
+	else
+		ret = base64url_decode(out, b64, b64len);
+
 	if (ret < 0)
 		fail("failed to decode");
 
@@ -66,5 +71,5 @@
 void test(const char *ifname, void *in, size_t ilen, const char *iext,
 	  const char *ofname, void *out, size_t olen, const char *oext)
 {
-	check(out, olen, in, ilen);
+	check(out, olen, in, ilen, !strcmp(iext, "b64url"));
 }
--- a/tests/test_base64_encode.c	Sun Mar 31 14:53:30 2019 +0300
+++ b/tests/test_base64_encode.c	Sun Mar 31 15:03:58 2019 +0300
@@ -35,7 +35,8 @@
 	fprintf(stderr, "%s", tmp);
 }
 
-static void check(const void *raw, size_t rawlen, const char *b64, size_t b64len)
+static void check(const void *raw, size_t rawlen, const char *b64, size_t b64len,
+		  bool url)
 {
 	/* +1 for \0, +10 as a redzone to catch out of bounds writes */
 	char out[b64len + 1 + 10];
@@ -47,7 +48,10 @@
 	fprintf(stderr, "\n");
 	fprintf(stderr, "exp: '%s'\n", b64);
 
-	base64_encode(out, raw, rawlen);
+	if (!url)
+		base64_encode(out, raw, rawlen);
+	else
+		base64url_encode(out, raw, rawlen);
 
 	fprintf(stderr, "got: '%s'\n", out);
 
@@ -58,5 +62,5 @@
 void test(const char *ifname, void *in, size_t ilen, const char *iext,
 	  const char *ofname, void *out, size_t olen, const char *oext)
 {
-	check(in, ilen, out, olen);
+	check(in, ilen, out, olen, !strcmp(oext, "b64url"));
 }