Skip to content

Commit

Permalink
base64: Encoding/Decoding with URL and Filename Safe Alphabet (#471)
Browse files Browse the repository at this point in the history
sreimers authored Aug 25, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent f9c3559 commit 1cebc84
Showing 2 changed files with 77 additions and 9 deletions.
1 change: 1 addition & 0 deletions include/re_base64.h
Original file line number Diff line number Diff line change
@@ -6,5 +6,6 @@


int base64_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen);
int base64url_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen);
int base64_print(struct re_printf *pf, const uint8_t *ptr, size_t len);
int base64_decode(const char *in, size_t ilen, uint8_t *out, size_t *olen);
85 changes: 76 additions & 9 deletions src/base64/b64.c
Original file line number Diff line number Diff line change
@@ -13,6 +13,12 @@ static const char b64_table[65] =
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";

/* Base 64 Encoding with URL and Filename Safe Alphabet, RFC 4648 section 5 */
static const char b64url_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789-_";


/**
* Base-64 encode a buffer
@@ -53,10 +59,63 @@ int base64_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen)
++pad;
}

*out++ = b64_table[v>>18 & 0x3f];
*out++ = b64_table[v>>12 & 0x3f];
*out++ = (pad >= 2) ? '=' : b64_table[v>>6 & 0x3f];
*out++ = (pad >= 1) ? '=' : b64_table[v>>0 & 0x3f];
*out++ = b64_table[v >> 18 & 0x3f];
*out++ = b64_table[v >> 12 & 0x3f];
*out++ = (pad >= 2) ? '=' : b64_table[v >> 6 & 0x3f];
*out++ = (pad >= 1) ? '=' : b64_table[v >> 0 & 0x3f];
}

*olen = out - o;

return 0;
}


/**
* Base-64 url encode a buffer (without padding)
*
* @param in Input buffer
* @param ilen Length of input buffer
* @param out Output buffer
* @param olen Size of output buffer, actual written on return
*
* @return 0 if success, otherwise errorcode
*/
int base64url_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen)
{
const uint8_t *in_end = in + ilen;
const char *o = out;

if (!in || !out || !olen)
return EINVAL;

if (*olen < 4 * ((ilen+2)/3))
return EOVERFLOW;

for (; in < in_end; ) {
uint32_t v;
int pad = 0;

v = *in++ << 16;
if (in < in_end) {
v |= *in++ << 8;
}
else {
++pad;
}
if (in < in_end) {
v |= *in++ << 0;
}
else {
++pad;
}

*out++ = b64url_table[v >> 18 & 0x3f];
*out++ = b64url_table[v >> 12 & 0x3f];
if (pad < 2)
*out++ = b64url_table[v >> 6 & 0x3f];
if (pad < 1)
*out++ = b64url_table[v >> 0 & 0x3f];
}

*olen = out - o;
@@ -103,9 +162,9 @@ static inline uint32_t b64val(char c)
return c - 'a' + 26;
else if ('0' <= c && c <= '9')
return c - '0' + 52;
else if ('+' == c)
else if ('+' == c || '-' == c)
return 62;
else if ('/' == c)
else if ('/' == c || '_' == c)
return 63;
else if ('=' == c)
return 1<<24; /* special trick */
@@ -135,13 +194,21 @@ int base64_decode(const char *in, size_t ilen, uint8_t *out, size_t *olen)
if (*olen < 3 * (ilen/4))
return EOVERFLOW;

for (;in+3 < in_end; ) {
for (;in+1 < in_end; ) {
uint32_t v;

v = b64val(*in++) << 18;
v |= b64val(*in++) << 12;
v |= b64val(*in++) << 6;
v |= b64val(*in++) << 0;

if (in < in_end)
v |= b64val(*in++) << 6;
else
v |= (1<<24) << 6; /* padding fallback */

if (in < in_end)
v |= b64val(*in++) << 0;
else
v |= (1<<24) << 0; /* padding fallback */

*out++ = v>>16;
if (!(v & (1<<30)))

0 comments on commit 1cebc84

Please sign in to comment.