JWT encoding

This commit is contained in:
Arun M 2017-11-05 12:31:32 +05:30
parent e7d52450d6
commit 8277e2cbd3
5 changed files with 156 additions and 3 deletions

View file

@ -3,10 +3,11 @@
#include <array>
#include <cassert>
#include "jwt/string_view.hpp"
namespace jwt {
/*
/*!
* Encoding map.
*/
class EMap
@ -30,7 +31,8 @@ private:
};
};
/*!
*/
std::string base64_encode(const char* in, size_t len)
{
std::string result;
@ -120,7 +122,8 @@ private:
};
};
/*!
*/
std::string base64_decode(const char* in, size_t len)
{
std::string result;
@ -184,6 +187,31 @@ std::string base64_decode(const char* in, size_t len)
return result;
}
/*!
*/
void 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;
}
} // END namespace jwt

View file

@ -30,6 +30,75 @@ std::ostream& operator<< (std::ostream& os, const T& obj)
return os;
}
std::string jwt_signature::encode(const jwt_header& header,
const jwt_payload& payload)
{
std::string jwt_msg;
//TODO: Optimize allocations
sign_func_t sign_fn = get_algorithm_impl(header);
std::string hdr_sign = header.base64_encode();
std::string pld_sign = payload.base64_encode();
base64_uri_encode(&hdr_sign[0], hdr_sign.length());
base64_uri_encode(&pld_sign[0], pld_sign.length());
std::string data = hdr_sign + '.' + pld_sign;
auto res = sign_fn(key_, data);
std::string b64hash = base64_encode(res.first.c_str(), res.first.length());
base64_uri_encode(&b64hash[0], b64hash.length());
jwt_msg = data + '.' + b64hash;
return jwt_msg;
}
sign_func_t
jwt_signature::get_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;
}
} // END namespace jwt

View file

@ -8,6 +8,7 @@
#include <ostream>
#include "jwt/base64.hpp"
#include "jwt/algorithm.hpp"
#include "jwt/string_view.hpp"
#include "jwt/detail/meta.hpp"
#include "jwt/json/json.hpp"
@ -342,6 +343,37 @@ private:
*/
struct jwt_signature
{
public: // 'tors
/// Default constructor
jwt_signature() = default;
/*!
*/
jwt_signature(string_view key)
: key_(key.data(), key.length())
{
}
/// Default copy and assignment operator
jwt_signature(const jwt_signature&) = default;
jwt_signature& operator=(const jwt_signature&) = default;
~jwt_signature() = default;
public: // Exposed APIs
/*!
*/
std::string encode(const jwt_header& header,
const jwt_payload& payload);
private: // Private implementation
/*!
*/
sign_func_t get_algorithm_impl(const jwt_header& hdr) const noexcept;
private: // Data members;
/// The key for creating the JWS
std::string key_;
};

Binary file not shown.

View file

@ -0,0 +1,24 @@
#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"};
auto res = sgn.sign(hdr, jp);
std::cout << res << std::endl;
}
int main() {
basic_sign_test();
return 0;
}