Verification

This commit is contained in:
Arun M 2017-11-20 00:38:55 +05:30
parent 796abd6e65
commit 81e6b2392e
8 changed files with 125 additions and 30 deletions

Binary file not shown.

View file

@ -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

View file

@ -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] = '+';

View file

@ -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
) )
> >

View file

@ -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);

View file

@ -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

View file

@ -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.