mirror of
https://github.com/arun11299/cpp-jwt.git
synced 2025-05-14 16:58:34 +00:00
Verification
This commit is contained in:
parent
796abd6e65
commit
81e6b2392e
8 changed files with 125 additions and 30 deletions
Binary file not shown.
|
@ -25,7 +25,7 @@ using sign_func_t = sign_result_t (*) (const string_view key,
|
||||||
const string_view data);
|
const string_view data);
|
||||||
///
|
///
|
||||||
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 header,
|
const string_view head,
|
||||||
const string_view jwt_sign);
|
const string_view jwt_sign);
|
||||||
|
|
||||||
namespace algo {
|
namespace algo {
|
||||||
|
@ -215,7 +215,7 @@ struct HMACSign<algo::NONE>
|
||||||
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)
|
||||||
{
|
{
|
||||||
int compare_res = 0;
|
bool compare_res = 0;
|
||||||
std::error_code ec{};
|
std::error_code ec{};
|
||||||
|
|
||||||
//TODO: Set the appropriate error code for none
|
//TODO: Set the appropriate error code for none
|
||||||
|
@ -268,6 +268,18 @@ public:
|
||||||
return {std::move(sign), ec};
|
return {std::move(sign), ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*/
|
||||||
|
static verify_result_t
|
||||||
|
verify(const string_view key, const string_view head, const string_view sign)
|
||||||
|
{
|
||||||
|
bool compare_res = 0;
|
||||||
|
std::error_code ec{};
|
||||||
|
|
||||||
|
//TODO: Set the appropriate error code for none
|
||||||
|
return {compare_res, ec};
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
|
@ -284,5 +296,7 @@ private:
|
||||||
|
|
||||||
} // END namespace jwt
|
} // END namespace jwt
|
||||||
|
|
||||||
|
#include "jwt/impl/algorithm.ipp"
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -189,7 +189,7 @@ std::string base64_decode(const char* in, size_t len)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
void base64_uri_encode(char* data, size_t len) noexcept
|
size_t base64_uri_encode(char* data, size_t len) noexcept
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
|
@ -209,7 +209,7 @@ void base64_uri_encode(char* data, size_t len) noexcept
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -219,7 +219,9 @@ std::string base64_uri_decode(const char* data, size_t len)
|
||||||
std::string uri_dec;
|
std::string uri_dec;
|
||||||
uri_dec.resize(len + 4);
|
uri_dec.resize(len + 4);
|
||||||
|
|
||||||
for (size_t i = 0; i < len; ++i) {
|
size_t i = 0;
|
||||||
|
|
||||||
|
for (; i < len; ++i) {
|
||||||
switch (data[i]) {
|
switch (data[i]) {
|
||||||
case '-':
|
case '-':
|
||||||
uri_dec[i] = '+';
|
uri_dec[i] = '+';
|
||||||
|
|
|
@ -26,7 +26,7 @@ template <typename T>
|
||||||
struct has_create_json_obj_member<T,
|
struct has_create_json_obj_member<T,
|
||||||
void_t<
|
void_t<
|
||||||
decltype(
|
decltype(
|
||||||
std::declval<T&&>.create_json_obj(),
|
std::declval<T&&>().create_json_obj(),
|
||||||
(void)0
|
(void)0
|
||||||
)
|
)
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef CPP_JWT_ALGORITHM_IPP
|
#ifndef CPP_JWT_ALGORITHM_IPP
|
||||||
#define CPP_JWT_ALGORITHM_IPP
|
#define CPP_JWT_ALGORITHM_IPP
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace jwt {
|
namespace jwt {
|
||||||
|
|
||||||
template <typename Hasher>
|
template <typename Hasher>
|
||||||
|
@ -14,10 +16,14 @@ verify_result_t HMACSign<Hasher>::verify(
|
||||||
if (ptr) BIO_free_all(ptr);
|
if (ptr) BIO_free_all(ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
using bio_deletor_t = decltype(bio_deletor);
|
std::cout << "Key: " << key << std::endl;
|
||||||
using BIO_unique_ptr = std::unique_ptr<BIO_unique_ptr, bio_deletor_t>;
|
std::cout << "Head: " << head << std::endl;
|
||||||
|
std::cout << "JWT: " << jwt_sign << std::endl;
|
||||||
|
|
||||||
BIO_unique_ptr b64{BIO_new(BIO_f_base64())};
|
using bio_deletor_t = decltype(bio_deletor);
|
||||||
|
using BIO_unique_ptr = std::unique_ptr<BIO, bio_deletor_t>;
|
||||||
|
|
||||||
|
BIO_unique_ptr b64{BIO_new(BIO_f_base64()), bio_deletor};
|
||||||
if (!b64) {
|
if (!b64) {
|
||||||
//TODO: set error code
|
//TODO: set error code
|
||||||
return {false, ec};
|
return {false, ec};
|
||||||
|
@ -29,10 +35,11 @@ verify_result_t HMACSign<Hasher>::verify(
|
||||||
return {false, ec};
|
return {false, ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
BIO_push(b64, bmem);
|
BIO_push(b64.get(), bmem);
|
||||||
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
BIO_set_flags(b64.get(), BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
|
||||||
unsigned char enc_buf[EVP_MAX_MD_SIZE];
|
unsigned char enc_buf[EVP_MAX_MD_SIZE];
|
||||||
|
uint32_t enc_buf_len = 0;
|
||||||
|
|
||||||
unsigned char* res = HMAC(Hasher{}(),
|
unsigned char* res = HMAC(Hasher{}(),
|
||||||
key.data(),
|
key.data(),
|
||||||
|
@ -41,12 +48,36 @@ verify_result_t HMACSign<Hasher>::verify(
|
||||||
head.length(),
|
head.length(),
|
||||||
enc_buf,
|
enc_buf,
|
||||||
&enc_buf_len);
|
&enc_buf_len);
|
||||||
|
if (!res) {
|
||||||
|
//TODO: set error code
|
||||||
|
return {false, ec};
|
||||||
|
}
|
||||||
|
|
||||||
return {true, ec};
|
BIO_write(b64.get(), enc_buf, enc_buf_len);
|
||||||
|
(void)BIO_flush(b64.get());
|
||||||
|
|
||||||
|
int len = BIO_pending(bmem);
|
||||||
|
if (len < 0) {
|
||||||
|
//TODO: set error code
|
||||||
|
return {false, ec};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cbuf;
|
||||||
|
cbuf.resize(len + 1);
|
||||||
|
|
||||||
|
len = BIO_read(bmem, &cbuf[0], len);
|
||||||
|
cbuf.resize(len);
|
||||||
|
|
||||||
|
//Make the base64 string url safe
|
||||||
|
auto new_len = jwt::base64_uri_encode(&cbuf[0], cbuf.length());
|
||||||
|
cbuf.resize(new_len);
|
||||||
|
std::cout << "cbuf: " << cbuf << std::endl;
|
||||||
|
|
||||||
|
return {string_view{cbuf} == jwt_sign, ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Hasher>
|
template <typename Hasher>
|
||||||
sign_result_t PEMSign<Hasher>::load_key(const string_view key)
|
EVP_PKEY* PEMSign<Hasher>::load_key(const string_view key)
|
||||||
{
|
{
|
||||||
auto bio_deletor = [](BIO* ptr) {
|
auto bio_deletor = [](BIO* ptr) {
|
||||||
if (ptr) BIO_free(ptr);
|
if (ptr) BIO_free(ptr);
|
||||||
|
|
|
@ -79,7 +79,7 @@ std::string jwt_signature::encode(const jwt_header& header,
|
||||||
std::string jwt_msg;
|
std::string jwt_msg;
|
||||||
//TODO: Optimize allocations
|
//TODO: Optimize allocations
|
||||||
|
|
||||||
sign_func_t sign_fn = get_algorithm_impl(header);
|
sign_func_t sign_fn = get_sign_algorithm_impl(header);
|
||||||
|
|
||||||
std::string hdr_sign = header.base64_encode();
|
std::string hdr_sign = header.base64_encode();
|
||||||
std::string pld_sign = payload.base64_encode();
|
std::string pld_sign = payload.base64_encode();
|
||||||
|
@ -88,7 +88,8 @@ std::string jwt_signature::encode(const jwt_header& header,
|
||||||
auto res = sign_fn(key_, data);
|
auto res = sign_fn(key_, data);
|
||||||
|
|
||||||
std::string b64hash = base64_encode(res.first.c_str(), res.first.length());
|
std::string b64hash = base64_encode(res.first.c_str(), res.first.length());
|
||||||
base64_uri_encode(&b64hash[0], b64hash.length());
|
auto new_len = base64_uri_encode(&b64hash[0], b64hash.length());
|
||||||
|
b64hash.resize(new_len);
|
||||||
|
|
||||||
jwt_msg = data + '.' + b64hash;
|
jwt_msg = data + '.' + b64hash;
|
||||||
|
|
||||||
|
@ -97,16 +98,18 @@ std::string jwt_signature::encode(const jwt_header& header,
|
||||||
|
|
||||||
bool jwt_signature::verify(const jwt_header& header,
|
bool jwt_signature::verify(const jwt_header& header,
|
||||||
const string_view hdr_pld_sign,
|
const string_view hdr_pld_sign,
|
||||||
const srting_view jwt_sign)
|
const string_view jwt_sign)
|
||||||
{
|
{
|
||||||
//TODO: is bool the right choice ?
|
//TODO: is bool the right choice ?
|
||||||
|
verify_func_t verify_fn = get_verify_algorithm_impl(header);
|
||||||
|
verify_fn(key_, hdr_pld_sign, jwt_sign);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sign_func_t
|
sign_func_t
|
||||||
jwt_signature::get_algorithm_impl(const jwt_header& hdr) const noexcept
|
jwt_signature::get_sign_algorithm_impl(const jwt_header& hdr) const noexcept
|
||||||
{
|
{
|
||||||
sign_func_t ret = nullptr;
|
sign_func_t ret = nullptr;
|
||||||
|
|
||||||
|
@ -148,16 +151,61 @@ jwt_signature::get_algorithm_impl(const jwt_header& hdr) const noexcept
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
|
|
||||||
void jwt_decode(string_view encoded_str, string_view key, bool validate)
|
void jwt_decode(const string_view encoded_str, const string_view key, bool validate)
|
||||||
{
|
{
|
||||||
//TODO: implement error_code
|
//TODO: implement error_code
|
||||||
size_t fpos = encoded_str.find_first_of('.');
|
size_t fpos = encoded_str.find_first_of('.');
|
||||||
assert (fpos != string_view::npos);
|
assert (fpos != string_view::npos);
|
||||||
|
|
||||||
string_view head{&encoded_str[0], fpos};
|
string_view head{&encoded_str[0], fpos};
|
||||||
std::cout << "Head: " << head << std::endl;
|
|
||||||
jwt_header hdr;
|
jwt_header hdr;
|
||||||
hdr.decode(head);
|
hdr.decode(head);
|
||||||
|
|
||||||
|
@ -166,13 +214,13 @@ void jwt_decode(string_view encoded_str, string_view key, bool validate)
|
||||||
//TODO: Check for none algorithm
|
//TODO: Check for none algorithm
|
||||||
}
|
}
|
||||||
string_view body{&encoded_str[fpos + 1], spos - fpos - 1};
|
string_view body{&encoded_str[fpos + 1], spos - fpos - 1};
|
||||||
std::cout << "Body: " << body << std::endl;
|
|
||||||
|
|
||||||
//Json objects or claims get set in the decode
|
//Json objects or claims get set in the decode
|
||||||
jwt_payload pld;
|
jwt_payload pld;
|
||||||
pld.decode(body);
|
pld.decode(body);
|
||||||
|
|
||||||
|
jwt_signature jsign{key};
|
||||||
|
jsign.verify(hdr, encoded_str.substr(0, spos), encoded_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // END namespace jwt
|
} // END namespace jwt
|
||||||
|
|
|
@ -176,7 +176,7 @@ struct write_interface
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T, typename Cond>
|
||||||
friend std::ostream& operator<< (std::ostream& os, const T& obj);
|
friend std::ostream& operator<< (std::ostream& os, const T& obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,12 +195,9 @@ struct base64_enc_dec
|
||||||
{
|
{
|
||||||
std::string jstr = to_json_str(*static_cast<const Derived*>(this), with_pretty);
|
std::string jstr = to_json_str(*static_cast<const Derived*>(this), with_pretty);
|
||||||
std::string b64_str = jwt::base64_encode(jstr.c_str(), jstr.length());
|
std::string b64_str = jwt::base64_encode(jstr.c_str(), jstr.length());
|
||||||
size_t rpos = b64_str.length();
|
|
||||||
while(b64_str[rpos-1] == '=') rpos--;
|
|
||||||
// Remove the '=' characters
|
|
||||||
b64_str.resize(rpos);
|
|
||||||
// Do the URI safe encoding
|
// Do the URI safe encoding
|
||||||
jwt::base64_uri_encode(&b64_str[0], b64_str.length());
|
auto new_len = jwt::base64_uri_encode(&b64_str[0], b64_str.length());
|
||||||
|
b64_str.resize(new_len);
|
||||||
|
|
||||||
return b64_str;
|
return b64_str;
|
||||||
}
|
}
|
||||||
|
@ -438,7 +435,11 @@ public: // Exposed APIs
|
||||||
private: // Private implementation
|
private: // Private implementation
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
sign_func_t get_algorithm_impl(const jwt_header& hdr) const noexcept;
|
sign_func_t get_sign_algorithm_impl(const jwt_header& hdr) const noexcept;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*/
|
||||||
|
verify_func_t get_verify_algorithm_impl(const jwt_header& hdr) const noexcept;
|
||||||
|
|
||||||
private: // Data members;
|
private: // Data members;
|
||||||
/// The key for creating the JWS
|
/// The key for creating the JWS
|
||||||
|
@ -461,12 +462,11 @@ private: // Data Members
|
||||||
jwt_header header_;
|
jwt_header header_;
|
||||||
/// JWT payload section
|
/// JWT payload section
|
||||||
jwt_payload payload_;
|
jwt_payload payload_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
void jwt_decode(string_view encoded_str, string_view key, bool validate=true);
|
void jwt_decode(const string_view encoded_str, const string_view key, bool validate=true);
|
||||||
|
|
||||||
|
|
||||||
} // END namespace jwt
|
} // END namespace jwt
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue