From f387c69858ff9f0f615e2843ff96d9acb03e1cab Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Sun, 17 Jan 2021 10:16:57 -0600 Subject: [PATCH] :heavy_plus_sign: update: better base64 lib --- .gitmodules | 3 + bare_minimum_crypto/cpp/.gitignore | 1 + bare_minimum_crypto/cpp/Makefile | 12 +- bare_minimum_crypto/cpp/base64.h | 256 --------------------------- bare_minimum_crypto/cpp/bmc_test.cpp | 47 ++--- bare_minimum_crypto/cpp/cpp-base64 | 1 + 6 files changed, 34 insertions(+), 286 deletions(-) create mode 100644 .gitmodules delete mode 100644 bare_minimum_crypto/cpp/base64.h create mode 160000 bare_minimum_crypto/cpp/cpp-base64 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a5b3f84 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "bare_minimum_crypto/cpp/cpp-base64"] + path = bare_minimum_crypto/cpp/cpp-base64 + url = https://github.com/ReneNyffenegger/cpp-base64 diff --git a/bare_minimum_crypto/cpp/.gitignore b/bare_minimum_crypto/cpp/.gitignore index 9c7ab03..6c2a069 100644 --- a/bare_minimum_crypto/cpp/.gitignore +++ b/bare_minimum_crypto/cpp/.gitignore @@ -1 +1,2 @@ /bmc_test +*.o diff --git a/bare_minimum_crypto/cpp/Makefile b/bare_minimum_crypto/cpp/Makefile index 18b8a18..b9bb048 100644 --- a/bare_minimum_crypto/cpp/Makefile +++ b/bare_minimum_crypto/cpp/Makefile @@ -1,10 +1,18 @@ # g++ and clang++ both have pretty garbage errors CXX=g++ FLAGS=-std=c++17 -g +CXX_FLAGS=$(FLAGS) -c +L_FLAGS=$(FLAGS) LIBS=-lsodium -bmc_test: bmc_test.cpp - $(CXX) -o $@ $^ $(FLAGS) $(LIBS) +bmc_test: bmc_test.o base64.o + $(CXX) -o $@ $^ $(L_FLAGS) $(LIBS) + +bmc_test.o: bmc_test.cpp + $(CXX) -o $@ $(CXX_FLAGS) $< + +base64.o: cpp-base64/base64.cpp cpp-base64/base64.h + $(CXX) -o $@ $(CXX_FLAGS) $< clean: rm bmc_test diff --git a/bare_minimum_crypto/cpp/base64.h b/bare_minimum_crypto/cpp/base64.h deleted file mode 100644 index bda4806..0000000 --- a/bare_minimum_crypto/cpp/base64.h +++ /dev/null @@ -1,256 +0,0 @@ -#ifndef BASE64_H -#define BASE64_H - -#include - -const char kBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -class Base64 { - public: - static bool Encode(const std::string &in, std::string *out) { - int i = 0, j = 0; - size_t enc_len = 0; - unsigned char a3[3]; - unsigned char a4[4]; - - out->resize(EncodedLength(in)); - - size_t input_len = in.size(); - std::string::const_iterator input = in.begin(); - - while (input_len--) { - a3[i++] = *(input++); - if (i == 3) { - a3_to_a4(a4, a3); - - for (i = 0; i < 4; i++) { - (*out)[enc_len++] = kBase64Alphabet[a4[i]]; - } - - i = 0; - } - } - - if (i) { - for (j = i; j < 3; j++) { - a3[j] = '\0'; - } - - a3_to_a4(a4, a3); - - for (j = 0; j < i + 1; j++) { - (*out)[enc_len++] = kBase64Alphabet[a4[j]]; - } - - while ((i++ < 3)) { - (*out)[enc_len++] = '='; - } - } - - return (enc_len == out->size()); - } - - static bool Encode(const char *input, size_t input_length, char *out, size_t out_length) { - int i = 0, j = 0; - char *out_begin = out; - unsigned char a3[3]; - unsigned char a4[4]; - - size_t encoded_length = EncodedLength(input_length); - - if (out_length < encoded_length) return false; - - while (input_length--) { - a3[i++] = *input++; - if (i == 3) { - a3_to_a4(a4, a3); - - for (i = 0; i < 4; i++) { - *out++ = kBase64Alphabet[a4[i]]; - } - - i = 0; - } - } - - if (i) { - for (j = i; j < 3; j++) { - a3[j] = '\0'; - } - - a3_to_a4(a4, a3); - - for (j = 0; j < i + 1; j++) { - *out++ = kBase64Alphabet[a4[j]]; - } - - while ((i++ < 3)) { - *out++ = '='; - } - } - - return (out == (out_begin + encoded_length)); - } - - static bool Decode(const std::string &in, std::string *out) { - int i = 0, j = 0; - size_t dec_len = 0; - unsigned char a3[3]; - unsigned char a4[4]; - - size_t input_len = in.size(); - std::string::const_iterator input = in.begin(); - - out->resize(DecodedLength(in)); - - while (input_len--) { - if (*input == '=') { - break; - } - - a4[i++] = *(input++); - if (i == 4) { - for (i = 0; i <4; i++) { - a4[i] = b64_lookup(a4[i]); - } - - a4_to_a3(a3,a4); - - for (i = 0; i < 3; i++) { - (*out)[dec_len++] = a3[i]; - } - - i = 0; - } - } - - if (i) { - for (j = i; j < 4; j++) { - a4[j] = '\0'; - } - - for (j = 0; j < 4; j++) { - a4[j] = b64_lookup(a4[j]); - } - - a4_to_a3(a3,a4); - - for (j = 0; j < i - 1; j++) { - (*out)[dec_len++] = a3[j]; - } - } - - return (dec_len == out->size()); - } - - static bool Decode(const char *input, size_t input_length, char *out, size_t out_length) { - int i = 0, j = 0; - char *out_begin = out; - unsigned char a3[3]; - unsigned char a4[4]; - - size_t decoded_length = DecodedLength(input, input_length); - - if (out_length < decoded_length) return false; - - while (input_length--) { - if (*input == '=') { - break; - } - - a4[i++] = *(input++); - if (i == 4) { - for (i = 0; i <4; i++) { - a4[i] = b64_lookup(a4[i]); - } - - a4_to_a3(a3,a4); - - for (i = 0; i < 3; i++) { - *out++ = a3[i]; - } - - i = 0; - } - } - - if (i) { - for (j = i; j < 4; j++) { - a4[j] = '\0'; - } - - for (j = 0; j < 4; j++) { - a4[j] = b64_lookup(a4[j]); - } - - a4_to_a3(a3,a4); - - for (j = 0; j < i - 1; j++) { - *out++ = a3[j]; - } - } - - return (out == (out_begin + decoded_length)); - } - - static size_t DecodedLength(const char *in, size_t in_length) { - int numEq = 0; - - const char *in_end = in + in_length; - while (*--in_end == '=') ++numEq; - - return ((6 * in_length) / 8) - numEq; - } - - static size_t DecodedLength(const std::string &in) { - int numEq = 0; - size_t n = in.size(); - - for (std::string::const_reverse_iterator it = in.rbegin(); *it == '='; ++it) { - ++numEq; - } - - return ((6 * n) / 8) - numEq; - } - - inline static size_t EncodedLength(size_t length) { - return (length + 2 - ((length + 2) % 3)) / 3 * 4; - } - - inline static size_t EncodedLength(const std::string &in) { - return EncodedLength(in.length()); - } - - inline static void StripPadding(std::string *in) { - while (!in->empty() && *(in->rbegin()) == '=') in->resize(in->size() - 1); - } - - private: - static inline void a3_to_a4(unsigned char * a4, unsigned char * a3) { - a4[0] = (a3[0] & 0xfc) >> 2; - a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4); - a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6); - a4[3] = (a3[2] & 0x3f); - } - - static inline void a4_to_a3(unsigned char * a3, unsigned char * a4) { - a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4); - a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2); - a3[2] = ((a4[2] & 0x3) << 6) + a4[3]; - } - - static inline unsigned char b64_lookup(unsigned char c) { - if(c >='A' && c <='Z') return c - 'A'; - if(c >='a' && c <='z') return c - 71; - if(c >='0' && c <='9') return c + 4; - if(c == '+') return 62; - if(c == '/') return 63; - return 255; - } -}; - - - -#endif // BASE64_H diff --git a/bare_minimum_crypto/cpp/bmc_test.cpp b/bare_minimum_crypto/cpp/bmc_test.cpp index e34cad6..c323706 100644 --- a/bare_minimum_crypto/cpp/bmc_test.cpp +++ b/bare_minimum_crypto/cpp/bmc_test.cpp @@ -8,7 +8,7 @@ #include // From https://github.com/tkislan/base64 -#include "base64.h" +#include "cpp-base64/base64.h" #include "json.hpp" using namespace std; @@ -21,24 +21,18 @@ const int64_t about_3_months = (int64_t)105 * 86400; // Not sure why the Base64 lib fails to provide this API string b64_encode (const vector & v) { - string s; - s.resize (Base64::EncodedLength (v.size ())); - - Base64::Encode ((const char *)v.data (), v.size (), s.data (), s.size ()); - - return s; + return base64_encode (string_view ((const char *)v.data (), v.size ())); } optional > b64_decode (const string & s) { - vector v; - v.resize (Base64::DecodedLength (s.data (), s.size ())); - - if (! Base64::Decode (s.data (), s.size (), (char *)v.data (), v.size ())) - { + try { + const auto decoded = base64_decode (s); + const vector v ((const uint8_t *)&decoded [0], (const uint8_t *)&decoded [decoded.size ()]); + return v; + } + catch (const exception &) { return nullopt; } - - return v; } struct ExpiringSignature { @@ -108,10 +102,7 @@ optional try_verify_signed_data ( const string purpose = j ["purpose"]; const string payload_b64 = j ["payload_b64"]; - string payload_s; - Base64::Decode (payload_b64, &payload_s); - - const vector payload; + const auto payload = std::move (*b64_decode (payload_b64)); return VerifiedData { payload, @@ -132,13 +123,6 @@ optional verify_signed_data ( } } -string to_base64 (const vector & v) { - const string s ((const char *)v.data (), v.size ()); - string b64; - Base64::Encode (s, &b64); - return b64; -} - class SigningKey { vector pk; vector sk; @@ -158,7 +142,7 @@ public: } string pub_to_base64 () const { - return to_base64 (pk); + return b64_encode (pk); } optional sign_binary ( @@ -174,7 +158,7 @@ public: {"not_before", now}, {"not_after", not_after}, {"purpose", purpose}, - {"payload_b64", to_base64 (payload)}, + {"payload_b64", b64_encode (payload)}, }; const auto cert_s = j.dump (); @@ -218,6 +202,13 @@ int check_real_time () { } int check_base64 () { + // I assume that char is 8 bits + // char is C++ nonsense inherited from C nonsense + if (sizeof (char) != sizeof (uint8_t)) { + cerr << "char is not the same size as uint8_t" << endl; + return 1; + } + vector v {1, 2, 3, 4, 5, 6}; const auto s = b64_encode (v); @@ -290,7 +281,7 @@ int main () { { cerr << "Cert:" << endl; cerr << cert.cert_s << endl; - cerr << to_base64 (cert.sig) << endl; + cerr << b64_encode (cert.sig) << endl; } // Suppose the client knows our root public key diff --git a/bare_minimum_crypto/cpp/cpp-base64 b/bare_minimum_crypto/cpp/cpp-base64 new file mode 160000 index 0000000..80525f9 --- /dev/null +++ b/bare_minimum_crypto/cpp/cpp-base64 @@ -0,0 +1 @@ +Subproject commit 80525f93cbabaa11bbcae137f24467f97d74345d