From 0c958326c6051f012be39c214827776b74702864 Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Thu, 16 Apr 2026 23:44:52 +0200 Subject: [PATCH] adding base64 decoding --- .gitignore | 1 + Changelog | 8 ++++ Makefile | 9 ++-- UDPTCPNetwork.h | 3 ++ ssl.cc | 108 ++++++++++++++++++++++++++++++++++++++++++++++++ test-base64.cc | 43 +++++++++++++++++++ 6 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 test-base64.cc diff --git a/.gitignore b/.gitignore index a19ceb6..d10610d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ fbconfig.config *.so.* *.so test-getrandom +test-base64 test-webserver test-json test-ssl diff --git a/Changelog b/Changelog index f31ac68..0a84c77 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,11 @@ +Version 0.4: +============= +2026-04-16: +- base64encode and base64decode implemented + +Version 0.3: +============= + 2026-04-15: - getrandomtext did not init with a good seed value. using the sample from the linux man pages. diff --git a/Makefile b/Makefile index 2b6b200..cda85ea 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ .SILENT: help -VERSION=0.3 +VERSION=0.4 OBJLIB_NAME=UDPTCPNetwork -include Makefile.rules @@ -8,7 +8,7 @@ DEFAULT_TCPPORT=6131 DEFAULT_UDPPORT=6131 DEFAULT_SERVER=localhost -CFLAGS=-I./ +CFLAGS=-I./ -ggdb OBJLIB=network.o udp.o tcp.o unix.o ssl.o json.o webutils.o webserver.o INCLIB=UDPTCPNetwork.h UDPTCPNetwork-json.h UDPTCPNetwork-webutils.h DISTNAME=libUDPTCPNetwork-$(VERSION) @@ -18,7 +18,7 @@ noconfig: help endif -all: dep $(TARGET) test-udp test-tcpserver test-tcpclient test-ssl test-json test-webserver test-getrandom +all: dep $(TARGET) test-udp test-tcpserver test-tcpclient test-ssl test-json test-webserver test-getrandom test-base64 -include .depend @@ -37,6 +37,9 @@ configwindows: clean test-webserver: $(TARGET) test-webserver.o $(CXX) test-webserver.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS) +test-base64: $(TARGET) test-base64.o + $(CXX) test-base64.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS) + test-getrandom: $(TARGET) test-getrandom.o $(CXX) test-getrandom.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS) diff --git a/UDPTCPNetwork.h b/UDPTCPNetwork.h index 9283c26..351743f 100644 --- a/UDPTCPNetwork.h +++ b/UDPTCPNetwork.h @@ -199,6 +199,9 @@ public: std::string getsha256sum(std::string *in); std::string getrandomtext(int numbytes); +int base64encode(char *ibuffer, int ilen, std::string *output, int urlsafe); +int base64decode(std::string input, char **obuffer, int *olen); + /************************************************************************ * unix socket related functions diff --git a/ssl.cc b/ssl.cc index 3082a65..d81bb67 100644 --- a/ssl.cc +++ b/ssl.cc @@ -388,3 +388,111 @@ std::string getrandomtext(int numbytes) { return text; }; + +// 1 2 3 4 5 6 +// 0123456789012345678901234567890123456789012345678901234567890123 +static char base64table1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static char base64table2[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +int base64encode(char *ibuffer, int ilen, std::string *output, int urlsafe) { + int icnt; // input pos + char c1, c2; // two bytes + int idx; + + *output = ""; + + for (c1 = 0, c2 = 0, icnt = 0; icnt < ilen; icnt++) { + // byte 0 + c1 = ibuffer[icnt]; + idx = c1 >> 2; + *output += (urlsafe ? base64table2[idx] : base64table1[idx]); + + // byte 1 + if (++icnt >= ilen) break; + c2 = ibuffer[icnt]; + idx = (c1 & 0x03) << 4 | (c2 >> 4); + *output += (urlsafe ? base64table2[idx] : base64table1[idx]); + + // byte 2 + if (++icnt >= ilen) break; + c1 = ibuffer[icnt]; + idx = (c2 & 0x07) << 2 | (c1 & 0xC0) >> 6; + *output += (urlsafe ? base64table2[idx] : base64table1[idx]); + idx = c1 & 0x3F; + *output += (urlsafe ? base64table2[idx] : base64table1[idx]); + } + + switch (icnt % 3) { + case 0: + break; + case 1: + idx = (c1 & 0x03) << 4; + *output += (urlsafe ? base64table2[idx] : base64table1[idx]); + *output += '='; + *output += '='; + break; + case 2: + idx = (c2 & 0x07) << 2; + *output += (urlsafe ? base64table2[idx] : base64table1[idx]); + *output += '='; + break; + } + + return 1; +}; + + +int _base64getidx(char c) { + char *p; + + if (c == '=') return 0; + p = strchr (base64table1, c); + if (p != NULL) return p-base64table1; + p = strchr (base64table2, c); + if (p != NULL) return p-base64table2; + + return -1; +}; + +int base64decode(std::string input, char **obuffer, int *olen) { + int ocnt; + int icnt; + int v1, v2; + int ilen = input.length(); + char c; + + // calculate and realloc size of buffer + if (*obuffer == NULL || (1 + ilen*3/4) < *olen) { + *olen = 1 + ilen*3/4; + *obuffer = (char*) realloc(*obuffer, *olen); + } + + for (v1 = 0, v2 = 0, ocnt = 0, icnt = 0; icnt < ilen && ocnt < *olen; icnt++) { + // read byte 1 + v1 = _base64getidx(input[icnt]); + if (++icnt >= ilen || v1 == -1) return 0; + v2 = _base64getidx(input[icnt]); + if (v2 == -1) return 0; + c = ((v1 << 2) | ((v2 & 0x30) >> 4)) & 0xFF; + (*obuffer)[ocnt++] = c; + + // read byte 2 + if (++icnt >= ilen) return 0; + if (input[icnt] == '=') break; + v1 = _base64getidx(input[icnt]); + if (v1 == -1) return 0; + c = ((v2 & 0x07) << 4 | (v1 & 0x3C) >> 2) & 0xFF; + (*obuffer)[ocnt++] = c; + + // read byte 3 + if (++icnt >= ilen) return 0; + if (input[icnt] == '=') break; + v2 = _base64getidx(input[icnt]); + if (v2 == -1) return 0; + c = ((v1 & 0x03) << 6| (v2 & 0x3F)) & 0xFF; + (*obuffer)[ocnt++] = c; + } + *olen = ocnt; + return 1; +}; + diff --git a/test-base64.cc b/test-base64.cc new file mode 100644 index 0000000..2efc548 --- /dev/null +++ b/test-base64.cc @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "UDPTCPNetwork.h" + +int main(int argc, char **argv) { + std::string encoded = "TnVyIGVpbiBUZXN0Pw=="; + std::string text = "Nur ein Test?"; + + std::string temp; + int result, i; + char *buffer = (char*) malloc(256); + int bufferlen = 256; + + // + // test decoding + if (base64decode(encoded, &buffer, &bufferlen) == 0) + debug ("************* error on base64decode"); + else { + if (bufferlen+1 < 256) { + buffer[bufferlen] = 0; + debug (" decode: %s (%d bytes)", buffer, bufferlen); + } + for (i=0, result = 1; result && i < bufferlen && i < text.length(); i++) + if (buffer[i] != text[i]) result = 0; + + debug ("base64decode ----------------------------> %s", (result == 1 ? "OK" : "FAILED")); + } + + // + // test encode + if (base64encode((char *)text.c_str(), strlen(text.c_str()), &temp, 0) == 0) + debug ("************* error on base64decode"); + else { + debug (" encode: %s", temp.c_str()); + debug (" : %s", encoded.c_str()); + debug ("base64encode ----------------------------> %s", (encoded.compare(temp) == 0) ? "OK" : "FAILED"); + } + + return 0; +}; +