Skip to content

Commit

Permalink
refactor: replace libb64 with custom base64 implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Oct 27, 2023
1 parent 0451caa commit 010e301
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ RUN apt-get update && \
libboost-filesystem1.81-dev libssl-dev libc-ares-dev zlib1g-dev \
ca-certificates automake libtool patchelf cmake pkg-config lua5.4 liblua5.4-dev \
libgrpc++-dev libprotobuf-dev protobuf-compiler-grpc \
luarocks libb64-dev libcrypto++-dev nlohmann-json3-dev && \
luarocks libcrypto++-dev nlohmann-json3-dev && \
update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-15 120 && \
update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-15 120 && \
rm -rf /var/lib/apt/lists/*
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ Docker targets:
- Cryptopp >= 7.0.0
- GRPC >= 1.45.0
- Lua >= 5.4.4
- b64 >= 1.2.1
- Boost >= 1.81
- nlohmann JSON >= 3.10

Expand All @@ -38,7 +37,7 @@ apt-get install build-essential wget git clang-tidy-15 clang-format-15 \
libboost-filesystem1.81-dev libssl-dev libc-ares-dev zlib1g-dev \
ca-certificates automake libtool patchelf cmake pkg-config lua5.4 liblua5.4-dev \
libgrpc++-dev libprotobuf-dev protobuf-compiler-grpc \
luarocks libb64-dev libcrypto++-dev nlohmann-json3-dev
luarocks libcrypto++-dev nlohmann-json3-dev
sudo luarocks install --lua-version=5.4 lpeg
sudo luarocks install --lua-version=5.4 dkjson
Expand All @@ -50,7 +49,7 @@ sudo luarocks install --lua-version=5.4 luaposix

##### MacPorts
```
sudo port install clang-15 automake boost libtool wget cmake pkgconfig grpc zlib openssl lua libb64 libcryptopp nlohmann-json lua-luarocks
sudo port install clang-15 automake boost libtool wget cmake pkgconfig grpc zlib openssl lua libcryptopp nlohmann-json lua-luarocks
sudo luarocks install --lua-version=5.4 lpeg
sudo luarocks install --lua-version=5.4 dkjson
Expand All @@ -61,7 +60,7 @@ sudo luarocks install --lua-version=5.4 luaposix

##### Homebrew
```
brew install llvm@15 automake boost libomp wget cmake cryptopp pkg-config grpc zlib openssl [email protected] libb64 nlohmann-json luarocks
brew install llvm@15 automake boost libomp wget cmake cryptopp pkg-config grpc zlib openssl [email protected] nlohmann-json luarocks
luarocks --lua-dir=$(brew --prefix)/opt/[email protected] install lpeg
luarocks --lua-dir=$(brew --prefix)/opt/[email protected] install dkjson
luarocks --lua-dir=$(brew --prefix)/opt/[email protected] install luasocket
Expand Down
20 changes: 6 additions & 14 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ BOOST_INC_Darwin=-I$(BREW_PREFIX)/include
CRYPTOPP_LIB_Darwin:=-L$(BREW_PREFIX)/lib -lcryptopp
CRYPTOPP_INC_Darwin:=-I$(BREW_PREFIX)/include
NLOHMANN_JSON_INC_Darwin:=-I$(BREW_PREFIX)/include
B64_LIB_Darwin:=-L$(BREW_PREFIX)/lib -lb64
B64_INC_Darwin:=-I$(BREW_PREFIX)/include
GRPC_INC_Darwin:=$(shell pkg-config --cflags-only-I grpc++)
GRPC_LIB_Darwin:=$(shell pkg-config --libs grpc++)
PROTOBUF_INC_Darwin:=$(shell pkg-config --cflags-only-I protobuf)
Expand All @@ -81,8 +79,6 @@ BOOST_LIB_DIR_Darwin=-L$(PORT_PREFIX)/libexec/boost/1.81/lib
BOOST_INC_Darwin=-I$(PORT_PREFIX)/libexec/boost/1.81/include
CRYPTOPP_LIB_Darwin:=-L$(PORT_PREFIX)/lib -lcryptopp
CRYPTOPP_INC_Darwin:=-I$(PORT_PREFIX)/include
B64_LIB_Darwin:=-L$(PORT_PREFIX)/lib -lb64
B64_INC_Darwin:=-I$(PORT_PREFIX)/include
GRPC_INC_Darwin:=-I$(PORT_PREFIX)/include
GRPC_LIB_Darwin=-L$(PORT_PREFIX)/lib -lgrpc++ -lgrpc -lgpr -lprotobuf -lpthread -labsl_synchronization
PROTOBUF_INC_Darwin:=-I$(PORT_PREFIX)/include
Expand Down Expand Up @@ -115,8 +111,6 @@ FS_LIB_Linux=-lstdc++fs
BOOST_FILESYSTEM_LIB_Linux:=-lboost_system -lboost_filesystem
BOOST_PROCESS_LIB_Linux:=-lpthread
BOOST_INC_Linux=
B64_LIB_Linux:=-lb64
B64_INC_Linux:=
CRYPTOPP_LIB_Linux:=-lcryptopp
CRYPTOPP_INC_Linux:=
GRPC_INC_Linux:=$(shell pkg-config --cflags-only-I grpc++)
Expand All @@ -141,8 +135,6 @@ SOLDFLAGS:=$(SOLDFLAGS_$(UNAME)) $(GCLDFLAGS)
BOOST_PROCESS_LIB=$(BOOST_PROCESS_LIB_$(UNAME))
BOOST_FILESYSTEM_LIB=$(BOOST_FILESYSTEM_LIB_$(UNAME))
BOOST_INC=$(BOOST_INC_$(UNAME))
B64_LIB=$(B64_LIB_$(UNAME))
B64_INC=$(B64_INC_$(UNAME))
CRYPTOPP_LIB=$(CRYPTOPP_LIB_$(UNAME))
CRYPTOPP_INC=$(CRYPTOPP_INC_$(UNAME))
NLOHMANN_JSON_INC=$(NLOHMANN_JSON_INC_$(UNAME))
Expand All @@ -162,14 +154,14 @@ LIBCARTESI_GRPC_LDFLAGS=$(LIBCARTESI_GRPC_LDFLAGS_$(UNAME))
LIBCARTESI_GRPC_TESTS_LDFLAGS=$(LIBCARTESI_GRPC_TESTS_LDFLAGS_$(UNAME))
LIBCARTESI_GRPC_LIB=-L. -lcartesi_grpc-$(EMULATOR_VERSION_MAJOR).$(EMULATOR_VERSION_MINOR)

LIBCARTESI_LIBS:=$(CRYPTOPP_LIB) $(B64_LIB)
LIBCARTESI_LIBS:=$(CRYPTOPP_LIB)
LIBCARTESI_GRPC_LIBS:=$(CRYPTOPP_LIB) $(GRPC_LIB) $(PROTOBUF_LIB)
LUACARTESI_LIBS:=$(LIBCARTESI_LIB) $(CRYPTOPP_LIB)
LUACARTESI_GRPC_LIBS:=$(LIBCARTESI_LIB) $(CRYPTOPP_LIB) $(LIBCARTESI_GRPC_LIB)
LUACARTESI_JSONRPC_LIBS:=$(LIBCARTESI_LIB) $(CRYPTOPP_LIB) $(B64_LIB)
REMOTE_CARTESI_MACHINE_LIBS:=$(CRYPTOPP_LIB) $(GRPC_LIB) $(PROTOBUF_LIB) $(B64_LIB)
JSONRPC_REMOTE_CARTESI_MACHINE_LIBS:=$(CRYPTOPP_LIB) $(B64_LIB)
TEST_MACHINE_C_API_LIBS:=$(LIBCARTESI_LIB) $(CRYPTOPP_LIB) $(LIBCARTESI_GRPC_LIB) $(BOOST_PROCESS_LIB) $(BOOST_FILESYSTEM_LIB) $(B64_LIB)
LUACARTESI_JSONRPC_LIBS:=$(LIBCARTESI_LIB) $(CRYPTOPP_LIB)
REMOTE_CARTESI_MACHINE_LIBS:=$(CRYPTOPP_LIB) $(GRPC_LIB) $(PROTOBUF_LIB)
JSONRPC_REMOTE_CARTESI_MACHINE_LIBS:=$(CRYPTOPP_LIB)
TEST_MACHINE_C_API_LIBS:=$(LIBCARTESI_LIB) $(CRYPTOPP_LIB) $(LIBCARTESI_GRPC_LIB) $(BOOST_PROCESS_LIB) $(BOOST_FILESYSTEM_LIB)
HASH_LIBS:=$(CRYPTOPP_LIB)

#DEFS+= -DMT_ALL_DIRTY
Expand All @@ -178,7 +170,7 @@ WARNS=-W -Wall -pedantic

# Place our include directories before the system's
INCS=-I../lib/machine-emulator-defines -I../third-party/llvm-flang-uint128 \
$(LUA_INC) $(CRYPTOPP_INC) $(NLOHMANN_JSON_INC) $(MONGOOSE_INC) $(B64_INC) $(BOOST_INC) $(PROTOBUF_INC) $(GRPC_INC) $(INCS_$(UNAME))
$(LUA_INC) $(CRYPTOPP_INC) $(NLOHMANN_JSON_INC) $(MONGOOSE_INC) $(BOOST_INC) $(PROTOBUF_INC) $(GRPC_INC) $(INCS_$(UNAME))

ifeq ($(dump),yes)
#DEFS+=-DDUMP_ILLEGAL_INSN_EXCEPTIONS
Expand Down
148 changes: 132 additions & 16 deletions src/base64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,152 @@
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#include <cstdint>
#include <sstream>

#ifndef BUFFERSIZE
// To fulfill libb64's assumption that the macro BUFFERSIZE is always defined. It is not.
// bug https://sourceforge.net/p/libb64/bugs/3/
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define BUFFERSIZE 1024
#endif
#include "base64.h"

#include <b64/decode.h>
namespace cartesi {

#include <b64/encode.h>
// Base64 globals
static constexpr uint8_t b64base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

#include "base64.h"
static constexpr uint8_t b64unbase[] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 0, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255,
255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};

namespace cartesi {
// Acumulates bytes in input buffer until 3 bytes are available.
// Translate the 3 bytes into Base64 form and append to buffer.
// Returns new number of bytes in buffer.
static size_t b64encode(uint8_t c, uint8_t *input, size_t size, std::ostringstream &sout) {
input[size++] = c;
if (size == 3) {
uint8_t code[4];
unsigned long value = 0;
value += input[0];
value <<= 8;
value += input[1];
value <<= 8;
value += input[2];
code[3] = b64base[value & 0x3f];
value >>= 6;
code[2] = b64base[value & 0x3f];
value >>= 6;
code[1] = b64base[value & 0x3f];
value >>= 6;
code[0] = b64base[value];
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
sout << std::string_view(reinterpret_cast<char *>(code), 4);
size = 0;
}
return size;
}

// Encodes the Base64 last 1 or 2 bytes and adds padding '='
// Result, if any, is appended to buffer.
// Returns 0.
static size_t b64pad(const uint8_t *input, size_t size, std::ostringstream &sout) {
unsigned long value = 0;
uint8_t code[4] = {'=', '=', '=', '='};
switch (size) {
case 1:
value = input[0] << 4;
code[1] = b64base[value & 0x3f];
value >>= 6;
code[0] = b64base[value];
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
sout << std::string_view(reinterpret_cast<char *>(code), 4);
break;
case 2:
value = input[0];
value <<= 8;
value |= input[1];
value <<= 2;
code[2] = b64base[value & 0x3f];
value >>= 6;
code[1] = b64base[value & 0x3f];
value >>= 6;
code[0] = b64base[value];
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
sout << std::string_view(reinterpret_cast<char *>(code), 4);
break;
default:
break;
}
return 0;
}

// Acumulates bytes in input buffer until 4 bytes are available.
// Translate the 4 bytes from Base64 form and append to buffer.
// Returns new number of bytes in buffer.
static size_t b64decode(uint8_t c, uint8_t *input, size_t size, std::ostringstream &sout) {
// ignore invalid characters
if (b64unbase[c] > 64) {
return size;
}
input[size++] = c;
// decode atom
if (size == 4) {
uint8_t decoded[3];
int valid = 0;
int value = 0;
value = b64unbase[input[0]];
value <<= 6;
value |= b64unbase[input[1]];
value <<= 6;
value |= b64unbase[input[2]];
value <<= 6;
value |= b64unbase[input[3]];
decoded[2] = static_cast<uint8_t>(value & 0xff);
value >>= 8;
decoded[1] = static_cast<uint8_t>(value & 0xff);
value >>= 8;
decoded[0] = static_cast<uint8_t>(value);
// take care of paddding
valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3;
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
sout << std::string_view(reinterpret_cast<char *>(decoded), valid);
return 0;
// need more data
} else {
return size;
}
}

std::string encode_base64(const std::string &input) {
std::istringstream sin(input);
std::ostringstream sout;
base64::encoder E; // NOLINT(clang-analyzer-optin.cplusplus.UninitializedObject)
E.encode(sin, sout);
uint8_t ctx[4]{};
size_t ctxlen = 0;
size_t ncols = 0;
for (const char b : input) {
ctxlen = b64encode(static_cast<uint8_t>(b), ctx, ctxlen, sout);
if (ctxlen == 0) { // appended 4 characters
ncols += 4;
if (ncols >= 72) { // add CRLF every 72 columns
sout << "\r\n";
ncols = 0;
}
}
}
b64pad(ctx, ctxlen, sout);
return sout.str();
}

std::string decode_base64(const std::string &input) {
std::istringstream sin(input);
std::ostringstream sout;
base64::decoder E; // NOLINT(clang-analyzer-optin.cplusplus.UninitializedObject)
E.decode(sin, sout);
uint8_t ctx[4]{};
size_t ctxlen = 0;
for (const char b : input) {
ctxlen = b64decode(static_cast<uint8_t>(b), ctx, ctxlen, sout);
}
return sout.str();
}

Expand Down
2 changes: 1 addition & 1 deletion tools/template/control.template
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Homepage: https://docs.cartesi.io/machine/host/cmdline/
Architecture: ARG_ARCH
Maintainer: Machine Reference Unit <https://discord.com/channels/600597137524391947/1107965671976992878>
Provides: machine-emulator
Depends: libboost-context1.81.0, libboost-filesystem1.81.0, libreadline8, openssl, libc-ares2, zlib1g, ca-certificates, libgomp1, lua5.4, libb64-0d, libcrypto++8, libprotobuf32, libgrpc++1.51
Depends: libboost-context1.81.0, libboost-filesystem1.81.0, libreadline8, openssl, libc-ares2, zlib1g, ca-certificates, libgomp1, lua5.4, libcrypto++8, libprotobuf32, libgrpc++1.51
Section: devel
Priority: optional
Multi-Arch: foreign
Expand Down

0 comments on commit 010e301

Please sign in to comment.