diff --git a/include/jwt-cpp/base.h b/include/jwt-cpp/base.h index 5ba492fc..4e4ddf3c 100644 --- a/include/jwt-cpp/base.h +++ b/include/jwt-cpp/base.h @@ -38,6 +38,26 @@ namespace jwt { 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}}; return data; } + static const std::array& rdata() { + static constexpr std::array rdata{ + {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, + -1, 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,-1,-1,-1,-1,-1, + -1,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,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,}}; + return rdata; + } static const std::string& fill() { static const std::string fill{"="}; return fill; @@ -61,6 +81,26 @@ namespace jwt { 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'}}; return data; } + static const std::array& rdata() { + static constexpr std::array rdata{ + {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1, + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, + -1, 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,-1,-1,-1,-1,63, + -1,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,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,}}; + return rdata; + } static const std::string& fill() { static const std::string fill{"%3d"}; return fill; @@ -82,6 +122,26 @@ namespace jwt { 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'}}; return data; } + static const std::array& rdata() { + static constexpr std::array rdata{ + {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1, + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, + -1, 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,-1,-1,-1,-1,63, + -1,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,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,}}; + return rdata; + } static const std::vector& fill() { static const std::vector fill{"%3D", "%3d"}; return fill; @@ -89,11 +149,10 @@ namespace jwt { }; } // namespace helper - inline uint32_t index(const std::array& alphabet, char symbol) { - auto itr = std::find_if(alphabet.cbegin(), alphabet.cend(), [symbol](char c) { return c == symbol; }); - if (itr == alphabet.cend()) { throw std::runtime_error("Invalid input: not within alphabet"); } - - return static_cast(std::distance(alphabet.cbegin(), itr)); + inline uint32_t index(const std::array& rdata, char symbol) { + auto index = rdata[static_cast(symbol)]; + if (index <= -1) {throw std::runtime_error("Invalid input: not within alphabet");} + return static_cast(index); } } // namespace alphabet @@ -178,7 +237,7 @@ namespace jwt { return res; } - inline std::string decode(const std::string& base, const std::array& alphabet, + inline std::string decode(const std::string& base, const std::array& rdata, const std::vector& fill) { const auto pad = count_padding(base, fill); if (pad.count > 2) throw std::runtime_error("Invalid input: too much fill"); @@ -190,7 +249,7 @@ namespace jwt { std::string res; res.reserve(out_size); - auto get_sextet = [&](size_t offset) { return alphabet::index(alphabet, base[offset]); }; + auto get_sextet = [&](size_t offset) { return alphabet::index(rdata, base[offset]); }; size_t fast_size = size - size % 4; for (size_t i = 0; i < fast_size;) { @@ -224,9 +283,9 @@ namespace jwt { return res; } - inline std::string decode(const std::string& base, const std::array& alphabet, + inline std::string decode(const std::string& base, const std::array& rdata, const std::string& fill) { - return decode(base, alphabet, std::vector{fill}); + return decode(base, rdata, std::vector{fill}); } inline std::string pad(const std::string& base, const std::string& fill) { @@ -273,7 +332,7 @@ namespace jwt { */ template std::string decode(const std::string& base) { - return details::decode(base, T::data(), T::fill()); + return details::decode(base, T::rdata(), T::fill()); } /** * \brief Generic base64 padding diff --git a/tests/BaseTest.cpp b/tests/BaseTest.cpp index 210798af..741e1117 100644 --- a/tests/BaseTest.cpp +++ b/tests/BaseTest.cpp @@ -2,15 +2,43 @@ #include TEST(BaseTest, Base64Index) { - ASSERT_EQ(0, jwt::alphabet::index(jwt::alphabet::base64::data(), 'A')); - ASSERT_EQ(32, jwt::alphabet::index(jwt::alphabet::base64::data(), 'g')); - ASSERT_EQ(62, jwt::alphabet::index(jwt::alphabet::base64::data(), '+')); + ASSERT_EQ(0, jwt::alphabet::index(jwt::alphabet::base64::rdata(), 'A')); + ASSERT_EQ(32, jwt::alphabet::index(jwt::alphabet::base64::rdata(), 'g')); + ASSERT_EQ(62, jwt::alphabet::index(jwt::alphabet::base64::rdata(), '+')); + + std::size_t index = 0; + for (auto c : jwt::alphabet::base64::data()) { + ASSERT_EQ(index, jwt::alphabet::index(jwt::alphabet::base64::rdata(), c)); + index++; + } + + std::size_t noBaseCharCount = 0; + for (std::size_t i = 0; i < jwt::alphabet::base64::rdata().size(); i++) { + if(jwt::alphabet::base64::rdata().at(i) == -1) { + noBaseCharCount++; + } + } + ASSERT_EQ(jwt::alphabet::base64::rdata().size() - jwt::alphabet::base64::data().size(), noBaseCharCount); } TEST(BaseTest, Base64URLIndex) { - ASSERT_EQ(0, jwt::alphabet::index(jwt::alphabet::base64url::data(), 'A')); - ASSERT_EQ(32, jwt::alphabet::index(jwt::alphabet::base64url::data(), 'g')); - ASSERT_EQ(62, jwt::alphabet::index(jwt::alphabet::base64url::data(), '-')); + ASSERT_EQ(0, jwt::alphabet::index(jwt::alphabet::base64url::rdata(), 'A')); + ASSERT_EQ(32, jwt::alphabet::index(jwt::alphabet::base64url::rdata(), 'g')); + ASSERT_EQ(62, jwt::alphabet::index(jwt::alphabet::base64url::rdata(), '-')); + + std::size_t index = 0; + for (auto c : jwt::alphabet::base64url::data()) { + ASSERT_EQ(index, jwt::alphabet::index(jwt::alphabet::base64url::rdata(), c)); + index++; + } + + std::size_t noBaseCharCount = 0; + for (std::size_t i = 0; i < jwt::alphabet::base64url::rdata().size(); i++) { + if(jwt::alphabet::base64url::rdata().at(i) == -1) { + noBaseCharCount++; + } + } + ASSERT_EQ(jwt::alphabet::base64url::rdata().size() - jwt::alphabet::base64url::data().size(), noBaseCharCount); } TEST(BaseTest, BaseDetailsCountPadding) {