early-access version 2862
This commit is contained in:
557
externals/cpp-jwt/include/jwt/algorithm.hpp
vendored
Executable file
557
externals/cpp-jwt/include/jwt/algorithm.hpp
vendored
Executable file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ALGORITHM_HPP
|
||||
#define CPP_JWT_ALGORITHM_HPP
|
||||
|
||||
/*!
|
||||
* Most of the signing and verification code has been taken
|
||||
* and modified for C++ specific use from the C implementation
|
||||
* JWT library, libjwt.
|
||||
* https://github.com/benmcollins/libjwt/tree/master/libjwt
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
#include "jwt/assertions.hpp"
|
||||
#include "jwt/exceptions.hpp"
|
||||
#include "jwt/string_view.hpp"
|
||||
#include "jwt/error_codes.hpp"
|
||||
#include "jwt/base64.hpp"
|
||||
#include "jwt/config.hpp"
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/// The result type of the signing function
|
||||
using sign_result_t = std::pair<std::string, std::error_code>;
|
||||
/// The result type of verification function
|
||||
using verify_result_t = std::pair<bool, std::error_code>;
|
||||
/// The function pointer type for the signing function
|
||||
using sign_func_t = sign_result_t (*) (const jwt::string_view key,
|
||||
const jwt::string_view data);
|
||||
/// The function pointer type for the verifying function
|
||||
using verify_func_t = verify_result_t (*) (const jwt::string_view key,
|
||||
const jwt::string_view head,
|
||||
const jwt::string_view jwt_sign);
|
||||
|
||||
namespace algo {
|
||||
|
||||
//Me: TODO: All these can be done using code generaion.
|
||||
//Me: NO. NEVER. I hate Macros.
|
||||
//Me: You can use templates too.
|
||||
//Me: No. I would rather prefer explicit.
|
||||
//Me: Ok. You win.
|
||||
//Me: Same to you.
|
||||
|
||||
/**
|
||||
* HS256 algorithm.
|
||||
*/
|
||||
struct HS256
|
||||
{
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha256();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* HS384 algorithm.
|
||||
*/
|
||||
struct HS384
|
||||
{
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha384();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* HS512 algorithm.
|
||||
*/
|
||||
struct HS512
|
||||
{
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha512();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* NONE algorithm.
|
||||
*/
|
||||
struct NONE
|
||||
{
|
||||
void operator()() noexcept
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* RS256 algorithm.
|
||||
*/
|
||||
struct RS256
|
||||
{
|
||||
static const int type = EVP_PKEY_RSA;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha256();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* RS384 algorithm.
|
||||
*/
|
||||
struct RS384
|
||||
{
|
||||
static const int type = EVP_PKEY_RSA;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha384();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* RS512 algorithm.
|
||||
*/
|
||||
struct RS512
|
||||
{
|
||||
static const int type = EVP_PKEY_RSA;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha512();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ES256 algorithm.
|
||||
*/
|
||||
struct ES256
|
||||
{
|
||||
static const int type = EVP_PKEY_EC;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha256();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ES384 algorithm.
|
||||
*/
|
||||
struct ES384
|
||||
{
|
||||
static const int type = EVP_PKEY_EC;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha384();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ES512 algorithm.
|
||||
*/
|
||||
struct ES512
|
||||
{
|
||||
static const int type = EVP_PKEY_EC;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha512();
|
||||
}
|
||||
};
|
||||
|
||||
} //END Namespace algo
|
||||
|
||||
|
||||
/**
|
||||
* JWT signing algorithm types.
|
||||
*/
|
||||
enum class algorithm
|
||||
{
|
||||
NONE = 0,
|
||||
HS256,
|
||||
HS384,
|
||||
HS512,
|
||||
RS256,
|
||||
RS384,
|
||||
RS512,
|
||||
ES256,
|
||||
ES384,
|
||||
ES512,
|
||||
UNKN,
|
||||
TERM,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Convert the algorithm enum class type to
|
||||
* its stringified form.
|
||||
*/
|
||||
inline jwt::string_view alg_to_str(SCOPED_ENUM algorithm alg) noexcept
|
||||
{
|
||||
switch (alg) {
|
||||
case algorithm::HS256: return "HS256";
|
||||
case algorithm::HS384: return "HS384";
|
||||
case algorithm::HS512: return "HS512";
|
||||
case algorithm::RS256: return "RS256";
|
||||
case algorithm::RS384: return "RS384";
|
||||
case algorithm::RS512: return "RS512";
|
||||
case algorithm::ES256: return "ES256";
|
||||
case algorithm::ES384: return "ES384";
|
||||
case algorithm::ES512: return "ES512";
|
||||
case algorithm::TERM: return "TERM";
|
||||
case algorithm::NONE: return "NONE";
|
||||
case algorithm::UNKN: return "UNKN";
|
||||
default: assert (0 && "Unknown Algorithm");
|
||||
};
|
||||
return "UNKN";
|
||||
JWT_NOT_REACHED("Code not reached");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert stringified algorithm to enum class.
|
||||
* The string comparison is case insesitive.
|
||||
*/
|
||||
inline SCOPED_ENUM algorithm str_to_alg(const jwt::string_view alg) noexcept
|
||||
{
|
||||
if (!alg.length()) return algorithm::UNKN;
|
||||
|
||||
if (!strcasecmp(alg.data(), "NONE")) return algorithm::NONE;
|
||||
if (!strcasecmp(alg.data(), "HS256")) return algorithm::HS256;
|
||||
if (!strcasecmp(alg.data(), "HS384")) return algorithm::HS384;
|
||||
if (!strcasecmp(alg.data(), "HS512")) return algorithm::HS512;
|
||||
if (!strcasecmp(alg.data(), "RS256")) return algorithm::RS256;
|
||||
if (!strcasecmp(alg.data(), "RS384")) return algorithm::RS384;
|
||||
if (!strcasecmp(alg.data(), "RS512")) return algorithm::RS512;
|
||||
if (!strcasecmp(alg.data(), "ES256")) return algorithm::ES256;
|
||||
if (!strcasecmp(alg.data(), "ES384")) return algorithm::ES384;
|
||||
if (!strcasecmp(alg.data(), "ES512")) return algorithm::ES512;
|
||||
|
||||
return algorithm::UNKN;
|
||||
|
||||
JWT_NOT_REACHED("Code not reached");
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void bio_deletor(BIO* ptr)
|
||||
{
|
||||
if (ptr) BIO_free_all(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void evp_md_ctx_deletor(EVP_MD_CTX* ptr)
|
||||
{
|
||||
if (ptr) EVP_MD_CTX_destroy(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void ec_key_deletor(EC_KEY* ptr)
|
||||
{
|
||||
if (ptr) EC_KEY_free(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void ec_sig_deletor(ECDSA_SIG* ptr)
|
||||
{
|
||||
if (ptr) ECDSA_SIG_free(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void ev_pkey_deletor(EVP_PKEY* ptr)
|
||||
{
|
||||
if (ptr) EVP_PKEY_free(ptr);
|
||||
}
|
||||
|
||||
/// Useful typedefs
|
||||
using bio_deletor_t = decltype(&bio_deletor);
|
||||
using BIO_uptr = std::unique_ptr<BIO, bio_deletor_t>;
|
||||
|
||||
using evp_mdctx_deletor_t = decltype(&evp_md_ctx_deletor);
|
||||
using EVP_MDCTX_uptr = std::unique_ptr<EVP_MD_CTX, evp_mdctx_deletor_t>;
|
||||
|
||||
using eckey_deletor_t = decltype(&ec_key_deletor);
|
||||
using EC_KEY_uptr = std::unique_ptr<EC_KEY, eckey_deletor_t>;
|
||||
|
||||
using ecsig_deletor_t = decltype(&ec_sig_deletor);
|
||||
using EC_SIG_uptr = std::unique_ptr<ECDSA_SIG, ecsig_deletor_t>;
|
||||
|
||||
using evpkey_deletor_t = decltype(&ev_pkey_deletor);
|
||||
using EC_PKEY_uptr = std::unique_ptr<EVP_PKEY, evpkey_deletor_t>;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* OpenSSL HMAC based signature and verfication.
|
||||
*
|
||||
* The template type `Hasher` takes the type representing
|
||||
* the HMAC algorithm type from the `jwt::algo` namespace.
|
||||
*
|
||||
* The struct is specialized for NONE algorithm. See the
|
||||
* details of that class as well.
|
||||
*/
|
||||
template <typename Hasher>
|
||||
struct HMACSign
|
||||
{
|
||||
/// The type of Hashing algorithm
|
||||
using hasher_type = Hasher;
|
||||
|
||||
/**
|
||||
* Signs the input using the HMAC algorithm using the
|
||||
* provided key.
|
||||
*
|
||||
* Arguments:
|
||||
* @key : The secret/key to use for the signing.
|
||||
* Cannot be empty string.
|
||||
* @data : The data to be signed.
|
||||
*
|
||||
* Exceptions:
|
||||
* Any allocation failure will result in jwt::MemoryAllocationException
|
||||
* being thrown.
|
||||
*/
|
||||
static sign_result_t sign(const jwt::string_view key, const jwt::string_view data)
|
||||
{
|
||||
std::string sign;
|
||||
sign.resize(EVP_MAX_MD_SIZE);
|
||||
std::error_code ec{};
|
||||
|
||||
uint32_t len = 0;
|
||||
|
||||
unsigned char* res = HMAC(Hasher{}(),
|
||||
key.data(),
|
||||
static_cast<int>(key.length()),
|
||||
reinterpret_cast<const unsigned char*>(data.data()),
|
||||
data.length(),
|
||||
reinterpret_cast<unsigned char*>(&sign[0]),
|
||||
&len);
|
||||
if (!res) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
}
|
||||
|
||||
sign.resize(len);
|
||||
return { std::move(sign), ec };
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the JWT string against the signature using
|
||||
* the provided key.
|
||||
*
|
||||
* Arguments:
|
||||
* @key : The secret/key to use for the signing.
|
||||
* Cannot be empty string.
|
||||
* @head : The part of JWT encoded string representing header
|
||||
* and the payload claims.
|
||||
* @sign : The signature part of the JWT encoded string.
|
||||
*
|
||||
* Returns:
|
||||
* verify_result_t
|
||||
* verify_result_t::first set to true if verification succeeds.
|
||||
* false otherwise.
|
||||
* verify_result_t::second set to relevant error if verification fails.
|
||||
*
|
||||
* Exceptions:
|
||||
* Any allocation failure will result in jwt::MemoryAllocationException
|
||||
* being thrown.
|
||||
*/
|
||||
static verify_result_t
|
||||
verify(const jwt::string_view key, const jwt::string_view head, const jwt::string_view sign);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialization of `HMACSign` class
|
||||
* for NONE algorithm.
|
||||
*
|
||||
* This specialization is selected for even
|
||||
* PEM based algorithms.
|
||||
*
|
||||
* The signing and verification APIs are
|
||||
* basically no-op except that they would
|
||||
* set the relevant error code.
|
||||
*
|
||||
* NOTE: error_code would be set in the case
|
||||
* of usage of NONE algorithm.
|
||||
* Users of this API are expected to check for
|
||||
* the case explicitly.
|
||||
*/
|
||||
template <>
|
||||
struct HMACSign<algo::NONE>
|
||||
{
|
||||
using hasher_type = algo::NONE;
|
||||
|
||||
/**
|
||||
* Basically a no-op. Sets the error code to NoneAlgorithmUsed.
|
||||
*/
|
||||
static sign_result_t sign(const jwt::string_view key, const jwt::string_view data)
|
||||
{
|
||||
(void)key;
|
||||
(void)data;
|
||||
std::error_code ec{};
|
||||
ec = AlgorithmErrc::NoneAlgorithmUsed;
|
||||
|
||||
return { std::string{}, ec };
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically a no-op. Sets the error code to NoneAlgorithmUsed.
|
||||
*/
|
||||
static verify_result_t
|
||||
verify(const jwt::string_view key, const jwt::string_view head, const jwt::string_view sign)
|
||||
{
|
||||
(void)key;
|
||||
(void)head;
|
||||
(void)sign;
|
||||
std::error_code ec{};
|
||||
ec = AlgorithmErrc::NoneAlgorithmUsed;
|
||||
|
||||
return { true, ec };
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* OpenSSL PEM based signature and verfication.
|
||||
*
|
||||
* The template type `Hasher` takes the type representing
|
||||
* the PEM algorithm type from the `jwt::algo` namespace.
|
||||
*
|
||||
* For NONE algorithm, HMACSign<> specialization is used.
|
||||
* See that for more details.
|
||||
*/
|
||||
template <typename Hasher>
|
||||
struct PEMSign
|
||||
{
|
||||
public:
|
||||
/// The type of Hashing algorithm
|
||||
using hasher_type = Hasher;
|
||||
|
||||
/**
|
||||
* Signs the input data using PEM encryption algorithm.
|
||||
*
|
||||
* Arguments:
|
||||
* @key : The key/secret to be used for signing.
|
||||
* Cannot be an empty string.
|
||||
* @data: The data to be signed.
|
||||
*
|
||||
* Exceptions:
|
||||
* Any allocation failure would be thrown out as
|
||||
* jwt::MemoryAllocationException.
|
||||
*/
|
||||
static sign_result_t sign(const jwt::string_view key, const jwt::string_view data)
|
||||
{
|
||||
std::error_code ec{};
|
||||
|
||||
std::string ii{data.data(), data.length()};
|
||||
|
||||
EC_PKEY_uptr pkey{load_key(key, ec), ev_pkey_deletor};
|
||||
if (ec) return { std::string{}, ec };
|
||||
|
||||
//TODO: Use stack string here ?
|
||||
std::string sign = evp_digest(pkey.get(), data, ec);
|
||||
|
||||
if (ec) return { std::string{}, ec };
|
||||
|
||||
if (Hasher::type == EVP_PKEY_EC) {
|
||||
sign = public_key_ser(pkey.get(), sign, ec);
|
||||
}
|
||||
|
||||
return { std::move(sign), ec };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
static verify_result_t
|
||||
verify(const jwt::string_view key, const jwt::string_view head, const jwt::string_view sign);
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
*/
|
||||
static EVP_PKEY* load_key(const jwt::string_view key, std::error_code& ec);
|
||||
|
||||
/*!
|
||||
*/
|
||||
static std::string evp_digest(EVP_PKEY* pkey, const jwt::string_view data, std::error_code& ec);
|
||||
|
||||
/*!
|
||||
*/
|
||||
static std::string public_key_ser(EVP_PKEY* pkey, jwt::string_view sign, std::error_code& ec);
|
||||
|
||||
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L
|
||||
|
||||
|
||||
//ATTN: Below 2 functions
|
||||
//are Taken from https://github.com/nginnever/zogminer/issues/39
|
||||
|
||||
/**
|
||||
*/
|
||||
static void ECDSA_SIG_get0(const ECDSA_SIG* sig, const BIGNUM** pr, const BIGNUM** ps)
|
||||
{
|
||||
if (pr != nullptr) *pr = sig->r;
|
||||
if (ps != nullptr) *ps = sig->s;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
static int ECDSA_SIG_set0(ECDSA_SIG* sig, BIGNUM* r, BIGNUM* s)
|
||||
{
|
||||
if (r == nullptr || s == nullptr) return 0;
|
||||
|
||||
BN_clear_free(sig->r);
|
||||
BN_clear_free(sig->s);
|
||||
|
||||
sig->r = r;
|
||||
sig->s = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#include "jwt/impl/algorithm.ipp"
|
||||
|
||||
|
||||
#endif
|
51
externals/cpp-jwt/include/jwt/assertions.hpp
vendored
Executable file
51
externals/cpp-jwt/include/jwt/assertions.hpp
vendored
Executable file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ASSERTIONS_HPP
|
||||
#define CPP_JWT_ASSERTIONS_HPP
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
#if defined(__clang__)
|
||||
# define JWT_NOT_REACHED_MARKER() __builtin_unreachable()
|
||||
#elif defined(__GNUC__)
|
||||
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
# define JWT_NOT_REACHED_MARKER() __builtin_unreachable()
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# define JWT_NOT_REACHED_MARKER() __assume(0)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
# define JWT_NOT_REACHED(reason) do { \
|
||||
assert (0 && reason); \
|
||||
JWT_NOT_REACHED_MARKER(); \
|
||||
} while (0)
|
||||
#else
|
||||
# define JWT_NOT_REACHED(reason) JWT_NOT_REACHED_MARKER()
|
||||
#endif
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
335
externals/cpp-jwt/include/jwt/base64.hpp
vendored
Executable file
335
externals/cpp-jwt/include/jwt/base64.hpp
vendored
Executable file
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_BASE64_HPP
|
||||
#define CPP_JWT_BASE64_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <ostream>
|
||||
#include "jwt/config.hpp"
|
||||
#include "jwt/string_view.hpp"
|
||||
|
||||
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.
|
||||
* A constexpr helper class for performing base64
|
||||
* encoding on the input byte string.
|
||||
*/
|
||||
class EMap
|
||||
{
|
||||
public:
|
||||
constexpr EMap() = default;
|
||||
|
||||
public:
|
||||
constexpr char at(size_t pos) const noexcept
|
||||
{
|
||||
return X_ASSERT(pos < chars_.size()), chars_.at(pos);
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<char, 64> chars_ = {{
|
||||
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
|
||||
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
|
||||
'0','1','2','3','4','5','6','7','8','9',
|
||||
'+','/',
|
||||
}};
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
inline std::string base64_encode(const char* in, size_t len)
|
||||
{
|
||||
std::string result;
|
||||
const auto encoded_siz = encoding_size(len);
|
||||
result.resize(encoded_siz);
|
||||
|
||||
constexpr static const EMap emap{};
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
for (; i < static_cast<int>(len) - 2; i += 3) {
|
||||
const auto first = in[i];
|
||||
const auto second = in[i+1];
|
||||
const auto third = in[i+2];
|
||||
|
||||
result[j++] = emap.at( (first >> 2) & 0x3F );
|
||||
result[j++] = emap.at(((first & 0x03) << 4) | ((second & 0xF0) >> 4));
|
||||
result[j++] = emap.at(((second & 0x0F) << 2) | ((third & 0xC0) >> 6));
|
||||
result[j++] = emap.at( (third & 0x3F) );
|
||||
}
|
||||
|
||||
switch (len % 3) {
|
||||
case 2:
|
||||
{
|
||||
const auto first = in[i];
|
||||
const auto second = in[i+1];
|
||||
|
||||
result[j++] = emap.at( (first >> 2) & 0x3F );
|
||||
result[j++] = emap.at(((first & 0x03) << 4) | ((second & 0xF0) >> 4));
|
||||
result[j++] = emap.at( (second & 0x0F) << 2 );
|
||||
result[j++] = '=';
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
const auto first = in[i];
|
||||
|
||||
result[j++] = emap.at((first >> 2) & 0x3F);
|
||||
result[j++] = emap.at((first & 0x03) << 4);
|
||||
result[j++] = '=';
|
||||
result[j++] = '=';
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
break;
|
||||
};
|
||||
|
||||
result.resize(j);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//======================= Decoder ==========================
|
||||
|
||||
/**
|
||||
* Decoding map.
|
||||
* A helper constexpr class for providing interface
|
||||
* to the decoding map for base64.
|
||||
*/
|
||||
class DMap
|
||||
{
|
||||
public:
|
||||
constexpr DMap() = default;
|
||||
|
||||
public:
|
||||
constexpr signed char at(size_t pos) const noexcept
|
||||
{
|
||||
return X_ASSERT(pos < map_.size()), map_[pos];
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<signed char, 256> map_ = {{
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32-47
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48-63
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80-95
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112-127
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240-255
|
||||
}};
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
inline std::string base64_decode(const char* in, size_t len)
|
||||
{
|
||||
std::string result;
|
||||
const auto decoded_siz = decoding_size(len);
|
||||
result.resize(decoded_siz);
|
||||
|
||||
int i = 0;
|
||||
size_t bytes_rem = len;
|
||||
size_t bytes_wr = 0;
|
||||
|
||||
constexpr static const DMap dmap{};
|
||||
|
||||
while (bytes_rem > 0 && dmap.at(in[bytes_rem - 1]) == -1) { bytes_rem--; }
|
||||
|
||||
while (bytes_rem > 4)
|
||||
{
|
||||
// Error case in input
|
||||
if (dmap.at(*in) == -1) return result;
|
||||
|
||||
const auto first = dmap.at(in[0]);
|
||||
const auto second = dmap.at(in[1]);
|
||||
const auto third = dmap.at(in[2]);
|
||||
const auto fourth = dmap.at(in[3]);
|
||||
|
||||
result[i] = (first << 2) | (second >> 4);
|
||||
result[i + 1] = (second << 4) | (third >> 2);
|
||||
result[i + 2] = (third << 6) | fourth;
|
||||
|
||||
bytes_rem -= 4;
|
||||
i += 3;
|
||||
in += 4;
|
||||
}
|
||||
bytes_wr = i;
|
||||
|
||||
switch(bytes_rem) {
|
||||
case 4:
|
||||
{
|
||||
const auto third = dmap.at(in[2]);
|
||||
const auto fourth = dmap.at(in[3]);
|
||||
result[i + 2] = (third << 6) | fourth;
|
||||
bytes_wr++;
|
||||
}
|
||||
//FALLTHROUGH
|
||||
case 3:
|
||||
{
|
||||
const auto second = dmap.at(in[1]);
|
||||
const auto third = dmap.at(in[2]);
|
||||
result[i + 1] = (second << 4) | (third >> 2);
|
||||
bytes_wr++;
|
||||
}
|
||||
//FALLTHROUGH
|
||||
case 2:
|
||||
{
|
||||
const auto first = dmap.at(in[0]);
|
||||
const auto second = dmap.at(in[1]);
|
||||
result[i] = (first << 2) | (second >> 4);
|
||||
bytes_wr++;
|
||||
}
|
||||
};
|
||||
|
||||
result.resize(bytes_wr);
|
||||
|
||||
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.
|
||||
*/
|
||||
inline size_t base64_uri_encode(char* data, size_t len) noexcept
|
||||
{
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
|
||||
for (; i < len; ++i) {
|
||||
switch (data[i]) {
|
||||
case '+':
|
||||
data[j++] = '-';
|
||||
break;
|
||||
case '/':
|
||||
data[j++] = '_';
|
||||
break;
|
||||
case '=':
|
||||
break;
|
||||
default:
|
||||
data[j++] = data[i];
|
||||
};
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
inline std::string base64_uri_decode(const char* data, size_t len)
|
||||
{
|
||||
std::string uri_dec;
|
||||
uri_dec.resize(len + 4);
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
for (; i < len; ++i)
|
||||
{
|
||||
switch (data[i]) {
|
||||
case '-':
|
||||
uri_dec[i] = '+';
|
||||
break;
|
||||
case '_':
|
||||
uri_dec[i] = '/';
|
||||
break;
|
||||
default:
|
||||
uri_dec[i] = data[i];
|
||||
};
|
||||
}
|
||||
|
||||
size_t trailer = 4 - (i % 4);
|
||||
if (trailer && trailer < 4) {
|
||||
while (trailer--) {
|
||||
uri_dec[i++] = '=';
|
||||
}
|
||||
}
|
||||
|
||||
return base64_decode(uri_dec.c_str(), uri_dec.length());
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
|
||||
#endif
|
51
externals/cpp-jwt/include/jwt/config.hpp
vendored
Executable file
51
externals/cpp-jwt/include/jwt/config.hpp
vendored
Executable file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (c) 2018 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef CPP_JWT_CONFIG_HPP
|
||||
#define CPP_JWT_CONFIG_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
// To hack around Visual Studio error:
|
||||
// error C3431: 'algorithm': a scoped enumeration cannot be redeclared as an unscoped enumeration
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define SCOPED_ENUM enum class
|
||||
#else
|
||||
#define SCOPED_ENUM enum
|
||||
#endif
|
||||
|
||||
// To hack around Visual Studio error
|
||||
// error C3249: illegal statement or sub-expression for 'constexpr' function
|
||||
// Doesn't allow assert to be part of constexpr functions.
|
||||
// Copied the solution as described in:
|
||||
// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/
|
||||
#if defined NDEBUG
|
||||
# define X_ASSERT(CHECK) void(0)
|
||||
#else
|
||||
# define X_ASSERT(CHECK) \
|
||||
( (CHECK) ? void(0) : []{assert(!#CHECK);}() )
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
236
externals/cpp-jwt/include/jwt/detail/meta.hpp
vendored
Executable file
236
externals/cpp-jwt/include/jwt/detail/meta.hpp
vendored
Executable file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef CPP_JWT_META_HPP
|
||||
#define CPP_JWT_META_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include "jwt/string_view.hpp"
|
||||
|
||||
namespace jwt {
|
||||
namespace detail {
|
||||
namespace meta {
|
||||
|
||||
/**
|
||||
* The famous void_t trick.
|
||||
*/
|
||||
template <typename... T>
|
||||
struct make_void
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <typename... T>
|
||||
using void_t = typename make_void<T...>::type;
|
||||
|
||||
/**
|
||||
* A type tag representing an empty tag.
|
||||
* To be used to represent a `result-not-found`
|
||||
* situation.
|
||||
*/
|
||||
struct empty_type {};
|
||||
|
||||
/**
|
||||
* A type list.
|
||||
*/
|
||||
template <typename... T> struct list{};
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename T, typename=void>
|
||||
struct has_create_json_obj_member: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_create_json_obj_member<T,
|
||||
void_t<
|
||||
decltype(
|
||||
std::declval<T&&>().create_json_obj(),
|
||||
(void)0
|
||||
)
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the type `T` models MappingConcept.
|
||||
*
|
||||
* Requirements on type `T` for matching the requirements:
|
||||
* a. Must be able to construct jwt::string_view from the
|
||||
* `key_type` of the map.
|
||||
* b. Must be able to construct jwt::string_view from the
|
||||
* `mapped_type` of the map.
|
||||
* c. The type `T` must have an access operator i.e. operator[].
|
||||
* d. The type `T` must have `begin` and `end` member functions
|
||||
* for iteration.
|
||||
*
|
||||
* NOTE: Requirements `a` and `b` means that the concept
|
||||
* type can only hold values that are string or constructible
|
||||
* to form a string_view (basically C strings and std::string)
|
||||
*/
|
||||
template <typename T, typename=void>
|
||||
struct is_mapping_concept: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_mapping_concept<T,
|
||||
void_t<
|
||||
typename std::enable_if<
|
||||
std::is_constructible<jwt::string_view, typename std::remove_reference_t<T>::key_type>::value,
|
||||
void
|
||||
>::type,
|
||||
|
||||
typename std::enable_if<
|
||||
std::is_constructible<jwt::string_view, typename std::remove_reference_t<T>::mapped_type>::value,
|
||||
void
|
||||
>::type,
|
||||
|
||||
decltype(
|
||||
std::declval<T&>().operator[](std::declval<typename std::remove_reference_t<T>::key_type>()),
|
||||
std::declval<T&>().begin(),
|
||||
std::declval<T&>().end(),
|
||||
(void)0
|
||||
)
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the type `T` models the ParameterConcept.
|
||||
*
|
||||
* Requirements on type `T` for matching the requirements:
|
||||
* a. The type must have a `get` method.
|
||||
*/
|
||||
template <typename T, typename=void>
|
||||
struct is_parameter_concept: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_parameter_concept<T,
|
||||
void_t<
|
||||
decltype(
|
||||
std::declval<T&>().get(),
|
||||
(void)0
|
||||
)
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Models SequenceConcept
|
||||
*/
|
||||
template <typename T, typename=void>
|
||||
struct is_sequence_concept: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
/// For array types
|
||||
template <typename T>
|
||||
struct is_sequence_concept<T,
|
||||
void_t<
|
||||
std::enable_if_t<std::is_array<std::decay_t<T>>::value>,
|
||||
|
||||
std::enable_if_t<
|
||||
std::is_constructible<jwt::string_view,
|
||||
std::remove_reference_t<decltype(*std::begin(std::declval<T&>()))>>::value
|
||||
>
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_sequence_concept<T,
|
||||
void_t<
|
||||
std::enable_if_t<
|
||||
std::is_base_of<
|
||||
std::forward_iterator_tag,
|
||||
typename std::remove_reference_t<T>::iterator::iterator_category
|
||||
>::value>,
|
||||
|
||||
std::enable_if_t<
|
||||
std::is_constructible<jwt::string_view, typename std::remove_reference_t<T>::value_type>::value
|
||||
>,
|
||||
|
||||
decltype(
|
||||
std::declval<T&>().begin(),
|
||||
std::declval<T&>().end(),
|
||||
(void)0
|
||||
)
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Find if a type is present in the typelist.
|
||||
* Eg: has_type<int, list<int, char, float>>{} == true
|
||||
* has_type<long, list<int, char, float>>{} == false
|
||||
*/
|
||||
template <typename F, typename T> struct has_type;
|
||||
|
||||
template <typename F>
|
||||
struct has_type<F, list<>>: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename F, typename... T>
|
||||
struct has_type<F, list<F, T...>>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename F, typename H, typename... T>
|
||||
struct has_type<F, list<H,T...>>: has_type<F, list<T...>>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* A pack of bools for the bool trick.
|
||||
*/
|
||||
template <bool... V>
|
||||
struct bool_pack {};
|
||||
|
||||
/**
|
||||
*/
|
||||
template <bool... B>
|
||||
using all_true = std::is_same<bool_pack<true, B...>, bool_pack<B..., true>>;
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename... T>
|
||||
using are_all_params = all_true<is_parameter_concept<T>::value...>;
|
||||
|
||||
|
||||
} // END namespace meta
|
||||
} // END namespace detail
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
136
externals/cpp-jwt/include/jwt/error_codes.hpp
vendored
Executable file
136
externals/cpp-jwt/include/jwt/error_codes.hpp
vendored
Executable file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ERROR_CODES_HPP
|
||||
#define CPP_JWT_ERROR_CODES_HPP
|
||||
|
||||
#include <system_error>
|
||||
|
||||
namespace jwt {
|
||||
/**
|
||||
* All the algorithm errors
|
||||
*/
|
||||
enum class AlgorithmErrc
|
||||
{
|
||||
SigningErr = 1,
|
||||
VerificationErr,
|
||||
KeyNotFoundErr,
|
||||
InvalidKeyErr,
|
||||
NoneAlgorithmUsed, // Not an actual error!
|
||||
};
|
||||
|
||||
/**
|
||||
* Algorithm error conditions
|
||||
* TODO: Remove it or use it!
|
||||
*/
|
||||
enum class AlgorithmFailureSource
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode error conditions
|
||||
*/
|
||||
enum class DecodeErrc
|
||||
{
|
||||
// No algorithms provided in decode API
|
||||
EmptyAlgoList = 1,
|
||||
// The JWT signature has incorrect format
|
||||
SignatureFormatError,
|
||||
// The JSON library failed to parse
|
||||
JsonParseError,
|
||||
// Algorithm field in header is missing
|
||||
AlgHeaderMiss,
|
||||
// Type field in header is missing
|
||||
TypHeaderMiss,
|
||||
// Unexpected type field value
|
||||
TypMismatch,
|
||||
// Found duplicate claims
|
||||
DuplClaims,
|
||||
// Key/Secret not passed as decode argument
|
||||
KeyNotPresent,
|
||||
// Key/secret passed as argument for NONE algorithm.
|
||||
// Not a hard error.
|
||||
KeyNotRequiredForNoneAlg,
|
||||
};
|
||||
|
||||
/**
|
||||
* Errors handled during verification process.
|
||||
*/
|
||||
enum class VerificationErrc
|
||||
{
|
||||
//Algorithms provided does not match with header
|
||||
InvalidAlgorithm = 1,
|
||||
//Token is expired at the time of decoding
|
||||
TokenExpired,
|
||||
//The issuer specified does not match with payload
|
||||
InvalidIssuer,
|
||||
//The subject specified does not match with payload
|
||||
InvalidSubject,
|
||||
//The field IAT is not present or is of invalid type
|
||||
InvalidIAT,
|
||||
//Checks for the existence of JTI
|
||||
//if validate_jti is passed in decode
|
||||
InvalidJTI,
|
||||
//The audience specified does not match with payload
|
||||
InvalidAudience,
|
||||
//Decoded before nbf time
|
||||
ImmatureSignature,
|
||||
//Signature match error
|
||||
InvalidSignature,
|
||||
// Invalid value type used for known claims
|
||||
TypeConversionError,
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
std::error_code make_error_code(AlgorithmErrc err);
|
||||
|
||||
/**
|
||||
*/
|
||||
std::error_code make_error_code(DecodeErrc err);
|
||||
|
||||
/**
|
||||
*/
|
||||
std::error_code make_error_code(VerificationErrc err);
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
|
||||
/**
|
||||
* Make the custom enum classes as error code
|
||||
* adaptable.
|
||||
*/
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct is_error_code_enum<jwt::AlgorithmErrc> : true_type {};
|
||||
|
||||
template <>
|
||||
struct is_error_code_enum<jwt::DecodeErrc>: true_type {};
|
||||
|
||||
template <>
|
||||
struct is_error_code_enum<jwt::VerificationErrc>: true_type {};
|
||||
}
|
||||
|
||||
#include "jwt/impl/error_codes.ipp"
|
||||
|
||||
#endif
|
305
externals/cpp-jwt/include/jwt/exceptions.hpp
vendored
Executable file
305
externals/cpp-jwt/include/jwt/exceptions.hpp
vendored
Executable file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_EXCEPTIONS_HPP
|
||||
#define CPP_JWT_EXCEPTIONS_HPP
|
||||
|
||||
#include <new>
|
||||
#include <string>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/**
|
||||
* Exception for allocation related failures in the
|
||||
* OpenSSL C APIs.
|
||||
*/
|
||||
class MemoryAllocationException final: public std::bad_alloc
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct MemoryAllocationException from a
|
||||
* string literal.
|
||||
*/
|
||||
template <size_t N>
|
||||
MemoryAllocationException(const char(&msg)[N])
|
||||
: msg_(&msg[0])
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char* what() const noexcept override
|
||||
{
|
||||
return msg_;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* msg_ = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown for failures in OpenSSL
|
||||
* APIs while signing.
|
||||
*/
|
||||
class SigningError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
SigningError(std::string msg)
|
||||
: std::runtime_error(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown for decode related errors.
|
||||
*/
|
||||
class DecodeError: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
DecodeError(std::string msg)
|
||||
: std::runtime_error(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A derived decode error for signature format
|
||||
* error.
|
||||
*/
|
||||
class SignatureFormatError final : public DecodeError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
SignatureFormatError(std::string msg)
|
||||
: DecodeError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A derived decode error for Key argument not present
|
||||
* error. Only thrown if the algorithm set is not NONE.
|
||||
*/
|
||||
class KeyNotPresentError final : public DecodeError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
KeyNotPresentError(std::string msg)
|
||||
: DecodeError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base class exception for all kinds of verification errors.
|
||||
* Verification errors are thrown only when the verify
|
||||
* decode parameter is set to true.
|
||||
*/
|
||||
class VerificationError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
VerificationError(std::string msg)
|
||||
: std::runtime_error(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the algorithm decoded in the header
|
||||
* is incorrect.
|
||||
*/
|
||||
class InvalidAlgorithmError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidAlgorithmError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the token is expired at the
|
||||
* time of decoding.
|
||||
*/
|
||||
class TokenExpiredError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
TokenExpiredError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the issuer claim does not match
|
||||
* with the one provided as part of decode argument.
|
||||
*/
|
||||
class InvalidIssuerError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidIssuerError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the audience claim does not match
|
||||
* with the one provided as part of decode argument.
|
||||
*/
|
||||
class InvalidAudienceError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidAudienceError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the subject claim does not match
|
||||
* with the one provided as part of decode argument.
|
||||
*/
|
||||
class InvalidSubjectError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidSubjectError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when verify_iat parameter is passed to
|
||||
* decode and IAT is not present.
|
||||
*/
|
||||
class InvalidIATError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidIATError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when validate_jti is asked for
|
||||
* in decode and jti claim is not present.
|
||||
*/
|
||||
class InvalidJTIError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidJTIError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the token is decoded at a time before
|
||||
* as specified in the `nbf` claim.
|
||||
*/
|
||||
class ImmatureSignatureError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
ImmatureSignatureError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the signature does not match in the verification process.
|
||||
*/
|
||||
class InvalidSignatureError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidSignatureError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class InvalidKeyError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidKeyError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when there type expectation mismatch
|
||||
* while verifying the values of registered claim names.
|
||||
*/
|
||||
class TypeConversionError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
TypeConversionError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
312
externals/cpp-jwt/include/jwt/impl/algorithm.ipp
vendored
Executable file
312
externals/cpp-jwt/include/jwt/impl/algorithm.ipp
vendored
Executable file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ALGORITHM_IPP
|
||||
#define CPP_JWT_ALGORITHM_IPP
|
||||
|
||||
namespace jwt {
|
||||
|
||||
template <typename Hasher>
|
||||
verify_result_t HMACSign<Hasher>::verify(
|
||||
const jwt::string_view key,
|
||||
const jwt::string_view head,
|
||||
const jwt::string_view jwt_sign)
|
||||
{
|
||||
std::error_code ec{};
|
||||
|
||||
unsigned char enc_buf[EVP_MAX_MD_SIZE];
|
||||
uint32_t enc_buf_len = 0;
|
||||
|
||||
unsigned char* res = HMAC(Hasher{}(),
|
||||
key.data(),
|
||||
static_cast<int>(key.length()),
|
||||
reinterpret_cast<const unsigned char*>(head.data()),
|
||||
head.length(),
|
||||
enc_buf,
|
||||
&enc_buf_len);
|
||||
if (!res) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return {false, ec};
|
||||
}
|
||||
if (enc_buf_len == 0) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return {false, ec};
|
||||
}
|
||||
|
||||
std::string b64_enc_str = jwt::base64_encode((const char*)&enc_buf[0], enc_buf_len);
|
||||
|
||||
if (!b64_enc_str.length()) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return {false, ec};
|
||||
}
|
||||
|
||||
// Make the base64 string url safe
|
||||
auto new_len = jwt::base64_uri_encode(&b64_enc_str[0], b64_enc_str.length());
|
||||
b64_enc_str.resize(new_len);
|
||||
|
||||
bool ret = (jwt::string_view{b64_enc_str} == jwt_sign);
|
||||
|
||||
return { ret, ec };
|
||||
}
|
||||
|
||||
|
||||
template <typename Hasher>
|
||||
verify_result_t PEMSign<Hasher>::verify(
|
||||
const jwt::string_view key,
|
||||
const jwt::string_view head,
|
||||
const jwt::string_view jwt_sign)
|
||||
{
|
||||
std::error_code ec{};
|
||||
std::string dec_sig = base64_uri_decode(jwt_sign.data(), jwt_sign.length());
|
||||
|
||||
BIO_uptr bufkey{
|
||||
BIO_new_mem_buf((void*)key.data(), static_cast<int>(key.length())),
|
||||
bio_deletor};
|
||||
|
||||
if (!bufkey) {
|
||||
throw MemoryAllocationException("BIO_new_mem_buf failed");
|
||||
}
|
||||
|
||||
EC_PKEY_uptr pkey{
|
||||
PEM_read_bio_PUBKEY(bufkey.get(), nullptr, nullptr, nullptr),
|
||||
ev_pkey_deletor};
|
||||
|
||||
if (!pkey) {
|
||||
ec = AlgorithmErrc::InvalidKeyErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
int pkey_type = EVP_PKEY_id(pkey.get());
|
||||
|
||||
if (pkey_type != Hasher::type) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
//Convert EC signature back to ASN1
|
||||
if (Hasher::type == EVP_PKEY_EC) {
|
||||
EC_SIG_uptr ec_sig{ECDSA_SIG_new(), ec_sig_deletor};
|
||||
if (!ec_sig) {
|
||||
throw MemoryAllocationException("ECDSA_SIG_new failed");
|
||||
}
|
||||
|
||||
//Get the actual ec_key
|
||||
EC_KEY_uptr ec_key{EVP_PKEY_get1_EC_KEY(pkey.get()), ec_key_deletor};
|
||||
if (!ec_key) {
|
||||
throw MemoryAllocationException("EVP_PKEY_get1_EC_KEY failed");
|
||||
}
|
||||
|
||||
unsigned int degree = EC_GROUP_get_degree(
|
||||
EC_KEY_get0_group(ec_key.get()));
|
||||
|
||||
unsigned int bn_len = (degree + 7) / 8;
|
||||
|
||||
if ((bn_len * 2) != dec_sig.length()) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
BIGNUM* ec_sig_r = BN_bin2bn((unsigned char*)dec_sig.data(), bn_len, nullptr);
|
||||
BIGNUM* ec_sig_s = BN_bin2bn((unsigned char*)dec_sig.data() + bn_len, bn_len, nullptr);
|
||||
|
||||
if (!ec_sig_r || !ec_sig_s) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
ECDSA_SIG_set0(ec_sig.get(), ec_sig_r, ec_sig_s);
|
||||
|
||||
size_t nlen = i2d_ECDSA_SIG(ec_sig.get(), nullptr);
|
||||
dec_sig.resize(nlen);
|
||||
|
||||
auto data = reinterpret_cast<unsigned char*>(&dec_sig[0]);
|
||||
nlen = i2d_ECDSA_SIG(ec_sig.get(), &data);
|
||||
|
||||
if (nlen == 0) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
}
|
||||
|
||||
EVP_MDCTX_uptr mdctx_ptr{EVP_MD_CTX_create(), evp_md_ctx_deletor};
|
||||
if (!mdctx_ptr) {
|
||||
throw MemoryAllocationException("EVP_MD_CTX_create failed");
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyInit(
|
||||
mdctx_ptr.get(), nullptr, Hasher{}(), nullptr, pkey.get()) != 1) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyUpdate(mdctx_ptr.get(), head.data(), head.length()) != 1) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyFinal(
|
||||
mdctx_ptr.get(), (unsigned char*)&dec_sig[0], dec_sig.length()) != 1) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
return { true, ec };
|
||||
}
|
||||
|
||||
template <typename Hasher>
|
||||
EVP_PKEY* PEMSign<Hasher>::load_key(
|
||||
const jwt::string_view key,
|
||||
std::error_code& ec)
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
BIO_uptr bio_ptr{
|
||||
BIO_new_mem_buf((void*)key.data(), static_cast<int>(key.length())),
|
||||
bio_deletor};
|
||||
|
||||
if (!bio_ptr) {
|
||||
throw MemoryAllocationException("BIO_new_mem_buf failed");
|
||||
}
|
||||
|
||||
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(
|
||||
bio_ptr.get(), nullptr, nullptr, nullptr);
|
||||
|
||||
if (!pkey) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pkey_type = EVP_PKEY_id(pkey);
|
||||
if (pkey_type != Hasher::type) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pkey;
|
||||
}
|
||||
|
||||
template <typename Hasher>
|
||||
std::string PEMSign<Hasher>::evp_digest(
|
||||
EVP_PKEY* pkey,
|
||||
const jwt::string_view data,
|
||||
std::error_code& ec)
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
EVP_MDCTX_uptr mdctx_ptr{EVP_MD_CTX_create(), evp_md_ctx_deletor};
|
||||
|
||||
if (!mdctx_ptr) {
|
||||
throw MemoryAllocationException("EVP_MD_CTX_create failed");
|
||||
}
|
||||
|
||||
//Initialiaze the digest algorithm
|
||||
if (EVP_DigestSignInit(
|
||||
mdctx_ptr.get(), nullptr, Hasher{}(), nullptr, pkey) != 1) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
//Update the digest with the input data
|
||||
if (EVP_DigestSignUpdate(mdctx_ptr.get(), data.data(), data.length()) != 1) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
|
||||
if (EVP_DigestSignFinal(mdctx_ptr.get(), nullptr, &len) != 1) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string sign;
|
||||
sign.resize(len);
|
||||
|
||||
//Get the signature
|
||||
if (EVP_DigestSignFinal(mdctx_ptr.get(), (unsigned char*)&sign[0], &len) != 1) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
return sign;
|
||||
}
|
||||
|
||||
template <typename Hasher>
|
||||
std::string PEMSign<Hasher>::public_key_ser(
|
||||
EVP_PKEY* pkey,
|
||||
jwt::string_view sign,
|
||||
std::error_code& ec)
|
||||
{
|
||||
// Get the EC_KEY representing a public key and
|
||||
// (optionaly) an associated private key
|
||||
std::string new_sign;
|
||||
ec.clear();
|
||||
|
||||
EC_KEY_uptr ec_key{EVP_PKEY_get1_EC_KEY(pkey), ec_key_deletor};
|
||||
|
||||
if (!ec_key) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint32_t degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key.get()));
|
||||
|
||||
ec_key.reset(nullptr);
|
||||
|
||||
auto char_ptr = &sign[0];
|
||||
|
||||
EC_SIG_uptr ec_sig{d2i_ECDSA_SIG(nullptr,
|
||||
(const unsigned char**)&char_ptr,
|
||||
static_cast<long>(sign.length())),
|
||||
ec_sig_deletor};
|
||||
|
||||
if (!ec_sig) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
const BIGNUM* ec_sig_r = nullptr;
|
||||
const BIGNUM* ec_sig_s = nullptr;
|
||||
|
||||
ECDSA_SIG_get0(ec_sig.get(), &ec_sig_r, &ec_sig_s);
|
||||
|
||||
int r_len = BN_num_bytes(ec_sig_r);
|
||||
int s_len = BN_num_bytes(ec_sig_s);
|
||||
int bn_len = static_cast<int>((degree + 7) / 8);
|
||||
|
||||
if ((r_len > bn_len) || (s_len > bn_len)) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto buf_len = 2 * bn_len;
|
||||
new_sign.resize(buf_len);
|
||||
|
||||
BN_bn2bin(ec_sig_r, (unsigned char*)&new_sign[0] + bn_len - r_len);
|
||||
BN_bn2bin(ec_sig_s, (unsigned char*)&new_sign[0] + buf_len - s_len);
|
||||
|
||||
return new_sign;
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
160
externals/cpp-jwt/include/jwt/impl/error_codes.ipp
vendored
Executable file
160
externals/cpp-jwt/include/jwt/impl/error_codes.ipp
vendored
Executable file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ERROR_CODES_IPP
|
||||
#define CPP_JWT_ERROR_CODES_IPP
|
||||
|
||||
namespace jwt {
|
||||
// Anonymous namespace
|
||||
namespace {
|
||||
|
||||
/**
|
||||
*/
|
||||
struct AlgorithmErrCategory: std::error_category
|
||||
{
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "algorithms";
|
||||
}
|
||||
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<AlgorithmErrc>(ev))
|
||||
{
|
||||
case AlgorithmErrc::SigningErr:
|
||||
return "signing failed";
|
||||
case AlgorithmErrc::VerificationErr:
|
||||
return "verification failed";
|
||||
case AlgorithmErrc::KeyNotFoundErr:
|
||||
return "key not provided";
|
||||
case AlgorithmErrc::NoneAlgorithmUsed:
|
||||
return "none algorithm used";
|
||||
case AlgorithmErrc::InvalidKeyErr:
|
||||
return "invalid key";
|
||||
};
|
||||
return "unknown algorithm error";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct DecodeErrorCategory: std::error_category
|
||||
{
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "decode";
|
||||
}
|
||||
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<DecodeErrc>(ev))
|
||||
{
|
||||
case DecodeErrc::EmptyAlgoList:
|
||||
return "empty algorithm list";
|
||||
case DecodeErrc::SignatureFormatError:
|
||||
return "signature format is incorrect";
|
||||
case DecodeErrc::AlgHeaderMiss:
|
||||
return "missing algorithm header";
|
||||
case DecodeErrc::TypHeaderMiss:
|
||||
return "missing type header";
|
||||
case DecodeErrc::TypMismatch:
|
||||
return "type mismatch";
|
||||
case DecodeErrc::JsonParseError:
|
||||
return "json parse failed";
|
||||
case DecodeErrc::DuplClaims:
|
||||
return "duplicate claims";
|
||||
case DecodeErrc::KeyNotPresent:
|
||||
return "key not present";
|
||||
case DecodeErrc::KeyNotRequiredForNoneAlg:
|
||||
return "key not required for NONE algorithm";
|
||||
};
|
||||
return "unknown decode error";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct VerificationErrorCategory: std::error_category
|
||||
{
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "verification";
|
||||
}
|
||||
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<VerificationErrc>(ev))
|
||||
{
|
||||
case VerificationErrc::InvalidAlgorithm:
|
||||
return "invalid algorithm";
|
||||
case VerificationErrc::TokenExpired:
|
||||
return "token expired";
|
||||
case VerificationErrc::InvalidIssuer:
|
||||
return "invalid issuer";
|
||||
case VerificationErrc::InvalidSubject:
|
||||
return "invalid subject";
|
||||
case VerificationErrc::InvalidAudience:
|
||||
return "invalid audience";
|
||||
case VerificationErrc::InvalidIAT:
|
||||
return "invalid iat";
|
||||
case VerificationErrc::InvalidJTI:
|
||||
return "invalid jti";
|
||||
case VerificationErrc::ImmatureSignature:
|
||||
return "immature signature";
|
||||
case VerificationErrc::InvalidSignature:
|
||||
return "invalid signature";
|
||||
case VerificationErrc::TypeConversionError:
|
||||
return "type conversion error";
|
||||
};
|
||||
return "unknown verification error";
|
||||
}
|
||||
};
|
||||
|
||||
// Create global object for the error categories
|
||||
const AlgorithmErrCategory theAlgorithmErrCategory {};
|
||||
|
||||
const DecodeErrorCategory theDecodeErrorCategory {};
|
||||
|
||||
const VerificationErrorCategory theVerificationErrorCategory {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Create the AlgorithmErrc error code
|
||||
inline std::error_code make_error_code(AlgorithmErrc err)
|
||||
{
|
||||
return { static_cast<int>(err), theAlgorithmErrCategory };
|
||||
}
|
||||
|
||||
inline std::error_code make_error_code(DecodeErrc err)
|
||||
{
|
||||
return { static_cast<int>(err), theDecodeErrorCategory };
|
||||
}
|
||||
|
||||
inline std::error_code make_error_code(VerificationErrc err)
|
||||
{
|
||||
return { static_cast<int>(err), theVerificationErrorCategory };
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
882
externals/cpp-jwt/include/jwt/impl/jwt.ipp
vendored
Executable file
882
externals/cpp-jwt/include/jwt/impl/jwt.ipp
vendored
Executable file
@@ -0,0 +1,882 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef JWT_IPP
|
||||
#define JWT_IPP
|
||||
|
||||
#include "jwt/config.hpp"
|
||||
#include "jwt/detail/meta.hpp"
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/**
|
||||
*/
|
||||
static inline void jwt_throw_exception(const std::error_code& ec);
|
||||
|
||||
template <typename T, typename Cond>
|
||||
std::string to_json_str(const T& obj, bool pretty)
|
||||
{
|
||||
return pretty ? obj.create_json_obj().dump(2)
|
||||
: obj.create_json_obj().dump()
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
std::ostream& write(std::ostream& os, const T& obj, bool pretty)
|
||||
{
|
||||
pretty ? (os << std::setw(2) << obj.create_json_obj())
|
||||
: (os << obj.create_json_obj())
|
||||
;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename Cond>
|
||||
std::ostream& operator<< (std::ostream& os, const T& obj)
|
||||
{
|
||||
os << obj.create_json_obj();
|
||||
return os;
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
|
||||
inline void jwt_header::decode(const jwt::string_view enc_str, std::error_code& ec)
|
||||
{
|
||||
ec.clear();
|
||||
std::string json_str = base64_decode(enc_str);
|
||||
|
||||
try {
|
||||
payload_ = json_t::parse(std::move(json_str));
|
||||
} catch(const std::exception&) {
|
||||
ec = DecodeErrc::JsonParseError;
|
||||
return;
|
||||
}
|
||||
|
||||
//Look for the algorithm field
|
||||
auto alg_itr = payload_.find("alg");
|
||||
if (alg_itr == payload_.end()) {
|
||||
ec = DecodeErrc::AlgHeaderMiss;
|
||||
return;
|
||||
}
|
||||
|
||||
alg_ = str_to_alg(alg_itr.value().get<std::string>());
|
||||
|
||||
if (alg_ != algorithm::NONE)
|
||||
{
|
||||
auto itr = payload_.find("typ");
|
||||
|
||||
if (itr != payload_.end()) {
|
||||
const auto& typ = itr.value().get<std::string>();
|
||||
if (strcasecmp(typ.c_str(), "JWT")) {
|
||||
ec = DecodeErrc::TypMismatch;
|
||||
return;
|
||||
}
|
||||
|
||||
typ_ = str_to_type(typ);
|
||||
}
|
||||
} else {
|
||||
//TODO:
|
||||
}
|
||||
|
||||
// Populate header
|
||||
for (auto it = payload_.begin(); it != payload_.end(); ++it) {
|
||||
auto ret = headers_.insert(it.key());
|
||||
if (!ret.second) {
|
||||
ec = DecodeErrc::DuplClaims;
|
||||
//ATTN: Dont stop the decode here
|
||||
//Not a hard error.
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
inline void jwt_header::decode(const jwt::string_view enc_str)
|
||||
{
|
||||
std::error_code ec;
|
||||
decode(enc_str, ec);
|
||||
if (ec) {
|
||||
throw DecodeError(ec.message());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
inline void jwt_payload::decode(const jwt::string_view enc_str, std::error_code& ec)
|
||||
{
|
||||
ec.clear();
|
||||
std::string json_str = base64_decode(enc_str);
|
||||
try {
|
||||
payload_ = json_t::parse(std::move(json_str));
|
||||
} catch(const std::exception&) {
|
||||
ec = DecodeErrc::JsonParseError;
|
||||
return;
|
||||
}
|
||||
//populate the claims set
|
||||
for (auto it = payload_.begin(); it != payload_.end(); ++it) {
|
||||
auto ret = claim_names_.insert(it.key());
|
||||
if (!ret.second) {
|
||||
ec = DecodeErrc::DuplClaims;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
inline void jwt_payload::decode(const jwt::string_view enc_str)
|
||||
{
|
||||
std::error_code ec;
|
||||
decode(enc_str, ec);
|
||||
if (ec) {
|
||||
throw DecodeError(ec.message());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
inline std::string jwt_signature::encode(const jwt_header& header,
|
||||
const jwt_payload& payload,
|
||||
std::error_code& ec)
|
||||
{
|
||||
std::string jwt_msg;
|
||||
ec.clear();
|
||||
//TODO: Optimize allocations
|
||||
|
||||
sign_func_t sign_fn = get_sign_algorithm_impl(header);
|
||||
|
||||
std::string hdr_sign = header.base64_encode();
|
||||
std::string pld_sign = payload.base64_encode();
|
||||
std::string data = hdr_sign + '.' + pld_sign;
|
||||
|
||||
auto res = sign_fn(key_, data);
|
||||
|
||||
if (res.second && res.second != AlgorithmErrc::NoneAlgorithmUsed) {
|
||||
ec = res.second;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string b64hash;
|
||||
|
||||
if (!res.second) {
|
||||
b64hash = base64_encode(res.first.c_str(), res.first.length());
|
||||
}
|
||||
|
||||
auto new_len = base64_uri_encode(&b64hash[0], b64hash.length());
|
||||
b64hash.resize(new_len);
|
||||
|
||||
jwt_msg = data + '.' + b64hash;
|
||||
|
||||
return jwt_msg;
|
||||
}
|
||||
|
||||
inline verify_result_t jwt_signature::verify(const jwt_header& header,
|
||||
const jwt::string_view hdr_pld_sign,
|
||||
const jwt::string_view jwt_sign)
|
||||
{
|
||||
verify_func_t verify_fn = get_verify_algorithm_impl(header);
|
||||
return verify_fn(key_, hdr_pld_sign, jwt_sign);
|
||||
}
|
||||
|
||||
|
||||
inline sign_func_t
|
||||
jwt_signature::get_sign_algorithm_impl(const jwt_header& hdr) const noexcept
|
||||
{
|
||||
sign_func_t ret = nullptr;
|
||||
|
||||
switch (hdr.algo()) {
|
||||
case algorithm::HS256:
|
||||
ret = HMACSign<algo::HS256>::sign;
|
||||
break;
|
||||
case algorithm::HS384:
|
||||
ret = HMACSign<algo::HS384>::sign;
|
||||
break;
|
||||
case algorithm::HS512:
|
||||
ret = HMACSign<algo::HS512>::sign;
|
||||
break;
|
||||
case algorithm::NONE:
|
||||
ret = HMACSign<algo::NONE>::sign;
|
||||
break;
|
||||
case algorithm::RS256:
|
||||
ret = PEMSign<algo::RS256>::sign;
|
||||
break;
|
||||
case algorithm::RS384:
|
||||
ret = PEMSign<algo::RS384>::sign;
|
||||
break;
|
||||
case algorithm::RS512:
|
||||
ret = PEMSign<algo::RS512>::sign;
|
||||
break;
|
||||
case algorithm::ES256:
|
||||
ret = PEMSign<algo::ES256>::sign;
|
||||
break;
|
||||
case algorithm::ES384:
|
||||
ret = PEMSign<algo::ES384>::sign;
|
||||
break;
|
||||
case algorithm::ES512:
|
||||
ret = PEMSign<algo::ES512>::sign;
|
||||
break;
|
||||
default:
|
||||
assert (0 && "Code not reached");
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline verify_func_t
|
||||
jwt_signature::get_verify_algorithm_impl(const jwt_header& hdr) const noexcept
|
||||
{
|
||||
verify_func_t ret = nullptr;
|
||||
|
||||
switch (hdr.algo()) {
|
||||
case algorithm::HS256:
|
||||
ret = HMACSign<algo::HS256>::verify;
|
||||
break;
|
||||
case algorithm::HS384:
|
||||
ret = HMACSign<algo::HS384>::verify;
|
||||
break;
|
||||
case algorithm::HS512:
|
||||
ret = HMACSign<algo::HS512>::verify;
|
||||
break;
|
||||
case algorithm::NONE:
|
||||
ret = HMACSign<algo::NONE>::verify;
|
||||
break;
|
||||
case algorithm::RS256:
|
||||
ret = PEMSign<algo::RS256>::verify;
|
||||
break;
|
||||
case algorithm::RS384:
|
||||
ret = PEMSign<algo::RS384>::verify;
|
||||
break;
|
||||
case algorithm::RS512:
|
||||
ret = PEMSign<algo::RS512>::verify;
|
||||
break;
|
||||
case algorithm::ES256:
|
||||
ret = PEMSign<algo::ES256>::verify;
|
||||
break;
|
||||
case algorithm::ES384:
|
||||
ret = PEMSign<algo::ES384>::verify;
|
||||
break;
|
||||
case algorithm::ES512:
|
||||
ret = PEMSign<algo::ES512>::verify;
|
||||
break;
|
||||
default:
|
||||
assert (0 && "Code not reached");
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
template <typename First, typename... Rest,
|
||||
typename SFINAE_COND>
|
||||
jwt_object::jwt_object(
|
||||
First&& first, Rest&&... rest)
|
||||
{
|
||||
static_assert (detail::meta::is_parameter_concept<First>::value &&
|
||||
detail::meta::are_all_params<Rest...>::value,
|
||||
"All constructor argument types must model ParameterConcept");
|
||||
|
||||
set_parameters(std::forward<First>(first), std::forward<Rest>(rest)...);
|
||||
}
|
||||
|
||||
template <typename Map, typename... Rest>
|
||||
void jwt_object::set_parameters(
|
||||
params::detail::payload_param<Map>&& payload, Rest&&... rargs)
|
||||
{
|
||||
for (const auto& elem : payload.get()) {
|
||||
payload_.add_claim(std::move(elem.first), std::move(elem.second));
|
||||
}
|
||||
set_parameters(std::forward<Rest>(rargs)...);
|
||||
}
|
||||
|
||||
template <typename... Rest>
|
||||
void jwt_object::set_parameters(
|
||||
params::detail::secret_param secret, Rest&&... rargs)
|
||||
{
|
||||
secret_.assign(secret.get().data(), secret.get().length());
|
||||
set_parameters(std::forward<Rest>(rargs)...);
|
||||
}
|
||||
|
||||
template <typename... Rest>
|
||||
void jwt_object::set_parameters(
|
||||
params::detail::algorithm_param alg, Rest&&... rargs)
|
||||
{
|
||||
header_.algo(alg.get());
|
||||
set_parameters(std::forward<Rest>(rargs)...);
|
||||
}
|
||||
|
||||
template <typename Map, typename... Rest>
|
||||
void jwt_object::set_parameters(
|
||||
params::detail::headers_param<Map>&& header, Rest&&... rargs)
|
||||
{
|
||||
for (const auto& elem : header.get()) {
|
||||
header_.add_header(std::move(elem.first), std::move(elem.second));
|
||||
}
|
||||
|
||||
set_parameters(std::forward<Rest>(rargs)...);
|
||||
}
|
||||
|
||||
inline void jwt_object::set_parameters()
|
||||
{
|
||||
//sentinel call
|
||||
return;
|
||||
}
|
||||
|
||||
inline jwt_object& jwt_object::add_claim(const jwt::string_view name, system_time_t tp)
|
||||
{
|
||||
return add_claim(
|
||||
name,
|
||||
std::chrono::duration_cast<
|
||||
std::chrono::seconds>(tp.time_since_epoch()).count()
|
||||
);
|
||||
}
|
||||
|
||||
inline jwt_object& jwt_object::remove_claim(const jwt::string_view name)
|
||||
{
|
||||
payload_.remove_claim(name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline std::string jwt_object::signature(std::error_code& ec) const
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
//key/secret should be set for any algorithm except NONE
|
||||
if (header().algo() != jwt::algorithm::NONE) {
|
||||
if (secret_.length() == 0) {
|
||||
ec = AlgorithmErrc::KeyNotFoundErr;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
jwt_signature jws{secret_};
|
||||
return jws.encode(header_, payload_, ec);
|
||||
}
|
||||
|
||||
inline std::string jwt_object::signature() const
|
||||
{
|
||||
std::error_code ec;
|
||||
std::string res = signature(ec);
|
||||
if (ec) {
|
||||
throw SigningError(ec.message());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Params, typename SequenceT>
|
||||
std::error_code jwt_object::verify(
|
||||
const Params& dparams,
|
||||
const params::detail::algorithms_param<SequenceT>& algos) const
|
||||
{
|
||||
std::error_code ec{};
|
||||
|
||||
//Verify if the algorithm set in the header
|
||||
//is any of the one expected by the client.
|
||||
auto fitr = std::find_if(algos.get().begin(),
|
||||
algos.get().end(),
|
||||
[this](const auto& elem)
|
||||
{
|
||||
return jwt::str_to_alg(elem) == this->header().algo();
|
||||
});
|
||||
|
||||
if (fitr == algos.get().end()) {
|
||||
ec = VerificationErrc::InvalidAlgorithm;
|
||||
return ec;
|
||||
}
|
||||
|
||||
//Check for the expiry timings
|
||||
if (has_claim(registered_claims::expiration)) {
|
||||
auto curr_time =
|
||||
std::chrono::duration_cast<
|
||||
std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
auto p_exp = payload()
|
||||
.get_claim_value<uint64_t>(registered_claims::expiration);
|
||||
|
||||
if (static_cast<uint64_t>(curr_time) > static_cast<uint64_t>(p_exp + dparams.leeway)) {
|
||||
ec = VerificationErrc::TokenExpired;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check for issuer
|
||||
if (dparams.has_issuer)
|
||||
{
|
||||
if (has_claim(registered_claims::issuer))
|
||||
{
|
||||
const std::string& p_issuer = payload()
|
||||
.get_claim_value<std::string>(registered_claims::issuer);
|
||||
|
||||
if (p_issuer != dparams.issuer) {
|
||||
ec = VerificationErrc::InvalidIssuer;
|
||||
return ec;
|
||||
}
|
||||
} else {
|
||||
ec = VerificationErrc::InvalidIssuer;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check for audience
|
||||
if (dparams.has_aud)
|
||||
{
|
||||
if (has_claim(registered_claims::audience))
|
||||
{
|
||||
const std::string& p_aud = payload()
|
||||
.get_claim_value<std::string>(registered_claims::audience);
|
||||
|
||||
if (p_aud != dparams.aud) {
|
||||
ec = VerificationErrc::InvalidAudience;
|
||||
return ec;
|
||||
}
|
||||
} else {
|
||||
ec = VerificationErrc::InvalidAudience;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check the subject
|
||||
if (dparams.has_sub)
|
||||
{
|
||||
if (has_claim(registered_claims::subject))
|
||||
{
|
||||
const std::string& p_sub = payload()
|
||||
.get_claim_value<std::string>(registered_claims::subject);
|
||||
if (p_sub != dparams.sub) {
|
||||
ec = VerificationErrc::InvalidSubject;
|
||||
return ec;
|
||||
}
|
||||
} else {
|
||||
ec = VerificationErrc::InvalidSubject;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check for NBF
|
||||
if (has_claim(registered_claims::not_before))
|
||||
{
|
||||
auto curr_time =
|
||||
std::chrono::duration_cast<
|
||||
std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
auto p_exp = payload()
|
||||
.get_claim_value<uint64_t>(registered_claims::not_before);
|
||||
|
||||
if (static_cast<uint64_t>(p_exp - dparams.leeway) > static_cast<uint64_t>(curr_time)) {
|
||||
ec = VerificationErrc::ImmatureSignature;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check IAT validation
|
||||
if (dparams.validate_iat) {
|
||||
if (!has_claim(registered_claims::issued_at)) {
|
||||
ec = VerificationErrc::InvalidIAT;
|
||||
return ec;
|
||||
} else {
|
||||
// Will throw type conversion error
|
||||
auto val = payload()
|
||||
.get_claim_value<uint64_t>(registered_claims::issued_at);
|
||||
(void)val;
|
||||
}
|
||||
}
|
||||
|
||||
//Check JTI validation
|
||||
if (dparams.validate_jti) {
|
||||
if (!has_claim("jti")) {
|
||||
ec = VerificationErrc::InvalidJTI;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
|
||||
inline std::array<jwt::string_view, 3>
|
||||
jwt_object::three_parts(const jwt::string_view enc_str)
|
||||
{
|
||||
std::array<jwt::string_view, 3> result;
|
||||
|
||||
size_t fpos = enc_str.find_first_of('.');
|
||||
assert (fpos != jwt::string_view::npos);
|
||||
|
||||
result[0] = jwt::string_view{&enc_str[0], fpos};
|
||||
|
||||
size_t spos = enc_str.find_first_of('.', fpos + 1);
|
||||
|
||||
result[1] = jwt::string_view{&enc_str[fpos + 1], spos - fpos - 1};
|
||||
|
||||
if (spos + 1 != enc_str.length()) {
|
||||
result[2] = jwt::string_view{&enc_str[spos + 1], enc_str.length() - spos - 1};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::secret_param s, Rest&&... args)
|
||||
{
|
||||
dparams.secret.assign(s.get().data(), s.get().length());
|
||||
dparams.has_secret = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename T, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::secret_function_param<T>&& s, Rest&&... args)
|
||||
{
|
||||
dparams.secret = s.get(*dparams.payload_ptr);
|
||||
dparams.has_secret = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::leeway_param l, Rest&&... args)
|
||||
{
|
||||
dparams.leeway = l.get();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::verify_param v, Rest&&... args)
|
||||
{
|
||||
dparams.verify = v.get();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::issuer_param i, Rest&&... args)
|
||||
{
|
||||
dparams.issuer = std::move(i).get();
|
||||
dparams.has_issuer = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::audience_param a, Rest&&... args)
|
||||
{
|
||||
dparams.aud = std::move(a).get();
|
||||
dparams.has_aud = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::subject_param s, Rest&&... args)
|
||||
{
|
||||
dparams.sub = std::move(s).get();
|
||||
dparams.has_sub = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::validate_iat_param v, Rest&&... args)
|
||||
{
|
||||
dparams.validate_iat = v.get();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::validate_jti_param v, Rest&&... args)
|
||||
{
|
||||
dparams.validate_jti = v.get();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams)
|
||||
{
|
||||
(void) dparams; // prevent -Wunused-parameter with gcc
|
||||
return;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
|
||||
template <typename SequenceT, typename... Args>
|
||||
jwt_object decode(const jwt::string_view enc_str,
|
||||
const params::detail::algorithms_param<SequenceT>& algos,
|
||||
std::error_code& ec,
|
||||
Args&&... args)
|
||||
{
|
||||
ec.clear();
|
||||
jwt_object obj;
|
||||
|
||||
if (algos.get().size() == 0) {
|
||||
ec = DecodeErrc::EmptyAlgoList;
|
||||
return obj;
|
||||
}
|
||||
|
||||
struct decode_params
|
||||
{
|
||||
/// key to decode the JWS
|
||||
bool has_secret = false;
|
||||
std::string secret;
|
||||
|
||||
/// Verify parameter. Defaulted to true.
|
||||
bool verify = true;
|
||||
|
||||
/// Leeway parameter. Defaulted to zero seconds.
|
||||
uint32_t leeway = 0;
|
||||
|
||||
///The issuer
|
||||
//TODO: optional type
|
||||
bool has_issuer = false;
|
||||
std::string issuer;
|
||||
|
||||
///The audience
|
||||
//TODO: optional type
|
||||
bool has_aud = false;
|
||||
std::string aud;
|
||||
|
||||
//The subject
|
||||
//TODO: optional type
|
||||
bool has_sub = false;
|
||||
std::string sub;
|
||||
|
||||
//Validate IAT
|
||||
bool validate_iat = false;
|
||||
|
||||
//Validate JTI
|
||||
bool validate_jti = false;
|
||||
const jwt_payload* payload_ptr = 0;
|
||||
};
|
||||
|
||||
decode_params dparams{};
|
||||
|
||||
|
||||
//Signature must have atleast 2 dots
|
||||
auto dot_cnt = std::count_if(std::begin(enc_str), std::end(enc_str),
|
||||
[](char ch) { return ch == '.'; });
|
||||
if (dot_cnt < 2) {
|
||||
ec = DecodeErrc::SignatureFormatError;
|
||||
return obj;
|
||||
}
|
||||
|
||||
auto parts = jwt_object::three_parts(enc_str);
|
||||
|
||||
//throws decode error
|
||||
jwt_header hdr{};
|
||||
hdr.decode(parts[0], ec);
|
||||
if (ec) {
|
||||
return obj;
|
||||
}
|
||||
//obj.header(jwt_header{parts[0]});
|
||||
obj.header(std::move(hdr));
|
||||
|
||||
//If the algorithm is not NONE, it must not
|
||||
//have more than two dots ('.') and the split
|
||||
//must result in three strings with some length.
|
||||
if (obj.header().algo() != jwt::algorithm::NONE) {
|
||||
if (dot_cnt > 2) {
|
||||
ec = DecodeErrc::SignatureFormatError;
|
||||
return obj;
|
||||
}
|
||||
if (parts[2].length() == 0) {
|
||||
ec = DecodeErrc::SignatureFormatError;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
//throws decode error
|
||||
jwt_payload payload{};
|
||||
payload.decode(parts[1], ec);
|
||||
if (ec) {
|
||||
return obj;
|
||||
}
|
||||
obj.payload(std::move(payload));
|
||||
dparams.payload_ptr = & obj.payload();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Args>(args)...);
|
||||
if (dparams.verify) {
|
||||
try {
|
||||
ec = obj.verify(dparams, algos);
|
||||
} catch (const json_ns::detail::type_error&) {
|
||||
ec = VerificationErrc::TypeConversionError;
|
||||
}
|
||||
|
||||
if (ec) return obj;
|
||||
|
||||
//Verify the signature only if some algorithm was used
|
||||
if (obj.header().algo() != algorithm::NONE)
|
||||
{
|
||||
if (!dparams.has_secret) {
|
||||
ec = DecodeErrc::KeyNotPresent;
|
||||
return obj;
|
||||
}
|
||||
jwt_signature jsign{dparams.secret};
|
||||
|
||||
// Length of the encoded header and payload only.
|
||||
// Addition of '1' to account for the '.' character.
|
||||
auto l = parts[0].length() + 1 + parts[1].length();
|
||||
|
||||
//MemoryAllocationError is not caught
|
||||
verify_result_t res = jsign.verify(obj.header(), enc_str.substr(0, l), parts[2]);
|
||||
if (res.second) {
|
||||
ec = res.second;
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (!res.first) {
|
||||
ec = VerificationErrc::InvalidSignature;
|
||||
return obj;
|
||||
}
|
||||
} else {
|
||||
ec = AlgorithmErrc::NoneAlgorithmUsed;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename SequenceT, typename... Args>
|
||||
jwt_object decode(const jwt::string_view enc_str,
|
||||
const params::detail::algorithms_param<SequenceT>& algos,
|
||||
Args&&... args)
|
||||
{
|
||||
std::error_code ec{};
|
||||
auto jwt_obj = decode(enc_str,
|
||||
algos,
|
||||
ec,
|
||||
std::forward<Args>(args)...);
|
||||
|
||||
if (ec) {
|
||||
jwt_throw_exception(ec);
|
||||
}
|
||||
|
||||
return jwt_obj;
|
||||
}
|
||||
|
||||
|
||||
void jwt_throw_exception(const std::error_code& ec)
|
||||
{
|
||||
const auto& cat = ec.category();
|
||||
|
||||
if (&cat == &theVerificationErrorCategory ||
|
||||
std::string(cat.name()) == std::string(theVerificationErrorCategory.name()))
|
||||
{
|
||||
switch (static_cast<VerificationErrc>(ec.value()))
|
||||
{
|
||||
case VerificationErrc::InvalidAlgorithm:
|
||||
{
|
||||
throw InvalidAlgorithmError(ec.message());
|
||||
}
|
||||
case VerificationErrc::TokenExpired:
|
||||
{
|
||||
throw TokenExpiredError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidIssuer:
|
||||
{
|
||||
throw InvalidIssuerError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidAudience:
|
||||
{
|
||||
throw InvalidAudienceError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidSubject:
|
||||
{
|
||||
throw InvalidSubjectError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidIAT:
|
||||
{
|
||||
throw InvalidIATError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidJTI:
|
||||
{
|
||||
throw InvalidJTIError(ec.message());
|
||||
}
|
||||
case VerificationErrc::ImmatureSignature:
|
||||
{
|
||||
throw ImmatureSignatureError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidSignature:
|
||||
{
|
||||
throw InvalidSignatureError(ec.message());
|
||||
}
|
||||
case VerificationErrc::TypeConversionError:
|
||||
{
|
||||
throw TypeConversionError(ec.message());
|
||||
}
|
||||
default:
|
||||
assert (0 && "Unknown error code");
|
||||
};
|
||||
}
|
||||
|
||||
if (&cat == &theDecodeErrorCategory ||
|
||||
std::string(cat.name()) == std::string(theDecodeErrorCategory.name()))
|
||||
{
|
||||
switch (static_cast<DecodeErrc>(ec.value()))
|
||||
{
|
||||
case DecodeErrc::SignatureFormatError:
|
||||
{
|
||||
throw SignatureFormatError(ec.message());
|
||||
}
|
||||
case DecodeErrc::KeyNotPresent:
|
||||
{
|
||||
throw KeyNotPresentError(ec.message());
|
||||
}
|
||||
case DecodeErrc::KeyNotRequiredForNoneAlg:
|
||||
{
|
||||
// Not an error. Just to be ignored.
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw DecodeError(ec.message());
|
||||
}
|
||||
};
|
||||
|
||||
assert (0 && "Unknown error code");
|
||||
}
|
||||
|
||||
if (&cat == &theAlgorithmErrCategory ||
|
||||
std::string(cat.name()) == std::string(theAlgorithmErrCategory.name()))
|
||||
{
|
||||
switch (static_cast<AlgorithmErrc>(ec.value()))
|
||||
{
|
||||
case AlgorithmErrc::InvalidKeyErr:
|
||||
{
|
||||
throw InvalidKeyError(ec.message());
|
||||
}
|
||||
case AlgorithmErrc::VerificationErr:
|
||||
{
|
||||
throw InvalidSignatureError(ec.message());
|
||||
}
|
||||
case AlgorithmErrc::NoneAlgorithmUsed:
|
||||
{
|
||||
//Not an error actually.
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert (0 && "Unknown error code or not to be treated as an error");
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
|
||||
#endif
|
87
externals/cpp-jwt/include/jwt/impl/stack_alloc.ipp
vendored
Executable file
87
externals/cpp-jwt/include/jwt/impl/stack_alloc.ipp
vendored
Executable file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STACK_ALLOC_IPP
|
||||
#define STACK_ALLOC_IPP
|
||||
|
||||
namespace jwt {
|
||||
|
||||
template <size_t N, size_t alignment>
|
||||
template <size_t reqested_alignment>
|
||||
char* Arena<N, alignment>::allocate(size_t n) noexcept
|
||||
{
|
||||
static_assert (reqested_alignment <= alignment,
|
||||
"Requested alignment is too small for this arena");
|
||||
|
||||
assert (pointer_in_storage(ptr_) &&
|
||||
"No more space in the arena or it has outgrown its capacity");
|
||||
|
||||
n = align_up(n);
|
||||
|
||||
if ((ptr_ + n) <= (buf_ + N)) {
|
||||
char* ret = ptr_;
|
||||
ptr_ += n;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
assert (0 && "Code should not reach here");
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <size_t N, size_t alignment>
|
||||
void Arena<N, alignment>::deallocate(char* p, size_t n) noexcept
|
||||
{
|
||||
assert (pointer_in_storage(p) &&
|
||||
"The address to de deleted does not lie inside the storage");
|
||||
|
||||
n = align_up(n);
|
||||
|
||||
if ((p + n) == ptr_) {
|
||||
ptr_ = p;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T, size_t N, size_t alignment>
|
||||
T* stack_alloc<T, N, alignment>::allocate(size_t n) noexcept
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
arena_.template allocate<alignof(T)>(n * sizeof(T))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename T, size_t N, size_t alignment>
|
||||
void stack_alloc<T, N, alignment>::deallocate(T* p, size_t n) noexcept
|
||||
{
|
||||
arena_.deallocate(reinterpret_cast<char*>(p), n);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
339
externals/cpp-jwt/include/jwt/impl/string_view.ipp
vendored
Executable file
339
externals/cpp-jwt/include/jwt/impl/string_view.ipp
vendored
Executable file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef JWT_STRING_VIEW_IPP
|
||||
#define JWT_STRING_VIEW_IPP
|
||||
|
||||
namespace jwt {
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type n) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (n < (len_ - pos) && "Comparison size out of bounds");
|
||||
|
||||
if (n == 0) {
|
||||
return pos <= len_ ? pos : npos;
|
||||
}
|
||||
if (n <= len_) {
|
||||
for (; pos <= (len_ - n); ++pos) {
|
||||
if (traits_type::eq(data_[pos], str[0]) &&
|
||||
traits_type::compare(data_ + pos + 1, str + 1, n - 1) == 0) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::rfind(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type n) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (pos < len_ && "Position out of bounds");
|
||||
|
||||
if (n <= len_) {
|
||||
pos = std::min(len_ - n, pos);
|
||||
do {
|
||||
if (traits_type::eq(data_[pos], str[0]) &&
|
||||
traits_type::compare(data_ + pos + 1, str + 1, n - 1) == 0) {
|
||||
return pos;
|
||||
}
|
||||
} while (pos-- != 0);
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find(
|
||||
const CharT ch,
|
||||
size_type pos) const noexcept -> size_type
|
||||
{
|
||||
if (pos < len_) {
|
||||
for (size_type i = pos; i < len_; ++i) {
|
||||
if (traits_type::eq(data_[i], ch)) return i;
|
||||
}
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::rfind(
|
||||
const CharT ch,
|
||||
size_type pos) const noexcept -> size_type
|
||||
{
|
||||
if (pos < len_) {
|
||||
do {
|
||||
if (traits_type::eq(data_[pos], ch)) {
|
||||
return pos;
|
||||
}
|
||||
} while (pos-- != 0);
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_first_of(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type count) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
|
||||
for (size_type i = pos; i < len_; ++i) {
|
||||
auto p = traits_type::find(str, count, data_[i]);
|
||||
if (p) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_last_of(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type count) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (pos < len_ && "Position must be within the bounds of the view");
|
||||
size_type siz = len_;
|
||||
|
||||
if (siz && count) {
|
||||
siz = std::min(pos, siz);
|
||||
|
||||
do {
|
||||
auto p = traits_type::find(str, count, data_[siz]);
|
||||
if (p) {
|
||||
return siz;
|
||||
}
|
||||
} while (siz-- != 0);
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_first_not_of(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type n) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (pos < len_&& "Position must be within the bounds of the view");
|
||||
|
||||
for (size_type i = pos; i < len_; ++i)
|
||||
{
|
||||
auto p = traits_type::find(str, n, data_[i]);
|
||||
if (!p) return i;
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_last_not_of(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type n) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (pos < len_ && "Position must be within the bounds of the view");
|
||||
|
||||
do {
|
||||
for (size_type i = 0; i < n; ++i) {
|
||||
if (!traits_type::eq(data_[pos], str[i])) return pos;
|
||||
}
|
||||
} while (pos-- != 0);
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_first_not_of(
|
||||
CharT ch,
|
||||
size_type pos) const noexcept -> size_type
|
||||
{
|
||||
assert (pos < len_&& "Position must be within the bounds of the view");
|
||||
|
||||
for (size_type i = pos; i < len_; ++i) {
|
||||
if (!traits_type::eq(data_[i], ch)) return i;
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_last_not_of(
|
||||
CharT ch,
|
||||
size_type pos) const noexcept -> size_type
|
||||
{
|
||||
assert (pos < len_ && "Position must be within the bounds of the view");
|
||||
|
||||
do {
|
||||
if (!traits_type::eq(data_[pos], ch)) return pos;
|
||||
} while (pos-- != 0);
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Comparison Operators
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator== (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
if (a.length() != b.length()) return false;
|
||||
using traits_type = typename basic_string_view<CharT, Traits>::traits_type;
|
||||
using size_type = typename basic_string_view<CharT, Traits>::size_type;
|
||||
|
||||
for (size_type i = 0; i < a.length(); ++i) {
|
||||
if (!traits_type::eq(a[i], b[i])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator!= (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return !( a == b );
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator< (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return a.compare(b) < 0;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator> (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return a.compare(b) > 0;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator<= (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return a.compare(b) <= 0;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator>= (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return a.compare(b) >= 0;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::ostream& operator<< (std::ostream& os, basic_string_view<CharT, Traits> sv)
|
||||
{
|
||||
os.write(sv.data(), sv.length());
|
||||
return os;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
* Copy of gcc implementation of murmurhash
|
||||
* hash_bytes.cc
|
||||
*/
|
||||
|
||||
inline size_t
|
||||
unaligned_load(const char* p) noexcept
|
||||
{
|
||||
std::size_t result;
|
||||
std::memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline size_t
|
||||
hash_bytes(const void* ptr, size_t len, size_t seed) noexcept
|
||||
{
|
||||
const size_t m = 0x5bd1e995;
|
||||
size_t hash = seed ^ len;
|
||||
const char* buf = static_cast<const char*>(ptr);
|
||||
|
||||
// Mix 4 bytes at a time into the hash.
|
||||
while(len >= 4)
|
||||
{
|
||||
size_t k = unaligned_load(buf);
|
||||
k *= m;
|
||||
k ^= k >> 24;
|
||||
k *= m;
|
||||
hash *= m;
|
||||
hash ^= k;
|
||||
buf += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
// Handle the last few bytes of the input array.
|
||||
switch(len)
|
||||
{
|
||||
case 3:
|
||||
hash ^= static_cast<unsigned char>(buf[2]) << 16;
|
||||
//FALLTHROUGH
|
||||
case 2:
|
||||
hash ^= static_cast<unsigned char>(buf[1]) << 8;
|
||||
//FALLTHROUGH
|
||||
case 1:
|
||||
hash ^= static_cast<unsigned char>(buf[0]);
|
||||
hash *= m;
|
||||
};
|
||||
|
||||
// Do a few final mixes of the hash.
|
||||
hash ^= hash >> 13;
|
||||
hash *= m;
|
||||
hash ^= hash >> 15;
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
/// Provide a hash specialization
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<jwt::string_view>
|
||||
{
|
||||
size_t operator()(const jwt::string_view& sv) const noexcept
|
||||
{
|
||||
return jwt::hash_bytes((void*)sv.data(), sv.length(), static_cast<size_t>(0xc70f6907UL));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
25447
externals/cpp-jwt/include/jwt/json/json.hpp
vendored
Executable file
25447
externals/cpp-jwt/include/jwt/json/json.hpp
vendored
Executable file
File diff suppressed because it is too large
Load Diff
24
externals/cpp-jwt/include/jwt/json/test_json.cc
vendored
Executable file
24
externals/cpp-jwt/include/jwt/json/test_json.cc
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#if defined( CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
|
||||
#include "./json.hpp"
|
||||
#else
|
||||
#include "nlohmann/json.hpp"
|
||||
#endif
|
||||
using json = nlohmann::json;
|
||||
|
||||
void basic_json_test()
|
||||
{
|
||||
json obj = json::object();
|
||||
obj["test"] = "value-test";
|
||||
obj["test-int"] = 42;
|
||||
|
||||
std::string jstr = obj.dump(0);
|
||||
std::cout << jstr << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_json_test();
|
||||
|
||||
return 0;
|
||||
}
|
1203
externals/cpp-jwt/include/jwt/jwt.hpp
vendored
Executable file
1203
externals/cpp-jwt/include/jwt/jwt.hpp
vendored
Executable file
File diff suppressed because it is too large
Load Diff
451
externals/cpp-jwt/include/jwt/parameters.hpp
vendored
Executable file
451
externals/cpp-jwt/include/jwt/parameters.hpp
vendored
Executable file
@@ -0,0 +1,451 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_PARAMETERS_HPP
|
||||
#define CPP_JWT_PARAMETERS_HPP
|
||||
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "jwt/algorithm.hpp"
|
||||
#include "jwt/detail/meta.hpp"
|
||||
#include "jwt/string_view.hpp"
|
||||
|
||||
namespace jwt {
|
||||
|
||||
using system_time_t = std::chrono::time_point<std::chrono::system_clock>;
|
||||
|
||||
namespace params {
|
||||
|
||||
|
||||
namespace detail {
|
||||
/**
|
||||
* Parameter for providing the payload.
|
||||
* Takes a Mapping concept representing
|
||||
* key-value pairs.
|
||||
*
|
||||
* NOTE: MappingConcept allows only strings
|
||||
* for both keys and values. Use `add_header`
|
||||
* API of `jwt_object` otherwise.
|
||||
*
|
||||
* Modeled as ParameterConcept.
|
||||
*/
|
||||
template <typename MappingConcept>
|
||||
struct payload_param
|
||||
{
|
||||
payload_param(MappingConcept&& mc)
|
||||
: payload_(std::forward<MappingConcept>(mc))
|
||||
{}
|
||||
|
||||
MappingConcept get() && { return std::move(payload_); }
|
||||
const MappingConcept& get() const& { return payload_; }
|
||||
|
||||
MappingConcept payload_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameter for providing the secret key.
|
||||
* Stores only the view of the provided string
|
||||
* as string_view. Later the implementation may or
|
||||
* may-not copy it.
|
||||
*
|
||||
* Modeled as ParameterConcept.
|
||||
*/
|
||||
struct secret_param
|
||||
{
|
||||
secret_param(string_view sv)
|
||||
: secret_(sv)
|
||||
{}
|
||||
|
||||
string_view get() { return secret_; }
|
||||
string_view secret_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct secret_function_param
|
||||
{
|
||||
T get() const { return fun_; }
|
||||
template <typename U>
|
||||
std::string get(U&& u) const { return fun_(u);}
|
||||
T fun_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameter for providing the algorithm to use.
|
||||
* The parameter can accept either the string representation
|
||||
* or the enum class.
|
||||
*
|
||||
* Modeled as ParameterConcept.
|
||||
*/
|
||||
struct algorithm_param
|
||||
{
|
||||
algorithm_param(const string_view alg)
|
||||
: alg_(str_to_alg(alg))
|
||||
{}
|
||||
|
||||
algorithm_param(jwt::algorithm alg)
|
||||
: alg_(alg)
|
||||
{}
|
||||
|
||||
jwt::algorithm get() const noexcept
|
||||
{
|
||||
return alg_;
|
||||
}
|
||||
|
||||
typename jwt::algorithm alg_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameter for providing additional headers.
|
||||
* Takes a mapping concept representing
|
||||
* key-value pairs.
|
||||
*
|
||||
* Modeled as ParameterConcept.
|
||||
*/
|
||||
template <typename MappingConcept>
|
||||
struct headers_param
|
||||
{
|
||||
headers_param(MappingConcept&& mc)
|
||||
: headers_(std::forward<MappingConcept>(mc))
|
||||
{}
|
||||
|
||||
MappingConcept get() && { return std::move(headers_); }
|
||||
const MappingConcept& get() const& { return headers_; }
|
||||
|
||||
MappingConcept headers_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct verify_param
|
||||
{
|
||||
verify_param(bool v)
|
||||
: verify_(v)
|
||||
{}
|
||||
|
||||
bool get() const { return verify_; }
|
||||
|
||||
bool verify_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename Sequence>
|
||||
struct algorithms_param
|
||||
{
|
||||
algorithms_param(Sequence&& seq)
|
||||
: seq_(std::forward<Sequence>(seq))
|
||||
{}
|
||||
|
||||
Sequence get() && { return std::move(seq_); }
|
||||
const Sequence& get() const& { return seq_; }
|
||||
|
||||
Sequence seq_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct leeway_param
|
||||
{
|
||||
leeway_param(uint32_t v)
|
||||
: leeway_(v)
|
||||
{}
|
||||
|
||||
uint32_t get() const noexcept { return leeway_; }
|
||||
|
||||
uint32_t leeway_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct audience_param
|
||||
{
|
||||
audience_param(std::string aud)
|
||||
: aud_(std::move(aud))
|
||||
{}
|
||||
|
||||
const std::string& get() const& noexcept { return aud_; }
|
||||
std::string get() && noexcept { return aud_; }
|
||||
|
||||
std::string aud_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct issuer_param
|
||||
{
|
||||
issuer_param(std::string iss)
|
||||
: iss_(std::move(iss))
|
||||
{}
|
||||
|
||||
const std::string& get() const& noexcept { return iss_; }
|
||||
std::string get() && noexcept { return iss_; }
|
||||
|
||||
std::string iss_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct subject_param
|
||||
{
|
||||
subject_param(std::string sub)
|
||||
: sub_(std::move(sub))
|
||||
{}
|
||||
|
||||
const std::string& get() const& noexcept { return sub_; }
|
||||
std::string get() && noexcept { return sub_; }
|
||||
|
||||
std::string sub_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct validate_iat_param
|
||||
{
|
||||
validate_iat_param(bool v)
|
||||
: iat_(v)
|
||||
{}
|
||||
|
||||
bool get() const noexcept { return iat_; }
|
||||
|
||||
bool iat_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct validate_jti_param
|
||||
{
|
||||
validate_jti_param(bool v)
|
||||
: jti_(v)
|
||||
{}
|
||||
|
||||
bool get() const noexcept { return jti_; }
|
||||
|
||||
bool jti_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct nbf_param
|
||||
{
|
||||
nbf_param(const jwt::system_time_t tp)
|
||||
: duration_(std::chrono::duration_cast<
|
||||
std::chrono::seconds>(tp.time_since_epoch()).count())
|
||||
{}
|
||||
|
||||
nbf_param(const uint64_t epoch)
|
||||
: duration_(epoch)
|
||||
{}
|
||||
|
||||
uint64_t get() const noexcept { return duration_; }
|
||||
|
||||
uint64_t duration_;
|
||||
};
|
||||
|
||||
} // END namespace detail
|
||||
|
||||
// Useful typedef
|
||||
using param_init_list_t = std::initializer_list<std::pair<jwt::string_view, jwt::string_view>>;
|
||||
using param_seq_list_t = std::initializer_list<jwt::string_view>;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::payload_param<std::unordered_map<std::string, std::string>>
|
||||
payload(const param_init_list_t& kvs)
|
||||
{
|
||||
std::unordered_map<std::string, std::string> m;
|
||||
|
||||
for (const auto& elem : kvs) {
|
||||
m.emplace(elem.first.data(), elem.second.data());
|
||||
}
|
||||
|
||||
return { std::move(m) };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename MappingConcept>
|
||||
detail::payload_param<MappingConcept>
|
||||
payload(MappingConcept&& mc)
|
||||
{
|
||||
static_assert (jwt::detail::meta::is_mapping_concept<MappingConcept>::value,
|
||||
"Template parameter does not meet the requirements for MappingConcept.");
|
||||
|
||||
return { std::forward<MappingConcept>(mc) };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::secret_param secret(const string_view sv)
|
||||
{
|
||||
return { sv };
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::enable_if_t<!std::is_convertible<T, string_view>::value, detail::secret_function_param<T>>
|
||||
secret(T&& fun)
|
||||
{
|
||||
return detail::secret_function_param<T>{ fun };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::algorithm_param algorithm(const string_view sv)
|
||||
{
|
||||
return { sv };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::algorithm_param algorithm(jwt::algorithm alg)
|
||||
{
|
||||
return { alg };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::headers_param<std::map<std::string, std::string>>
|
||||
headers(const param_init_list_t& kvs)
|
||||
{
|
||||
std::map<std::string, std::string> m;
|
||||
|
||||
for (const auto& elem : kvs) {
|
||||
m.emplace(elem.first.data(), elem.second.data());
|
||||
}
|
||||
|
||||
return { std::move(m) };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename MappingConcept>
|
||||
detail::headers_param<MappingConcept>
|
||||
headers(MappingConcept&& mc)
|
||||
{
|
||||
static_assert (jwt::detail::meta::is_mapping_concept<MappingConcept>::value,
|
||||
"Template parameter does not meet the requirements for MappingConcept.");
|
||||
|
||||
return { std::forward<MappingConcept>(mc) };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::verify_param
|
||||
verify(bool v)
|
||||
{
|
||||
return { v };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::leeway_param
|
||||
leeway(uint32_t l)
|
||||
{
|
||||
return { l };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::algorithms_param<std::vector<std::string>>
|
||||
algorithms(const param_seq_list_t& seq)
|
||||
{
|
||||
std::vector<std::string> vec;
|
||||
vec.reserve(seq.size());
|
||||
|
||||
for (const auto& e: seq) { vec.emplace_back(e.data(), e.length()); }
|
||||
|
||||
return { std::move(vec) };
|
||||
}
|
||||
|
||||
template <typename SequenceConcept>
|
||||
detail::algorithms_param<SequenceConcept>
|
||||
algorithms(SequenceConcept&& sc)
|
||||
{
|
||||
return { std::forward<SequenceConcept>(sc) };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::audience_param
|
||||
aud(const jwt::string_view aud)
|
||||
{
|
||||
return { aud.data() };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::issuer_param
|
||||
issuer(const jwt::string_view iss)
|
||||
{
|
||||
return { iss.data() };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::subject_param
|
||||
sub(const jwt::string_view subj)
|
||||
{
|
||||
return { subj.data() };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::validate_iat_param
|
||||
validate_iat(bool v)
|
||||
{
|
||||
return { v };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::validate_jti_param
|
||||
validate_jti(bool v)
|
||||
{
|
||||
return { v };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::nbf_param
|
||||
nbf(const system_time_t tp)
|
||||
{
|
||||
return { tp };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::nbf_param
|
||||
nbf(const uint64_t epoch)
|
||||
{
|
||||
return { epoch };
|
||||
}
|
||||
|
||||
} // END namespace params
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
38
externals/cpp-jwt/include/jwt/short_string.hpp
vendored
Executable file
38
externals/cpp-jwt/include/jwt/short_string.hpp
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_SHORT_STRING_HPP
|
||||
#define CPP_JWT_SHORT_STRING_HPP
|
||||
|
||||
#include <string>
|
||||
#include "jwt/stack_alloc.hpp"
|
||||
|
||||
namespace jwt {
|
||||
/*
|
||||
* A basic_string implementation using stack allocation.
|
||||
*/
|
||||
template <size_t N>
|
||||
using short_string = std::basic_string<char, std::char_traits<char>, stack_alloc<char, N>>;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
200
externals/cpp-jwt/include/jwt/stack_alloc.hpp
vendored
Executable file
200
externals/cpp-jwt/include/jwt/stack_alloc.hpp
vendored
Executable file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STACK_ALLOC_HPP
|
||||
#define STACK_ALLOC_HPP
|
||||
|
||||
/*
|
||||
* Based on Howard Hinnants awesome allocator boilerplate code
|
||||
* https://howardhinnant.github.io/short_alloc.h
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/*
|
||||
*/
|
||||
template <
|
||||
/// Size of the stack allocated byte buffer.
|
||||
size_t N,
|
||||
/// The alignment required for the buffer.
|
||||
size_t alignment = alignof(std::max_align_t)
|
||||
>
|
||||
class Arena
|
||||
{
|
||||
public: // 'tors
|
||||
Arena() noexcept
|
||||
: ptr_(buf_)
|
||||
{
|
||||
static_assert (alignment <= alignof(std::max_align_t),
|
||||
"Alignment chosen is more than the maximum supported alignment");
|
||||
}
|
||||
|
||||
/// Non copyable and assignable
|
||||
Arena(const Arena&) = delete;
|
||||
Arena& operator=(const Arena&) = delete;
|
||||
|
||||
~Arena()
|
||||
{
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
public: // Public APIs
|
||||
|
||||
/*
|
||||
* Reserves space within the buffer of size atleast 'n'
|
||||
* bytes.
|
||||
* More bytes maybe reserved based on the alignment requirements.
|
||||
*
|
||||
* Returns:
|
||||
* 1. The pointer within the storage buffer where the object can be constructed.
|
||||
* 2. nullptr if space cannot be reserved for requested number of bytes
|
||||
* (+ alignment padding if applicable)
|
||||
*/
|
||||
template <
|
||||
/// The requested alignment for this allocation.
|
||||
/// Must be less than or equal to the 'alignment'.
|
||||
size_t requested_alignment
|
||||
>
|
||||
char* allocate(size_t n) noexcept;
|
||||
|
||||
/*
|
||||
* Free back the space pointed by p within the storage buffer.
|
||||
*/
|
||||
void deallocate(char* p, size_t n) noexcept;
|
||||
|
||||
/*
|
||||
* The size of the internal storage buffer.
|
||||
*/
|
||||
constexpr static size_t size() noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns number of remaining bytes within the storage buffer
|
||||
* that can be used for further allocation requests.
|
||||
*/
|
||||
size_t used() const noexcept
|
||||
{
|
||||
return static_cast<size_t>(ptr_ - buf_);
|
||||
}
|
||||
|
||||
private: // Private member functions
|
||||
|
||||
/*
|
||||
* A check to determine if the pointer 'p'
|
||||
* points to a region within storage.
|
||||
*/
|
||||
bool pointer_in_storage(char* p) const noexcept
|
||||
{
|
||||
return (buf_ <= p) && (p <= (buf_ + N));
|
||||
}
|
||||
|
||||
/*
|
||||
* Rounds up the number to the next closest number
|
||||
* as per the alignment.
|
||||
*/
|
||||
constexpr static size_t align_up(size_t n) noexcept
|
||||
{
|
||||
return (n + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
private: // data members
|
||||
/// Storage
|
||||
alignas(alignment) char buf_[N];
|
||||
|
||||
/// Current allocation pointer within storage
|
||||
char* ptr_ = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
template <
|
||||
/// The allocator for type T
|
||||
typename T,
|
||||
/// Number of bytes for the arena
|
||||
size_t N,
|
||||
/// Alignment of the arena
|
||||
size_t align = alignof(std::max_align_t)
|
||||
>
|
||||
class stack_alloc
|
||||
{
|
||||
public: // typedefs
|
||||
using value_type = T;
|
||||
using arena_type = Arena<N, align>;
|
||||
|
||||
static auto constexpr alignment = align;
|
||||
static auto constexpr size = N;
|
||||
|
||||
public: // 'tors
|
||||
stack_alloc(arena_type& a)
|
||||
: arena_(a)
|
||||
{
|
||||
}
|
||||
|
||||
stack_alloc(const stack_alloc&) = default;
|
||||
stack_alloc& operator=(const stack_alloc&) = delete;
|
||||
|
||||
template <typename U>
|
||||
stack_alloc(const stack_alloc<U, N, alignment>& other)
|
||||
: arena_(other.arena_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
struct rebind {
|
||||
using other = stack_alloc<U, N, alignment>;
|
||||
};
|
||||
|
||||
public: // Exposed APIs
|
||||
|
||||
/*
|
||||
* Allocate memory of 'n' bytes for object
|
||||
* of type 'T'
|
||||
*/
|
||||
T* allocate(size_t n) noexcept;
|
||||
|
||||
/*
|
||||
* Deallocate the storage reserved for the object
|
||||
* of type T pointed by pointer 'p'
|
||||
*/
|
||||
void deallocate(T* p, size_t n) noexcept;
|
||||
|
||||
private: // Private APIs
|
||||
|
||||
private: // Private data members
|
||||
/// The arena
|
||||
arena_type& arena_;
|
||||
};
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#include "jwt/impl/stack_alloc.ipp"
|
||||
|
||||
#endif
|
381
externals/cpp-jwt/include/jwt/string_view.hpp
vendored
Executable file
381
externals/cpp-jwt/include/jwt/string_view.hpp
vendored
Executable file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef JWT_STRING_VIEW_HPP
|
||||
#define JWT_STRING_VIEW_HPP
|
||||
|
||||
#if defined(__cpp_lib_string_view)
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace jwt {
|
||||
using string_view = std::string_view;
|
||||
}
|
||||
|
||||
#else // defined(__cpp_lib_string_view)
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/*
|
||||
* Implements c++17 string_view.
|
||||
* Could have used boost::string_ref, but wanted to
|
||||
* keep boost dependency off from this library.
|
||||
*/
|
||||
|
||||
template <
|
||||
typename CharT,
|
||||
typename Traits = std::char_traits<CharT>
|
||||
>
|
||||
class basic_string_view
|
||||
{
|
||||
public: // Member Types
|
||||
using traits_type = std::char_traits<CharT>;
|
||||
using value_type = CharT;
|
||||
using pointer = const CharT*;
|
||||
using const_pointer = const CharT*;
|
||||
using reference = const CharT&;
|
||||
using const_reference = const CharT&;
|
||||
using iterator = const CharT*;
|
||||
using const_iterator = const CharT*;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
using size_type = size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
static constexpr size_type npos = size_type(-1);
|
||||
|
||||
public: // 'tors
|
||||
/// The default constructor;
|
||||
basic_string_view() = default;
|
||||
|
||||
/// Construct from string literal
|
||||
basic_string_view(const CharT* str) noexcept
|
||||
: data_(str)
|
||||
, len_(str ? traits_type::length(str) : 0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct from CharT pointer and provided length
|
||||
basic_string_view(const CharT* p, size_type len) noexcept
|
||||
: data_(p)
|
||||
, len_(len)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct from std::string
|
||||
template <typename Allocator>
|
||||
basic_string_view(
|
||||
const std::basic_string<CharT, Traits, Allocator>& str) noexcept
|
||||
: data_(str.data())
|
||||
, len_(str.length())
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
basic_string_view(const basic_string_view&) = default;
|
||||
|
||||
/// Assignment operator
|
||||
basic_string_view& operator=(const basic_string_view&) = default;
|
||||
|
||||
/// Destructor
|
||||
~basic_string_view()
|
||||
{
|
||||
data_ = nullptr;
|
||||
len_ = 0;
|
||||
}
|
||||
|
||||
public: // Exposed APIs
|
||||
/// Iterator Member Functions
|
||||
|
||||
iterator begin() const noexcept { return data_; }
|
||||
iterator end() const noexcept { return data_ + len_; }
|
||||
|
||||
iterator rbegin() const noexcept { return reverse_iterator(end()); }
|
||||
iterator rend() const noexcept { return reverse_iterator(begin()); }
|
||||
|
||||
const_iterator cbegin() const noexcept { return begin(); }
|
||||
const_iterator cend() const noexcept { return end(); }
|
||||
|
||||
const_iterator crbegin() const noexcept { return rbegin(); }
|
||||
const_iterator crend() const noexcept { return rend(); }
|
||||
|
||||
/// Capacity Member Functions
|
||||
|
||||
size_type length() const noexcept { return len_; }
|
||||
size_type size() const noexcept { return len_; }
|
||||
|
||||
size_type max_size() const noexcept
|
||||
{
|
||||
return (npos - sizeof(size_type) - sizeof(void*))
|
||||
/ sizeof(value_type) / 4;
|
||||
}
|
||||
|
||||
bool empty() const noexcept { return len_ == 0; }
|
||||
|
||||
/// Element Access Member Functions
|
||||
const_reference operator[](size_type idx) const noexcept
|
||||
{
|
||||
assert(idx < len_ && "string_view subscript out of range");
|
||||
return data_[idx];
|
||||
}
|
||||
|
||||
// NOTE: 'at' not supported
|
||||
//CharT at(size_type idx) const;
|
||||
|
||||
const_reference front() const noexcept
|
||||
{
|
||||
return data_[0];
|
||||
}
|
||||
|
||||
const_reference back() const noexcept
|
||||
{
|
||||
return data_[len_ - 1];
|
||||
}
|
||||
|
||||
const_pointer data() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
/// Modifier Member Functions
|
||||
void remove_prefix(size_type n) noexcept
|
||||
{
|
||||
assert (n < len_ && "Data would point out of bounds");
|
||||
data_ += n;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
void remove_suffix(size_type n) noexcept
|
||||
{
|
||||
assert (n < len_ && "Suffix length more than data length");
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
void swap(basic_string_view& other)
|
||||
{
|
||||
std::swap(data_, other.data_);
|
||||
std::swap(len_, other.len_);
|
||||
}
|
||||
|
||||
/// String Operation Member Functions
|
||||
|
||||
template <typename Allocator>
|
||||
explicit operator std::basic_string<CharT, Traits, Allocator>() const
|
||||
{
|
||||
return {data_, len_};
|
||||
}
|
||||
|
||||
// NOTE: Does not throw
|
||||
size_type copy(CharT* dest, size_type n, size_type pos = 0) const noexcept
|
||||
{
|
||||
assert (pos < len_ && n < len_);
|
||||
size_type to_copy = std::min(n, len_ - pos);
|
||||
|
||||
for (size_type i = 0; i < to_copy; i++) {
|
||||
dest[i] = data_[i + pos];
|
||||
}
|
||||
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
// NOTE: Does not throw
|
||||
basic_string_view substr(size_type pos, size_type n = npos) const noexcept
|
||||
{
|
||||
assert (pos < len_ && "Start position should be less than length of the view");
|
||||
assert (n == npos ? 1 : (n - pos) < len_ &&
|
||||
"Substring length asked for is more than the view length");
|
||||
|
||||
if (n == npos) n = len_;
|
||||
|
||||
return basic_string_view{data_ + pos, n};
|
||||
}
|
||||
|
||||
/// Comparison Member Functions
|
||||
int compare(const basic_string_view& other) const noexcept
|
||||
{
|
||||
int ret = traits_type::compare(data_, other.data_, std::min(len_, other.len_));
|
||||
if (ret == 0) {
|
||||
ret = compare_length(len_, other.len_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int compare(size_type pos, size_type n, basic_string_view other) const noexcept
|
||||
{
|
||||
return substr(pos, n).compare(other);
|
||||
}
|
||||
|
||||
int compare(const CharT* str) const noexcept
|
||||
{
|
||||
return compare(basic_string_view{str});
|
||||
}
|
||||
|
||||
int compare(size_type pos, size_type n, const CharT* str) const noexcept
|
||||
{
|
||||
return compare(pos, n, basic_string_view{str});
|
||||
}
|
||||
|
||||
int compare(size_type pos, size_type n1, const CharT* str, size_type n2) const noexcept
|
||||
{
|
||||
return compare(pos, n1, basic_string_view{str, n2});
|
||||
}
|
||||
|
||||
/// Find operations
|
||||
size_type find(const CharT* str, size_type pos, size_type n) const noexcept;
|
||||
|
||||
size_type find(const CharT ch, size_type pos) const noexcept;
|
||||
|
||||
size_type find(basic_string_view sv, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find(sv.data(), pos, sv.length());
|
||||
}
|
||||
|
||||
size_type find(const CharT* str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find(str, pos, traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type rfind(const CharT* str, size_type pos, size_type n) const noexcept;
|
||||
|
||||
size_type rfind(const CharT ch, size_type pos) const noexcept;
|
||||
|
||||
size_type rfind(basic_string_view sv, size_type pos = 0) const noexcept
|
||||
{
|
||||
return rfind(sv.data(), pos, sv.length());
|
||||
}
|
||||
|
||||
size_type rfind(const CharT* str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return rfind(str, pos, traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type find_first_of(const CharT* str, size_type pos, size_type count) const noexcept;
|
||||
|
||||
size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_of(str.data(), pos, str.length());
|
||||
}
|
||||
|
||||
size_type find_first_of(CharT ch, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find(ch, pos);
|
||||
}
|
||||
|
||||
size_type find_first_of(const CharT* str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_of(str, pos, traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type find_last_of(const CharT* str, size_type pos, size_type count) const noexcept;
|
||||
|
||||
size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_of(str.data(), (pos == npos ? len_ - 1 : pos), str.length());
|
||||
}
|
||||
|
||||
size_type find_last_of(CharT ch, size_type pos = npos) const noexcept
|
||||
{
|
||||
return rfind(ch, pos == npos ? len_ - 1 : pos);
|
||||
}
|
||||
|
||||
size_type find_last_of(const CharT* str, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_of(str, (pos == npos ? len_ - 1 : pos), traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type find_first_not_of(const CharT* str, size_type pos, size_type n) const noexcept;
|
||||
|
||||
size_type find_first_not_of(CharT ch, size_type pos) const noexcept;
|
||||
|
||||
size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_not_of(str.data(), pos, str.length());
|
||||
}
|
||||
|
||||
size_type find_first_not_of(const CharT* str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_not_of(str, pos, traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type find_last_not_of(const CharT* str, size_type pos, size_type n) const noexcept;
|
||||
|
||||
size_type find_last_not_of(CharT ch, size_type pos) const noexcept;
|
||||
|
||||
size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_not_of(str.data(), (pos == npos ? len_ - 1 : pos), str.length());
|
||||
}
|
||||
|
||||
size_type find_last_not_of(const CharT* str, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_not_of(str, (pos == npos ? len_ - 1 : pos), traits_type::length(str));
|
||||
}
|
||||
|
||||
/// Comparison operators Member Functions
|
||||
/*
|
||||
friend bool operator== (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator!= (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator< (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator> (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator<= (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator>= (basic_string_view a, basic_string_view b) noexcept;
|
||||
*/
|
||||
|
||||
private: // private implementations
|
||||
|
||||
static constexpr int compare_length(size_type n1, size_type n2) noexcept
|
||||
{
|
||||
return static_cast<difference_type>(n1 - n2) > std::numeric_limits<int>::max()
|
||||
? std::numeric_limits<int>::max()
|
||||
: static_cast<difference_type>(n1 - n2) < std::numeric_limits<int>::min()
|
||||
? std::numeric_limits<int>::min()
|
||||
: static_cast<int>(n1 - n2)
|
||||
;
|
||||
}
|
||||
|
||||
private:
|
||||
// This is what view is basically...
|
||||
const char* data_ = nullptr;
|
||||
size_type len_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/// Helper typedef
|
||||
using string_view = basic_string_view<char>;
|
||||
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#include "jwt/impl/string_view.ipp"
|
||||
|
||||
#endif // defined(__cpp_lib_string_view)
|
||||
|
||||
#endif
|
1
externals/cpp-jwt/include/jwt/test/compile.txt
vendored
Executable file
1
externals/cpp-jwt/include/jwt/test/compile.txt
vendored
Executable file
@@ -0,0 +1 @@
|
||||
g++ -std=c++14 -I /usr/local/Cellar/openssl/1.0.2j/include/ -I /Users/amuralid/dev_test/cpp-jwt/include/ -o test_rsa test_rsa.cc -L /usr/local/Cellar//openssl/1.0.2j/lib/ -lssl -lcrypto
|
BIN
externals/cpp-jwt/include/jwt/test/test_base64
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_base64
vendored
Executable file
Binary file not shown.
48
externals/cpp-jwt/include/jwt/test/test_base64.cc
vendored
Executable file
48
externals/cpp-jwt/include/jwt/test/test_base64.cc
vendored
Executable 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;
|
||||
}
|
45
externals/cpp-jwt/include/jwt/test/test_evp.c
vendored
Executable file
45
externals/cpp-jwt/include/jwt/test/test_evp.c
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
#include <stdio.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
EVP_MD_CTX *mdctx;
|
||||
const EVP_MD *md;
|
||||
char mess1[] = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaXNzIjoiYXJ1bi5jb20iLCJ0aW1lX3N0ciI6Ijg6MThwbSAyNCBOb3YgMjAxNyIsIndoZXJlIjoiYWlycG9ydCJ9";
|
||||
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||
int md_len, i;
|
||||
|
||||
//OpenSSL_add_all_digests();
|
||||
|
||||
if(!argv[1]) {
|
||||
printf("Usage: mdtest digestname\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
md = EVP_sha256();
|
||||
|
||||
if(!md) {
|
||||
printf("Unknown message digest %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mdctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit_ex(mdctx, md, NULL);
|
||||
EVP_DigestUpdate(mdctx, mess1, strlen(mess1));
|
||||
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
|
||||
printf("Dig: %s\n", md_value);
|
||||
printf("Dig: %d\n", md_len);
|
||||
|
||||
printf("Digest is: ");
|
||||
for(i = 0; i < md_len; i++)
|
||||
printf("%02x", md_value[i]);
|
||||
printf("\n");
|
||||
|
||||
d2i_ECDSA_SIG(NULL, (const unsigned char **)&md_value[0], md_len);
|
||||
|
||||
/* Call this once before exit. */
|
||||
EVP_cleanup();
|
||||
exit(0);
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_hmac
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_hmac
vendored
Executable file
Binary file not shown.
16
externals/cpp-jwt/include/jwt/test/test_hmac.cc
vendored
Executable file
16
externals/cpp-jwt/include/jwt/test/test_hmac.cc
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
#include <iostream>
|
||||
#include "jwt/algorithm.hpp"
|
||||
|
||||
void basic_hmac_test()
|
||||
{
|
||||
jwt::string_view sv = "secret" ;
|
||||
jwt::string_view d = "Some random data string";
|
||||
auto res = jwt::HMACSign<jwt::algo::HS256>::sign(sv, d);
|
||||
|
||||
std::cout << res.first << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_hmac_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_decode
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_decode
vendored
Executable file
Binary file not shown.
30
externals/cpp-jwt/include/jwt/test/test_jwt_decode.cc
vendored
Executable file
30
externals/cpp-jwt/include/jwt/test/test_jwt_decode.cc
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void basic_decode_test()
|
||||
{
|
||||
// Create header
|
||||
jwt::jwt_header hdr;
|
||||
hdr = jwt::jwt_header{jwt::algorithm::HS256};
|
||||
|
||||
// Create payload
|
||||
jwt::jwt_payload jp;
|
||||
jp.add_claim("sub", "1234567890");
|
||||
jp.add_claim("name", "John Doe");
|
||||
jp.add_claim("admin", true);
|
||||
|
||||
jwt::jwt_signature sgn{"secret"};
|
||||
std::error_code ec{};
|
||||
auto res = sgn.encode(hdr, jp, ec);
|
||||
std::cout << res << std::endl;
|
||||
|
||||
using namespace jwt::params;
|
||||
|
||||
std::cout << "DECODE: \n";
|
||||
jwt::decode(res, algorithms({"none", "HS256"}), ec, verify(false), secret("secret"));
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_decode_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_header
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_header
vendored
Executable file
Binary file not shown.
19
externals/cpp-jwt/include/jwt/test/test_jwt_header.cc
vendored
Executable file
19
externals/cpp-jwt/include/jwt/test/test_jwt_header.cc
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void test_basic_header()
|
||||
{
|
||||
jwt::jwt_header hdr;
|
||||
hdr = jwt::jwt_header{jwt::algorithm::HS256};
|
||||
std::string jstr = to_json_str(hdr);
|
||||
std::cout << jstr << std::endl;
|
||||
|
||||
std::string enc_str = hdr.base64_encode();
|
||||
std::cout << "Base64: " << enc_str << std::endl;
|
||||
std::cout << "Decoded: " << hdr.base64_decode(enc_str) << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_basic_header();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_object
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_object
vendored
Executable file
Binary file not shown.
93
externals/cpp-jwt/include/jwt/test/test_jwt_object.cc
vendored
Executable file
93
externals/cpp-jwt/include/jwt/test/test_jwt_object.cc
vendored
Executable file
@@ -0,0 +1,93 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <unordered_map>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void basic_jwt_object_test()
|
||||
{
|
||||
using namespace jwt::params;
|
||||
jwt::jwt_object obj(payload({
|
||||
{"a", "b"},
|
||||
{"c", "d"}
|
||||
}));
|
||||
|
||||
//check with std::map
|
||||
std::map<std::string, std::string> m;
|
||||
m["a"] = "b";
|
||||
m["c"] = "d";
|
||||
|
||||
jwt::jwt_object obj1{payload(m)};
|
||||
|
||||
auto obj2 = std::move(obj1);
|
||||
|
||||
std::cout << obj2.payload() << std::endl;
|
||||
|
||||
//check with unordered map of string_view
|
||||
std::unordered_map<jwt::string_view, std::string> um = {
|
||||
{"a", "b"},
|
||||
{"c", "d"}
|
||||
};
|
||||
jwt::jwt_object obj3{payload(um)};
|
||||
|
||||
obj3.add_claim("f", true)
|
||||
.add_claim("time", 176353563)
|
||||
.add_claim("exp", std::chrono::system_clock::now())
|
||||
;
|
||||
|
||||
std::cout << jwt::to_json_str(obj3.payload(), true) << std::endl;
|
||||
|
||||
obj3.remove_claim(std::string{"a"});
|
||||
std::cout << obj3.payload() << std::endl;
|
||||
|
||||
obj3.secret("secret");
|
||||
obj3.header().algo("HS256");
|
||||
|
||||
auto dec_obj = jwt::decode(obj3.signature(), algorithms({"HS256"}), secret("secret"));
|
||||
}
|
||||
|
||||
void jwt_object_pem_test()
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
std::string pub_key =
|
||||
R"(-----BEGIN PUBLIC KEY-----
|
||||
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEomxC9ycc8AkXSwWQpu1kN5Fmgy/sD/KJ
|
||||
qN3tlSZmUEZ3w3c6KYJfK97PMOSZQaUdeydBoq/IOglQQOj8zLqubq5IpaaUiDQ5
|
||||
0eJg79PvXuLiVUH98cBL/o8sDVB/sGzz
|
||||
-----END PUBLIC KEY-----)";
|
||||
|
||||
std::string priv_key =
|
||||
R"(-----BEGIN EC PRIVATE KEY-----
|
||||
MIGkAgEBBDBeLCgapjZmvTatMHaYX3A02+0Ys3Tr8kda+E9DFnmCSiCOEig519fT
|
||||
13edeU8YdDugBwYFK4EEACKhZANiAASibEL3JxzwCRdLBZCm7WQ3kWaDL+wP8omo
|
||||
3e2VJmZQRnfDdzopgl8r3s8w5JlBpR17J0Gir8g6CVBA6PzMuq5urkilppSINDnR
|
||||
4mDv0+9e4uJVQf3xwEv+jywNUH+wbPM=
|
||||
-----END EC PRIVATE KEY-----)";
|
||||
|
||||
jwt::jwt_object obj;
|
||||
obj.secret(priv_key);
|
||||
obj.header().algo(jwt::algorithm::ES256);
|
||||
|
||||
obj.add_claim("iss", "arun.com")
|
||||
.add_claim("where", "airport")
|
||||
.add_claim("time_str", "8:18pm 24 Nov 2017")
|
||||
.add_claim("id", 1)
|
||||
.add_claim("exp", std::chrono::system_clock::now())
|
||||
;
|
||||
|
||||
std::cout << "pem sign " << obj.signature() << std::endl;
|
||||
std::cout << "Get claim value for exp: " <<
|
||||
obj.payload().get_claim_value<uint64_t>("exp") << std::endl;
|
||||
|
||||
auto dec_obj = jwt::decode(obj.signature(), algorithms({"ES256"}), secret(pub_key));
|
||||
std::cout << dec_obj.payload() << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_jwt_object_test();
|
||||
//jwt_object_pem_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_payload
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_payload
vendored
Executable file
Binary file not shown.
34
externals/cpp-jwt/include/jwt/test/test_jwt_payload.cc
vendored
Executable file
34
externals/cpp-jwt/include/jwt/test/test_jwt_payload.cc
vendored
Executable file
@@ -0,0 +1,34 @@
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void basic_payload_test()
|
||||
{
|
||||
jwt::jwt_payload jp;
|
||||
jp.add_claim("iss", "myself");
|
||||
jp.add_claim("exp", 1234567);
|
||||
jp.add_claim("Exp", 1234567, true);
|
||||
|
||||
auto jstr = jwt::to_json_str(jp);
|
||||
std::cout << jstr << std::endl;
|
||||
|
||||
auto enc = jp.base64_encode();
|
||||
std::cout << "Base64 enc: " << enc << std::endl;
|
||||
|
||||
auto dec = jp.base64_decode(enc);
|
||||
std::cout << "Base64 dec: " << dec << std::endl;
|
||||
std::cout << "Base64 dec: " << jstr << std::endl;
|
||||
|
||||
assert (jstr == dec && "Encoded and decoded messages do not match");
|
||||
assert (jp.has_claim("exp") && "Claim exp must exist");
|
||||
assert (jp.has_claim("Exp") && "Claim Exp must exist");
|
||||
|
||||
assert (!jp.has_claim("aud") && "Claim aud does not exist");
|
||||
assert (jp.has_claim_with_value("exp", 1234567) && "Claim exp with value 1234567 does not exist");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_payload_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_signature
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_signature
vendored
Executable file
Binary file not shown.
25
externals/cpp-jwt/include/jwt/test/test_jwt_signature.cc
vendored
Executable file
25
externals/cpp-jwt/include/jwt/test/test_jwt_signature.cc
vendored
Executable file
@@ -0,0 +1,25 @@
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void basic_sign_test()
|
||||
{
|
||||
// Create header
|
||||
jwt::jwt_header hdr;
|
||||
hdr = jwt::jwt_header{jwt::algorithm::HS256};
|
||||
|
||||
// Create payload
|
||||
jwt::jwt_payload jp;
|
||||
jp.add_claim("sub", "1234567890");
|
||||
jp.add_claim("name", "John Doe");
|
||||
jp.add_claim("admin", true);
|
||||
|
||||
jwt::jwt_signature sgn{"secret"};
|
||||
std::error_code ec{};
|
||||
auto res = sgn.encode(hdr, jp, ec);
|
||||
std::cout << res << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_sign_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_rsa
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_rsa
vendored
Executable file
Binary file not shown.
47
externals/cpp-jwt/include/jwt/test/test_rsa.cc
vendored
Executable file
47
externals/cpp-jwt/include/jwt/test/test_rsa.cc
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
#include <iostream>
|
||||
#include "jwt/algorithm.hpp"
|
||||
|
||||
static const char* rsa_2048_pem =
|
||||
R"(-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDC2kwAziXUf33m
|
||||
iqWp0yG6o259+nj7hpQLC4UT0Hmz0wmvreDJ/yNbSgOvsxvVdvzL2IaRZ+Gi5mo0
|
||||
lswWvL6IGz7PZO0kXTq9sdBnNqMOx27HddV9e/2/p0MgibJTbgywY2Sk23QYhJpq
|
||||
Kq/nU0xlBfSaI5ddZ2RC9ZNkVeGawUKYksTruhAVJqviHN8BoK6VowP5vcxyyOWH
|
||||
TK9KruDqzCIhqwRTeo0spokBkTN/LCuhVivcHAzUiJVtB4qAiTI9L/zkzhjpKz9P
|
||||
45aLU54rj011gG8U/6E1USh5nMnPkr+d3oLfkhfS3Zs3kJVdyFQWZpQxiTaI92Fd
|
||||
2wLvbS0HAgMBAAECggEAD8dTnkETSSjlzhRuI9loAtAXM3Zj86JLPLW7GgaoxEoT
|
||||
n7lJ2bGicFMHB2ROnbOb9vnas82gtOtJsGaBslmoaCckp/C5T1eJWTEb+i+vdpPp
|
||||
wZcmKZovyyRFSE4+NYlU17fEv6DRvuaGBpDcW7QgHJIl45F8QWEM+msee2KE+V4G
|
||||
z/9vAQ+sOlvsb4mJP1tJIBx9Lb5loVREwCRy2Ha9tnWdDNar8EYkOn8si4snPT+E
|
||||
3ZCy8mlcZyUkZeiS/HdtydxZfoiwrSRYamd1diQpPhWCeRteQ802a7ds0Y2YzgfF
|
||||
UaYjNuRQm7zA//hwbXS7ELPyNMU15N00bajlG0tUOQKBgQDnLy01l20OneW6A2cI
|
||||
DIDyYhy5O7uulsaEtJReUlcjEDMkin8b767q2VZHb//3ZH+ipnRYByUUyYUhdOs2
|
||||
DYRGGeAebnH8wpTT4FCYxUsIUpDfB7RwfdBONgaKewTJz/FPswy1Ye0b5H2c6vVi
|
||||
m2FZ33HQcoZ3wvFFqyGVnMzpOwKBgQDXxL95yoxUGKa8vMzcE3Cn01szh0dFq0sq
|
||||
cFpM+HWLVr84CItuG9H6L0KaStEEIOiJsxOVpcXfFFhsJvOGhMA4DQTwH4WuXmXp
|
||||
1PoVMDlV65PYqvhzwL4+QhvZO2bsrEunITXOmU7CI6kilnAN3LuP4HbqZgoX9lqP
|
||||
I31VYzLupQKBgGEYck9w0s/xxxtR9ILv5XRnepLdoJzaHHR991aKFKjYU/KD7JDK
|
||||
INfoAhGs23+HCQhCCtkx3wQVA0Ii/erM0II0ueluD5fODX3TV2ZibnoHW2sgrEsW
|
||||
vFcs36BnvIIaQMptc+f2QgSV+Z/fGsKYadG6Q+39O7au/HB7SHayzWkjAoGBAMgt
|
||||
Fzslp9TpXd9iBWjzfCOnGUiP65Z+GWkQ/SXFqD+SRir0+m43zzGdoNvGJ23+Hd6K
|
||||
TdQbDJ0uoe4MoQeepzoZEgi4JeykVUZ/uVfo+nh06yArVf8FxTm7WVzLGGzgV/uA
|
||||
+wtl/cRtEyAsk1649yW/KHPEIP8kJdYAJeoO8xSlAoGAERMrkFR7KGYZG1eFNRdV
|
||||
mJMq+Ibxyw8ks/CbiI+n3yUyk1U8962ol2Q0T4qjBmb26L5rrhNQhneM4e8mo9FX
|
||||
LlQapYkPvkdrqW0Bp72A/UNAvcGTmN7z5OCJGMUutx2hmEAlrYmpLKS8pM/p9zpK
|
||||
tEOtzsP5GMDYVlEp1jYSjzQ=
|
||||
-----END PRIVATE KEY-----)";
|
||||
|
||||
void basic_rsa_test()
|
||||
{
|
||||
jwt::string_view sv = rsa_2048_pem;
|
||||
jwt::string_view d = "Some random data string";
|
||||
|
||||
auto res = jwt::PEMSign<jwt::algo::RS256>::sign(sv, d);
|
||||
|
||||
std::cout << res.first << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_rsa_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_stack_alloc
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_stack_alloc
vendored
Executable file
Binary file not shown.
22
externals/cpp-jwt/include/jwt/test/test_stack_alloc.cc
vendored
Executable file
22
externals/cpp-jwt/include/jwt/test/test_stack_alloc.cc
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "jwt/stack_alloc.hpp"
|
||||
|
||||
template <typename T, size_t SZ = 2>
|
||||
using SmallVector = std::vector<T, jwt::stack_alloc<T, SZ, alignof(T)>>;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
SmallVector<int>::allocator_type::arena_type a;
|
||||
SmallVector<int> v{a};
|
||||
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_sv
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_sv
vendored
Executable file
Binary file not shown.
169
externals/cpp-jwt/include/jwt/test/test_sv.cc
vendored
Executable file
169
externals/cpp-jwt/include/jwt/test/test_sv.cc
vendored
Executable file
@@ -0,0 +1,169 @@
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include "jwt/string_view.hpp"
|
||||
|
||||
using string_view = jwt::basic_string_view<char>;
|
||||
|
||||
void basic_cons()
|
||||
{
|
||||
// Default construction
|
||||
string_view sv{};
|
||||
assert (sv.length() == 0 && "Size must be zero for default constructor");
|
||||
|
||||
// Construction from string literal
|
||||
string_view sv2{"Arun Muralidharan"};
|
||||
assert (sv2.length() == strlen("Arun Muralidharan") && "Lengths must match");
|
||||
|
||||
const char* haystack = "some really big data with infinite objects....";
|
||||
|
||||
// Construct using part of data
|
||||
string_view sv3{haystack, 4};
|
||||
assert (sv3.length() == 4 && "Partial construction is not ok");
|
||||
assert (sv3.to_string() == "some" && "Partial strings are not equal");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void iterator_test()
|
||||
{
|
||||
string_view sv{"Arun Muralidharan"};
|
||||
for (auto c : sv) std::cout << c;
|
||||
std::cout << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void str_operations()
|
||||
{
|
||||
string_view sv{"Arun Muralidharan"};
|
||||
string_view tmp = sv;
|
||||
sv.remove_prefix(5);
|
||||
assert (sv.to_string() == "Muralidharan" && "Remove prefix failed");
|
||||
|
||||
sv = tmp;
|
||||
sv.remove_suffix(strlen("Muralidharan"));
|
||||
assert (sv.to_string() == "Arun " && "Remove suffix failed");
|
||||
|
||||
sv=tmp;
|
||||
{
|
||||
std::unique_ptr<char[]> dst{new char[32]};
|
||||
sv.copy(dst.get(), 6, 0);
|
||||
dst[6] = '\0';
|
||||
assert (strlen(dst.get()) == 6 && "Copy Failed-1");
|
||||
assert (std::string{dst.get()} == "Arun M" && "Copy Failed-2");
|
||||
|
||||
sv.copy(dst.get(), 8, 4);
|
||||
dst[8] = '\0';
|
||||
assert (strlen(dst.get()) == 8 && "Middle copy failed-1");
|
||||
assert (std::string{dst.get()} == " Muralid" && "Middle copy failed-2");
|
||||
}
|
||||
|
||||
{
|
||||
auto ss1 = sv.substr(0, 4);
|
||||
assert (ss1.to_string() == "Arun" && "Substr failed - 1");
|
||||
|
||||
auto ss2 = sv.substr(1, 3);
|
||||
assert (ss2.to_string() == "run" && "Substr failed - 2");
|
||||
|
||||
auto ss3 = sv.substr(0);
|
||||
assert (ss3.length() == sv.length() && "Substr failed - 3");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void find_oper()
|
||||
{
|
||||
string_view sv{"Arun Muralidharan"};
|
||||
auto pos = sv.find("Arun", 0, 4);
|
||||
assert (pos == 0 && "Arun not found in sv");
|
||||
|
||||
pos = sv.find("arun", 0, 4);
|
||||
assert (pos == string_view::npos && "arun is not there in sv");
|
||||
|
||||
sv = "This has a, in it.";
|
||||
pos = sv.find_first_of(",", 0, 1);
|
||||
assert (pos != string_view::npos);
|
||||
assert (pos == 10 && "Comma not found at correct place");
|
||||
|
||||
pos = sv.find_first_of(",", 10, 1);
|
||||
assert (pos != string_view::npos);
|
||||
assert (pos == 10 && "Comma not found at correct place");
|
||||
|
||||
pos = sv.find_first_of(":", 10, 1);
|
||||
assert (pos == string_view::npos);
|
||||
|
||||
pos = sv.find_last_of(",", 5, 1);
|
||||
assert (pos == string_view::npos);
|
||||
|
||||
pos = sv.find_last_of(",", sv.length() - 1, 1);
|
||||
assert (pos != string_view::npos);
|
||||
assert (pos == 10 && "Comma not found at correct place");
|
||||
|
||||
pos = sv.find_first_of(".", 0, 1);
|
||||
assert (pos == sv.length() - 1 && "Dot not found at correct place");
|
||||
|
||||
pos = sv.find_last_of(".", sv.length() - 2, 1);
|
||||
assert (pos == string_view::npos);
|
||||
|
||||
pos = sv.find_last_of(".", sv.length() - 1, 1);
|
||||
assert (pos == sv.length() - 1);
|
||||
|
||||
sv = "Some string :<> with some ??? pattern --**";
|
||||
|
||||
pos = sv.rfind("???", sv.length() - 1, 3);
|
||||
assert (pos != string_view::npos && "??? not found");
|
||||
assert (pos == 26 && "??? not found at the correct place");
|
||||
|
||||
sv = "ATCGTTCACGRRRTCGGGGACGTC";
|
||||
|
||||
pos = sv.find_first_not_of("ATCG");
|
||||
assert (pos != string_view::npos);
|
||||
assert (pos == 10);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void conversions()
|
||||
{
|
||||
auto c2sv = [](int num) -> string_view {
|
||||
switch (num) {
|
||||
case 1: return "one";
|
||||
case 2: return "two";
|
||||
case 3: return "three";
|
||||
default: return "many";
|
||||
};
|
||||
};
|
||||
|
||||
auto res = c2sv(2);
|
||||
assert (res.to_string() == "two");
|
||||
|
||||
auto s2sv = [](std::string s) {
|
||||
return s;
|
||||
};
|
||||
|
||||
s2sv(static_cast<std::string>(res));
|
||||
}
|
||||
|
||||
void comparisons()
|
||||
{
|
||||
string_view s1{"Apple"};
|
||||
string_view s2{"Orange"};
|
||||
|
||||
assert (s1 != s2 && "Two string views are not equal");
|
||||
assert (s2 > s1 && "Orange is lexicographically bigger than Apple");
|
||||
|
||||
s2 = "Apples";
|
||||
assert (s2 > s1 && "Because Apples is plural");
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_cons();
|
||||
iterator_test();
|
||||
str_operations();
|
||||
find_oper();
|
||||
conversions();
|
||||
comparisons();
|
||||
return 0;
|
||||
};
|
Reference in New Issue
Block a user