mirror of
https://github.com/arun11299/cpp-jwt.git
synced 2025-05-15 09:18:33 +00:00
Im provements in base64.hpp
This commit is contained in:
parent
da6d4932c3
commit
2290c8733a
5 changed files with 134 additions and 25 deletions
|
@ -7,8 +7,27 @@
|
||||||
|
|
||||||
namespace jwt {
|
namespace jwt {
|
||||||
|
|
||||||
/*!
|
// Returns the maximum number of bytes required to
|
||||||
|
// encode an input byte string of length `n` to base64.
|
||||||
|
inline constexpr
|
||||||
|
size_t encoding_size(size_t n)
|
||||||
|
{
|
||||||
|
return 4 * ((n + 2) / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the maximum number of bytes required
|
||||||
|
// to store a decoded base64 byte string.
|
||||||
|
inline constexpr
|
||||||
|
size_t decoding_size(size_t n)
|
||||||
|
{
|
||||||
|
return n / 4 * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* Encoding map.
|
* Encoding map.
|
||||||
|
* A constexpr helper class for performing base64
|
||||||
|
* encoding on the input byte string.
|
||||||
*/
|
*/
|
||||||
class EMap
|
class EMap
|
||||||
{
|
{
|
||||||
|
@ -31,21 +50,32 @@ private:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* Encodes a sequence of octet into base64 string.
|
||||||
|
* Returns std::string resized to contain only the
|
||||||
|
* encoded data (as usual without null terminator).
|
||||||
|
*
|
||||||
|
* The encoded string is atleast `encoding_size(input len)`
|
||||||
|
* in size.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* @in : Input byte string to be encoded.
|
||||||
|
* @len : Length of the input byte string.
|
||||||
*/
|
*/
|
||||||
std::string base64_encode(const char* in, size_t len)
|
std::string base64_encode(const char* in, size_t len)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
result.resize(128);
|
const auto encoded_siz = encoding_size(len);
|
||||||
|
result.resize(encoded_siz);
|
||||||
|
|
||||||
constexpr static const EMap emap{};
|
constexpr static const EMap emap{};
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (; i < len - 2; i += 3) {
|
for (; i < len - 2; i += 3) {
|
||||||
auto& first = in[i];
|
const auto first = in[i];
|
||||||
auto& second = in[i+1];
|
const auto second = in[i+1];
|
||||||
auto& third = in[i+2];
|
const auto third = in[i+2];
|
||||||
|
|
||||||
result[j++] = emap.at( (first >> 2) & 0x3F );
|
result[j++] = emap.at( (first >> 2) & 0x3F );
|
||||||
result[j++] = emap.at(((first & 0x03) << 4) | ((second & 0xF0) >> 4));
|
result[j++] = emap.at(((first & 0x03) << 4) | ((second & 0xF0) >> 4));
|
||||||
|
@ -56,8 +86,8 @@ std::string base64_encode(const char* in, size_t len)
|
||||||
switch (len % 3) {
|
switch (len % 3) {
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
auto& first = in[i];
|
const auto first = in[i];
|
||||||
auto& second = in[i+1];
|
const auto second = in[i+1];
|
||||||
|
|
||||||
result[j++] = emap.at( (first >> 2) & 0x3F );
|
result[j++] = emap.at( (first >> 2) & 0x3F );
|
||||||
result[j++] = emap.at(((first & 0x03) << 4) | ((second & 0xF0) >> 4));
|
result[j++] = emap.at(((first & 0x03) << 4) | ((second & 0xF0) >> 4));
|
||||||
|
@ -67,7 +97,7 @@ std::string base64_encode(const char* in, size_t len)
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
auto& first = in[i];
|
const auto first = in[i];
|
||||||
|
|
||||||
result[j++] = emap.at((first >> 2) & 0x3F);
|
result[j++] = emap.at((first >> 2) & 0x3F);
|
||||||
result[j++] = emap.at((first & 0x03) << 4);
|
result[j++] = emap.at((first & 0x03) << 4);
|
||||||
|
@ -79,6 +109,8 @@ std::string base64_encode(const char* in, size_t len)
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
result.resize(j);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +118,10 @@ std::string base64_encode(const char* in, size_t len)
|
||||||
|
|
||||||
//======================= Decoder ==========================
|
//======================= Decoder ==========================
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Decoding map.
|
* Decoding map.
|
||||||
|
* A helper constexpr class for providing interface
|
||||||
|
* to the decoding map for base64.
|
||||||
*/
|
*/
|
||||||
class DMap
|
class DMap
|
||||||
{
|
{
|
||||||
|
@ -122,12 +156,21 @@ private:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* Decodes octet of base64 encoded byte string.
|
||||||
|
*
|
||||||
|
* Returns a std::string with the decoded byte string.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* @in : Encoded base64 byte string.
|
||||||
|
* @len : Length of the encoded input byte string.
|
||||||
*/
|
*/
|
||||||
std::string base64_decode(const char* in, size_t len)
|
std::string base64_decode(const char* in, size_t len)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
result.resize(128);
|
const auto decoded_siz = decoding_size(len);
|
||||||
|
result.resize(decoded_siz);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t bytes_rem = len;
|
size_t bytes_rem = len;
|
||||||
size_t bytes_wr = 0;
|
size_t bytes_wr = 0;
|
||||||
|
@ -141,10 +184,10 @@ std::string base64_decode(const char* in, size_t len)
|
||||||
// Error case in input
|
// Error case in input
|
||||||
if (dmap.at(*in) == -1) return result;
|
if (dmap.at(*in) == -1) return result;
|
||||||
|
|
||||||
auto first = dmap.at(in[0]);
|
const auto first = dmap.at(in[0]);
|
||||||
auto second = dmap.at(in[1]);
|
const auto second = dmap.at(in[1]);
|
||||||
auto third = dmap.at(in[2]);
|
const auto third = dmap.at(in[2]);
|
||||||
auto fourth = dmap.at(in[3]);
|
const auto fourth = dmap.at(in[3]);
|
||||||
|
|
||||||
result[i] = (first << 2) | (second >> 4);
|
result[i] = (first << 2) | (second >> 4);
|
||||||
result[i + 1] = (second << 4) | (third >> 2);
|
result[i + 1] = (second << 4) | (third >> 2);
|
||||||
|
@ -159,24 +202,24 @@ std::string base64_decode(const char* in, size_t len)
|
||||||
switch(bytes_rem) {
|
switch(bytes_rem) {
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
auto third = dmap.at(in[2]);
|
const auto third = dmap.at(in[2]);
|
||||||
auto fourth = dmap.at(in[3]);
|
const auto fourth = dmap.at(in[3]);
|
||||||
result[i + 2] = (third << 6) | fourth;
|
result[i + 2] = (third << 6) | fourth;
|
||||||
bytes_wr++;
|
bytes_wr++;
|
||||||
//FALLTHROUGH
|
//FALLTHROUGH
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
auto second = dmap.at(in[1]);
|
const auto second = dmap.at(in[1]);
|
||||||
auto third = dmap.at(in[2]);
|
const auto third = dmap.at(in[2]);
|
||||||
result[i + 1] = (second << 4) | (third >> 2);
|
result[i + 1] = (second << 4) | (third >> 2);
|
||||||
bytes_wr++;
|
bytes_wr++;
|
||||||
//FALLTHROUGH
|
//FALLTHROUGH
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
auto first = dmap.at(in[0]);
|
const auto first = dmap.at(in[0]);
|
||||||
auto second = dmap.at(in[1]);
|
const auto second = dmap.at(in[1]);
|
||||||
result[i] = (first << 2) | (second >> 4);
|
result[i] = (first << 2) | (second >> 4);
|
||||||
bytes_wr++;
|
bytes_wr++;
|
||||||
}
|
}
|
||||||
|
@ -187,7 +230,17 @@ std::string base64_decode(const char* in, size_t len)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* Makes the base64 encoded byte string URL safe.
|
||||||
|
* Overwrites/skips few URL unsafe characters
|
||||||
|
* from the input sequence.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* @data : Base64 encoded byte string.
|
||||||
|
* @len : Length of the base64 byte string.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Length of the URL safe base64 encoded byte string.
|
||||||
*/
|
*/
|
||||||
size_t base64_uri_encode(char* data, size_t len) noexcept
|
size_t base64_uri_encode(char* data, size_t len) noexcept
|
||||||
{
|
{
|
||||||
|
@ -212,7 +265,15 @@ size_t base64_uri_encode(char* data, size_t len) noexcept
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* Decodes an input URL safe base64 encoded byte string.
|
||||||
|
*
|
||||||
|
* NOTE: To be used only for decoding URL safe base64 encoded
|
||||||
|
* byte string.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* @data : URL safe base64 encoded byte string.
|
||||||
|
* @len : Length of the input byte string.
|
||||||
*/
|
*/
|
||||||
std::string base64_uri_decode(const char* data, size_t len)
|
std::string base64_uri_decode(const char* data, size_t len)
|
||||||
{
|
{
|
||||||
|
|
0
include/jwt/error_codes.hpp
Normal file
0
include/jwt/error_codes.hpp
Normal file
0
include/jwt/exceptions.hpp
Normal file
0
include/jwt/exceptions.hpp
Normal file
BIN
include/jwt/test/test_base64
Executable file
BIN
include/jwt/test/test_base64
Executable file
Binary file not shown.
48
include/jwt/test/test_base64.cc
Normal file
48
include/jwt/test/test_base64.cc
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <cassert>
|
||||||
|
#include "jwt/base64.hpp"
|
||||||
|
|
||||||
|
void base64_test_encode()
|
||||||
|
{
|
||||||
|
std::string input = "ArunMu";
|
||||||
|
std::string output = jwt::base64_encode(input.c_str(), input.length());
|
||||||
|
assert (output == "QXJ1bk11");
|
||||||
|
|
||||||
|
input = "Something really strange!!";
|
||||||
|
output = jwt::base64_encode(input.c_str(), input.length());
|
||||||
|
assert (output == "U29tZXRoaW5nIHJlYWxseSBzdHJhbmdlISE=");
|
||||||
|
|
||||||
|
input = "Do you want to know something more stranger ????";
|
||||||
|
output = jwt::base64_encode(input.c_str(), input.length());
|
||||||
|
assert (output == "RG8geW91IHdhbnQgdG8ga25vdyBzb21ldGhpbmcgbW9yZSBzdHJhbmdlciA/Pz8/");
|
||||||
|
|
||||||
|
input = R"({"a" : "b", "c" : [1,2,3,4,5]})";
|
||||||
|
output = jwt::base64_encode(input.c_str(), input.length());
|
||||||
|
assert (output == "eyJhIiA6ICJiIiwgImMiIDogWzEsMiwzLDQsNV19");
|
||||||
|
}
|
||||||
|
|
||||||
|
void base64_test_decode()
|
||||||
|
{
|
||||||
|
std::string input = "QXJ1bk11";
|
||||||
|
std::string output = jwt::base64_decode(input.c_str(), input.length());
|
||||||
|
assert (output == "ArunMu");
|
||||||
|
|
||||||
|
input = "U29tZXRoaW5nIHJlYWxseSBzdHJhbmdlISE=";
|
||||||
|
output = jwt::base64_decode(input.c_str(), input.length());
|
||||||
|
assert (output == "Something really strange!!");
|
||||||
|
|
||||||
|
input = "RG8geW91IHdhbnQgdG8ga25vdyBzb21ldGhpbmcgbW9yZSBzdHJhbmdlciA/Pz8/";
|
||||||
|
output = jwt::base64_decode(input.c_str(), input.length());
|
||||||
|
assert (output == "Do you want to know something more stranger ????");
|
||||||
|
|
||||||
|
input = "eyJhIiA6ICJiIiwgImMiIDogWzEsMiwzLDQsNV19";
|
||||||
|
output = jwt::base64_decode(input.c_str(), input.length());
|
||||||
|
assert (output == R"({"a" : "b", "c" : [1,2,3,4,5]})");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
base64_test_encode();
|
||||||
|
base64_test_decode();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue