From 9c3ccc182ef2eca08657ff2dc5bf0551c4ba26f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 19 Jul 2019 14:19:42 +0200 Subject: [PATCH] base64: implement encode() --- base64.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- base64.h | 5 ++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/base64.c b/base64.c index 1ea8e9c7..7e0ec0a1 100644 --- a/base64.c +++ b/base64.c @@ -4,6 +4,7 @@ #include #include #include +#include #define LOG_MODULE "base64" #define LOG_ENABLE_DBG 0 @@ -26,7 +27,6 @@ static const uint8_t reverse_lookup[256] = { ['+'] = 62, ['/'] = 63, }; -#if 0 static const char lookup[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', @@ -35,7 +35,6 @@ static const char lookup[64] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', }; -#endif static inline bool is_valid(char c) @@ -86,3 +85,70 @@ base64_decode(const char *s) ret[len / 4 * 3] = '\0'; return ret; } + +char * +base64_encode(const uint8_t *data, size_t size) +{ + assert(size % 3 == 0); + if (size %3 != 0) + return NULL; + + char *ret = malloc(size / 3 * 4 + 1); + + for (size_t i = 0, o = 0; i < size; i += 3, o += 4) { + int x = data[i + 0]; + int y = data[i + 1]; + int z = data[i + 2]; + + uint32_t v = x << 16 | y << 8 | z << 0; + + unsigned a = (v >> 18) & 0x3f; + unsigned b = (v >> 12) & 0x3f; + unsigned c = (v >> 6) & 0x3f; + unsigned d = (v >> 0) & 0x3f; + + char c0 = lookup[a]; + char c1 = lookup[b]; + char c2 = lookup[c]; + char c3 = lookup[d]; + + ret[o + 0] = c0; + ret[o + 1] = c1; + ret[o + 2] = c2; + ret[o + 3] = c3; + + LOG_DBG("base64: encode: %c%c%c%c", c0, c1, c2, c3); + } + + ret[size / 3 * 4] = '\0'; + return ret; +} + +void +base64_encode_final(const uint8_t *data, size_t size, char result[4]) +{ + assert(size > 0); + assert(size < 3); + + uint32_t v = 0; + if (size >= 1) + v |= data[0] << 16; + if (size >= 2) + v |= data[1] << 8; + + unsigned a = (v >> 18) & 0x3f; + unsigned b = (v >> 12) & 0x3f; + unsigned c = (v >> 6) & 0x3f; + + char c0 = lookup[a]; + char c1 = lookup[b]; + char c2 = size == 2 ? lookup[c] : '='; + char c3 = '='; + + result[0] = c0; + result[1] = c1; + result[2] = c2; + result[3] = c3; + + LOG_DBG("base64: encode: %c%c%c%c", c0, c1, c2, c3); +} diff --git a/base64.h b/base64.h index e7a3613b..d4042512 100644 --- a/base64.h +++ b/base64.h @@ -1,3 +1,8 @@ #pragma once +#include +#include + char *base64_decode(const char *s); +char *base64_encode(const uint8_t *data, size_t size); +void base64_encode_final(const uint8_t *data, size_t size, char result[4]);