mirror of
https://github.com/arun11299/cpp-jwt.git
synced 2025-05-15 17:28:37 +00:00
Add error codes for signing error checks
This commit is contained in:
parent
2290c8733a
commit
53a281640f
6 changed files with 275 additions and 70 deletions
|
@ -1,6 +1,13 @@
|
||||||
#ifndef CPP_JWT_ALGORITHM_HPP
|
#ifndef CPP_JWT_ALGORITHM_HPP
|
||||||
#define 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 <cassert>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
|
@ -12,7 +19,9 @@
|
||||||
#include <openssl/ecdsa.h>
|
#include <openssl/ecdsa.h>
|
||||||
#include <openssl/buffer.h>
|
#include <openssl/buffer.h>
|
||||||
|
|
||||||
|
#include "jwt/exceptions.hpp"
|
||||||
#include "jwt/string_view.hpp"
|
#include "jwt/string_view.hpp"
|
||||||
|
#include "jwt/error_codes.hpp"
|
||||||
|
|
||||||
namespace jwt {
|
namespace jwt {
|
||||||
|
|
||||||
|
@ -20,23 +29,25 @@ namespace jwt {
|
||||||
using sign_result_t = std::pair<std::string, std::error_code>;
|
using sign_result_t = std::pair<std::string, std::error_code>;
|
||||||
/// The result type of verification function
|
/// The result type of verification function
|
||||||
using verify_result_t = std::pair<bool, std::error_code>;
|
using verify_result_t = std::pair<bool, std::error_code>;
|
||||||
/// The function pointer type of the signing function
|
/// The function pointer type for the signing function
|
||||||
using sign_func_t = sign_result_t (*) (const string_view key,
|
using sign_func_t = sign_result_t (*) (const string_view key,
|
||||||
const string_view data);
|
const string_view data);
|
||||||
///
|
/// The function pointer type for the verifying function
|
||||||
using verify_func_t = verify_result_t (*) (const string_view key,
|
using verify_func_t = verify_result_t (*) (const string_view key,
|
||||||
const string_view head,
|
const string_view head,
|
||||||
const string_view jwt_sign);
|
const string_view jwt_sign);
|
||||||
|
|
||||||
namespace algo {
|
namespace algo {
|
||||||
|
|
||||||
//TODO: All these can be done using code generaion.
|
//Me: TODO: All these can be done using code generaion.
|
||||||
// NO. NEVER. I hate Macros.
|
//Me: NO. NEVER. I hate Macros.
|
||||||
// You can use templates too.
|
//Me: You can use templates too.
|
||||||
// No. I would rather prefer explicit.
|
//Me: No. I would rather prefer explicit.
|
||||||
// Ok. You win.
|
//Me: Ok. You win.
|
||||||
|
//Me: Same to you.
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* HS256 algorithm.
|
||||||
*/
|
*/
|
||||||
struct HS256
|
struct HS256
|
||||||
{
|
{
|
||||||
|
@ -46,7 +57,8 @@ struct HS256
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* HS384 algorithm.
|
||||||
*/
|
*/
|
||||||
struct HS384
|
struct HS384
|
||||||
{
|
{
|
||||||
|
@ -56,7 +68,8 @@ struct HS384
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* HS512 algorithm.
|
||||||
*/
|
*/
|
||||||
struct HS512
|
struct HS512
|
||||||
{
|
{
|
||||||
|
@ -66,7 +79,8 @@ struct HS512
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* NONE algorithm.
|
||||||
*/
|
*/
|
||||||
struct NONE
|
struct NONE
|
||||||
{
|
{
|
||||||
|
@ -76,7 +90,8 @@ struct NONE
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* RS256 algorithm.
|
||||||
*/
|
*/
|
||||||
struct RS256
|
struct RS256
|
||||||
{
|
{
|
||||||
|
@ -88,7 +103,8 @@ struct RS256
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* RS384 algorithm.
|
||||||
*/
|
*/
|
||||||
struct RS384
|
struct RS384
|
||||||
{
|
{
|
||||||
|
@ -100,7 +116,8 @@ struct RS384
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* RS512 algorithm.
|
||||||
*/
|
*/
|
||||||
struct RS512
|
struct RS512
|
||||||
{
|
{
|
||||||
|
@ -112,7 +129,8 @@ struct RS512
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* ES256 algorithm.
|
||||||
*/
|
*/
|
||||||
struct ES256
|
struct ES256
|
||||||
{
|
{
|
||||||
|
@ -124,7 +142,8 @@ struct ES256
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* ES384 algorithm.
|
||||||
*/
|
*/
|
||||||
struct ES384
|
struct ES384
|
||||||
{
|
{
|
||||||
|
@ -136,7 +155,8 @@ struct ES384
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* ES512 algorithm.
|
||||||
*/
|
*/
|
||||||
struct ES512
|
struct ES512
|
||||||
{
|
{
|
||||||
|
@ -151,8 +171,8 @@ struct ES512
|
||||||
} //END Namespace algo
|
} //END Namespace algo
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
* JWT signing algorithm.
|
* JWT signing algorithm types.
|
||||||
*/
|
*/
|
||||||
enum class algorithm
|
enum class algorithm
|
||||||
{
|
{
|
||||||
|
@ -170,7 +190,9 @@ enum class algorithm
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* Convert the algorithm enum class type to
|
||||||
|
* its stringified form.
|
||||||
*/
|
*/
|
||||||
string_view alg_to_str(enum algorithm alg) noexcept
|
string_view alg_to_str(enum algorithm alg) noexcept
|
||||||
{
|
{
|
||||||
|
@ -192,7 +214,9 @@ string_view alg_to_str(enum algorithm alg) noexcept
|
||||||
assert (0 && "Code not reached");
|
assert (0 && "Code not reached");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* Convert stringified algorithm to enum class.
|
||||||
|
* The string comparison is case insesitive.
|
||||||
*/
|
*/
|
||||||
enum algorithm str_to_alg(const string_view alg) noexcept
|
enum algorithm str_to_alg(const string_view alg) noexcept
|
||||||
{
|
{
|
||||||
|
@ -213,7 +237,14 @@ enum algorithm str_to_alg(const string_view alg) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* 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>
|
template <typename Hasher>
|
||||||
struct HMACSign
|
struct HMACSign
|
||||||
|
@ -221,7 +252,18 @@ struct HMACSign
|
||||||
/// The type of Hashing algorithm
|
/// The type of Hashing algorithm
|
||||||
using hasher_type = Hasher;
|
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 string_view key, const string_view data)
|
static sign_result_t sign(const string_view key, const string_view data)
|
||||||
{
|
{
|
||||||
|
@ -240,39 +282,55 @@ struct HMACSign
|
||||||
&len);
|
&len);
|
||||||
|
|
||||||
if (!res) {
|
if (!res) {
|
||||||
//TODO: Set the appropriate error code
|
ec = AlgorithmErrc::SigningErr;
|
||||||
}
|
}
|
||||||
sign.resize(len);
|
|
||||||
|
|
||||||
return {std::move(sign), ec};
|
sign.resize(len);
|
||||||
|
return { std::move(sign), ec };
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
*/
|
*/
|
||||||
static verify_result_t
|
static verify_result_t
|
||||||
verify(const string_view key, const string_view head, const string_view sign);
|
verify(const string_view key, const string_view head, const 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 <>
|
template <>
|
||||||
struct HMACSign<algo::NONE>
|
struct HMACSign<algo::NONE>
|
||||||
{
|
{
|
||||||
using hasher_type = algo::NONE;
|
using hasher_type = algo::NONE;
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
|
* Basically a no-op. Sets the error code to NoneAlgorithmUsed.
|
||||||
*/
|
*/
|
||||||
static sign_result_t sign(const string_view key, const string_view data)
|
static sign_result_t sign(const string_view key, const string_view data)
|
||||||
{
|
{
|
||||||
std::string sign;
|
(void)key;
|
||||||
|
(void)data;
|
||||||
std::error_code ec{};
|
std::error_code ec{};
|
||||||
|
ec = AlgorithmErrc::NoneAlgorithmUsed;
|
||||||
|
|
||||||
//TODO: Set the appropriate error code for none
|
return { std::string{}, ec };
|
||||||
return {sign, ec};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
*/
|
*/
|
||||||
static verify_result_t
|
static verify_result_t
|
||||||
verify(const string_view key, const string_view head, const string_view sign)
|
verify(const string_view key, const string_view head, const string_view sign)
|
||||||
|
@ -281,13 +339,21 @@ struct HMACSign<algo::NONE>
|
||||||
std::error_code ec{};
|
std::error_code ec{};
|
||||||
|
|
||||||
//TODO: Set the appropriate error code for none
|
//TODO: Set the appropriate error code for none
|
||||||
return {compare_res, ec};
|
return { compare_res, 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>
|
template <typename Hasher>
|
||||||
struct PEMSign
|
struct PEMSign
|
||||||
|
@ -296,7 +362,17 @@ public:
|
||||||
/// The type of Hashing algorithm
|
/// The type of Hashing algorithm
|
||||||
using hasher_type = Hasher;
|
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 string_view key, const string_view data)
|
static sign_result_t sign(const string_view key, const string_view data)
|
||||||
{
|
{
|
||||||
|
@ -307,27 +383,20 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<EVP_PKEY, decltype(evpkey_deletor)>
|
std::unique_ptr<EVP_PKEY, decltype(evpkey_deletor)>
|
||||||
pkey{load_key(key), evpkey_deletor};
|
pkey{load_key(key, ec), evpkey_deletor};
|
||||||
|
|
||||||
if (!pkey) {
|
if (ec) return { std::string{}, ec };
|
||||||
//TODO: set valid error code
|
|
||||||
return {std::string{}, ec};
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Use stack string here ?
|
//TODO: Use stack string here ?
|
||||||
std::string sign = evp_digest(pkey.get(), data, ec);
|
std::string sign = evp_digest(pkey.get(), data, ec);
|
||||||
if (ec) {
|
|
||||||
//TODO: handle error_code
|
|
||||||
return {std::move(sign), ec};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Hasher::type != EVP_PKEY_EC) {
|
if (ec) return { std::string{}, ec };
|
||||||
return {std::move(sign), ec};
|
|
||||||
} else {
|
if (Hasher::type == EVP_PKEY_EC) {
|
||||||
sign = public_key_ser(pkey.get(), sign, ec);
|
sign = public_key_ser(pkey.get(), sign, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {std::move(sign), ec};
|
return { std::move(sign), ec };
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -345,7 +414,7 @@ public:
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
static EVP_PKEY* load_key(const string_view key);
|
static EVP_PKEY* load_key(const string_view key, std::error_code& ec);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#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,
|
||||||
|
NoneAlgorithmUsed, // Not an actual error!
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Algorithm error conditions
|
||||||
|
*/
|
||||||
|
enum class AlgorithmFailureSource
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
std::error_code make_error_code(AlgorithmErrc 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 {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "jwt/impl/error_codes.ipp"
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef CPP_JWT_EXCEPTIONS_HPP
|
||||||
|
#define CPP_JWT_EXCEPTIONS_HPP
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
namespace jwt {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // END namespace jwt
|
||||||
|
|
||||||
|
#endif
|
|
@ -12,6 +12,7 @@ verify_result_t HMACSign<Hasher>::verify(
|
||||||
const string_view jwt_sign)
|
const string_view jwt_sign)
|
||||||
{
|
{
|
||||||
std::error_code ec{};
|
std::error_code ec{};
|
||||||
|
//TODO: remove these static deletors.
|
||||||
static auto bio_deletor = [](BIO* ptr) {
|
static auto bio_deletor = [](BIO* ptr) {
|
||||||
if (ptr) BIO_free_all(ptr);
|
if (ptr) BIO_free_all(ptr);
|
||||||
};
|
};
|
||||||
|
@ -77,21 +78,27 @@ verify_result_t HMACSign<Hasher>::verify(
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Hasher>
|
template <typename Hasher>
|
||||||
EVP_PKEY* PEMSign<Hasher>::load_key(const string_view key)
|
EVP_PKEY* PEMSign<Hasher>::load_key(
|
||||||
|
const string_view key,
|
||||||
|
std::error_code& ec)
|
||||||
{
|
{
|
||||||
auto bio_deletor = [](BIO* ptr) {
|
static auto bio_deletor = [](BIO* ptr) {
|
||||||
if (ptr) BIO_free(ptr);
|
if (ptr) BIO_free(ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
std::unique_ptr<BIO, decltype(bio_deletor)>
|
std::unique_ptr<BIO, decltype(bio_deletor)>
|
||||||
bio_ptr{BIO_new_mem_buf((void*)key.data(), key.length()), bio_deletor};
|
bio_ptr{BIO_new_mem_buf((void*)key.data(), key.length()), bio_deletor};
|
||||||
|
|
||||||
if (!bio_ptr) {
|
if (!bio_ptr) {
|
||||||
return nullptr;
|
throw MemoryAllocationException("BIO_new_mem_buf failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio_ptr.get(), nullptr, nullptr, nullptr);
|
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio_ptr.get(), nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
if (!pkey) {
|
if (!pkey) {
|
||||||
|
ec = AlgorithmErrc::SigningErr;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,36 +111,37 @@ std::string PEMSign<Hasher>::evp_digest(
|
||||||
const string_view data,
|
const string_view data,
|
||||||
std::error_code& ec)
|
std::error_code& ec)
|
||||||
{
|
{
|
||||||
auto md_deletor = [](EVP_MD_CTX* ptr) {
|
static auto md_deletor = [](EVP_MD_CTX* ptr) {
|
||||||
if (ptr) EVP_MD_CTX_destroy(ptr);
|
if (ptr) EVP_MD_CTX_destroy(ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
std::unique_ptr<EVP_MD_CTX, decltype(md_deletor)>
|
std::unique_ptr<EVP_MD_CTX, decltype(md_deletor)>
|
||||||
mdctx_ptr{EVP_MD_CTX_create(), md_deletor};
|
mdctx_ptr{EVP_MD_CTX_create(), md_deletor};
|
||||||
|
|
||||||
if (!mdctx_ptr) {
|
if (!mdctx_ptr) {
|
||||||
//TODO: set appropriate error_code
|
throw MemoryAllocationException("EVP_MD_CTX_create failed");
|
||||||
return std::string{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Initialiaze the digest algorithm
|
//Initialiaze the digest algorithm
|
||||||
if (EVP_DigestSignInit(
|
if (EVP_DigestSignInit(
|
||||||
mdctx_ptr.get(), nullptr, Hasher{}(), nullptr, pkey) != 1) {
|
mdctx_ptr.get(), nullptr, Hasher{}(), nullptr, pkey) != 1) {
|
||||||
//TODO: set appropriate error_code
|
ec = AlgorithmErrc::SigningErr;
|
||||||
return std::string{};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
//Update the digest with the input data
|
//Update the digest with the input data
|
||||||
if (EVP_DigestSignUpdate(mdctx_ptr.get(), data.data(), data.length()) != 1) {
|
if (EVP_DigestSignUpdate(mdctx_ptr.get(), data.data(), data.length()) != 1) {
|
||||||
//TODO: set appropriate error_code
|
ec = AlgorithmErrc::SigningErr;
|
||||||
return std::string{};
|
return std::string{};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long len = 0;
|
unsigned long len = 0;
|
||||||
|
|
||||||
if (EVP_DigestSignFinal(mdctx_ptr.get(), nullptr, &len) != 1) {
|
if (EVP_DigestSignFinal(mdctx_ptr.get(), nullptr, &len) != 1) {
|
||||||
//TODO: set appropriate error_code
|
ec = AlgorithmErrc::SigningErr;
|
||||||
return std::string{};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sign;
|
std::string sign;
|
||||||
|
@ -141,8 +149,8 @@ std::string PEMSign<Hasher>::evp_digest(
|
||||||
|
|
||||||
//Get the signature
|
//Get the signature
|
||||||
if (EVP_DigestSignFinal(mdctx_ptr.get(), (unsigned char*)&sign[0], &len) != 1) {
|
if (EVP_DigestSignFinal(mdctx_ptr.get(), (unsigned char*)&sign[0], &len) != 1) {
|
||||||
//TODO: set appropriate error_code
|
ec = AlgorithmErrc::SigningErr;
|
||||||
return std::string{};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return sign;
|
return sign;
|
||||||
|
@ -157,6 +165,7 @@ std::string PEMSign<Hasher>::public_key_ser(
|
||||||
// Get the EC_KEY representing a public key and
|
// Get the EC_KEY representing a public key and
|
||||||
// (optionaly) an associated private key
|
// (optionaly) an associated private key
|
||||||
std::string new_sign;
|
std::string new_sign;
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
static auto eckey_deletor = [](EC_KEY* ptr) {
|
static auto eckey_deletor = [](EC_KEY* ptr) {
|
||||||
if (ptr) EC_KEY_free(ptr);
|
if (ptr) EC_KEY_free(ptr);
|
||||||
|
@ -170,8 +179,8 @@ std::string PEMSign<Hasher>::public_key_ser(
|
||||||
ec_key{EVP_PKEY_get1_EC_KEY(pkey), eckey_deletor};
|
ec_key{EVP_PKEY_get1_EC_KEY(pkey), eckey_deletor};
|
||||||
|
|
||||||
if (!ec_key) {
|
if (!ec_key) {
|
||||||
//TODO set a valid error code
|
ec = AlgorithmErrc::SigningErr;
|
||||||
return std::string{};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key.get()));
|
uint32_t degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key.get()));
|
||||||
|
@ -183,8 +192,8 @@ std::string PEMSign<Hasher>::public_key_ser(
|
||||||
ecsig_deletor};
|
ecsig_deletor};
|
||||||
|
|
||||||
if (!ec_sig) {
|
if (!ec_sig) {
|
||||||
//TODO set a valid error code
|
ec = AlgorithmErrc::SigningErr;
|
||||||
return std::string{};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const BIGNUM* ec_sig_r = nullptr;
|
const BIGNUM* ec_sig_r = nullptr;
|
||||||
|
@ -192,7 +201,7 @@ std::string PEMSign<Hasher>::public_key_ser(
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
//Taken from https://github.com/nginnever/zogminer/issues/39
|
//Taken from https://github.com/nginnever/zogminer/issues/39
|
||||||
auto ECDSA_SIG_get0 = [](const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
|
static auto ECDSA_SIG_get0 = [](const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
|
||||||
{
|
{
|
||||||
if (pr != nullptr) *pr = sig->r;
|
if (pr != nullptr) *pr = sig->r;
|
||||||
if (ps != nullptr) *ps = sig->s;
|
if (ps != nullptr) *ps = sig->s;
|
||||||
|
@ -207,8 +216,8 @@ std::string PEMSign<Hasher>::public_key_ser(
|
||||||
auto bn_len = (degree + 7) / 8;
|
auto bn_len = (degree + 7) / 8;
|
||||||
|
|
||||||
if ((r_len > bn_len) || (s_len > bn_len)) {
|
if ((r_len > bn_len) || (s_len > bn_len)) {
|
||||||
//TODO set a valid error code
|
ec = AlgorithmErrc::SigningErr;
|
||||||
return std::string{};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto buf_len = 2 * bn_len;
|
auto buf_len = 2 * bn_len;
|
||||||
|
|
48
include/jwt/impl/error_codes.ipp
Normal file
48
include/jwt/impl/error_codes.ipp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#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::NoneAlgorithmUsed:
|
||||||
|
return "none algorithm used";
|
||||||
|
};
|
||||||
|
|
||||||
|
assert (0 && "Code not reached");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create global object for the error categories
|
||||||
|
const AlgorithmErrCategory theAlgorithmErrCategory {};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create the AlgorithmErrc error code
|
||||||
|
std::error_code make_error_code(AlgorithmErrc err)
|
||||||
|
{
|
||||||
|
return { static_cast<int>(err), theAlgorithmErrCategory };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // END namespace jwt
|
||||||
|
|
||||||
|
#endif
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue