Payload data type addded

This commit is contained in:
Arun M 2017-11-04 19:21:46 +05:30
parent 733696bf49
commit e7d52450d6
8 changed files with 199 additions and 11 deletions

View file

@ -241,14 +241,20 @@ public:
{
std::error_code ec{};
EVP_PKEY* pkey = load_key(key);
static auto evpkey_deletor = [](EVP_PKEY* ptr) {
if (ptr) EVP_PKEY_free(ptr);
};
std::unique_ptr<EVP_PKEY, decltype(evpkey_deletor)>
pkey{load_key(key), evpkey_deletor};
if (!pkey) {
//TODO: set valid error code
return {std::string{}, ec};
}
//TODO: Use stack string here ?
std::string sign = evp_digest(pkey, data, ec);
std::string sign = evp_digest(pkey.get(), data, ec);
if (ec) {
//TODO: handle error_code
return {std::move(sign), ec};
@ -257,7 +263,7 @@ public:
if (Hasher::type != EVP_PKEY_EC) {
return {std::move(sign), ec};
} else {
sign = public_key_ser(pkey, sign, ec);
sign = public_key_ser(pkey.get(), sign, ec);
}
return {std::move(sign), ec};
@ -316,7 +322,7 @@ private:
return std::string{};
}
uint32_t len = 0;
unsigned long len = 0;
if (EVP_DigestSignFinal(mdctx_ptr.get(), nullptr, &len) != 1) {
//TODO: set appropriate error_code
@ -327,7 +333,7 @@ private:
sign.resize(len);
//Get the signature
if (EVP_DigestSignFinal(mdctx_ptr.get(), &sign[0], &len) != 1) {
if (EVP_DigestSignFinal(mdctx_ptr.get(), (unsigned char*)&sign[0], &len) != 1) {
//TODO: set appropriate error_code
return std::string{};
}
@ -342,10 +348,14 @@ private:
// (optionaly) an associated private key
std::string new_sign;
auto eckey_deletor = [](EC_KEY* ptr) {
static auto eckey_deletor = [](EC_KEY* ptr) {
if (ptr) EC_KEY_free(ptr);
};
static auto ecsig_deletor = [](ECDSA_SIG* ptr) {
if (ptr) ECDSA_SIG_free(ptr);
};
std::unique_ptr<EC_KEY, decltype(eckey_deletor)>
ec_key{EVP_PKEY_get1_EC_KEY(pkey), eckey_deletor};
@ -356,9 +366,13 @@ private:
uint32_t degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key.get()));
ECDSA_SIG* ec_sig = d2i_ECDSA_SIG(nullptr,
(const unsigned char**)&sign[0],
sign.length());
std::unique_ptr<ECDSA_SIG, decltype(ecsig_deletor)>
ec_sig{d2i_ECDSA_SIG(nullptr,
(const unsigned char**)&sign[0],
sign.length()),
ecsig_deletor};
if (!ec_sig) {
//TODO set a valid error code
return std::string{};
@ -377,7 +391,7 @@ private:
#endif
ECDSA_SIG_get0(ec_sig, &ec_sig_r, &ec_sig_s);
ECDSA_SIG_get0(ec_sig.get(), &ec_sig_r, &ec_sig_s);
auto r_len = BN_num_bytes(ec_sig_r);
auto s_len = BN_num_bytes(ec_sig_s);

View file

@ -127,6 +127,7 @@ std::string base64_decode(const char* in, size_t len)
result.resize(128);
int i = 0;
size_t bytes_rem = len;
size_t bytes_wr = 0;
constexpr static const DMap dmap{};
@ -150,6 +151,7 @@ std::string base64_decode(const char* in, size_t len)
i += 3;
in += 4;
}
bytes_wr = i;
switch(bytes_rem) {
case 4:
@ -157,6 +159,7 @@ std::string base64_decode(const char* in, size_t len)
auto third = dmap.at(in[2]);
auto fourth = dmap.at(in[3]);
result[i + 2] = (third << 6) | fourth;
bytes_wr++;
//FALLTHROUGH
}
case 3:
@ -164,6 +167,7 @@ std::string base64_decode(const char* in, size_t len)
auto second = dmap.at(in[1]);
auto third = dmap.at(in[2]);
result[i + 1] = (second << 4) | (third >> 2);
bytes_wr++;
//FALLTHROUGH
}
case 2:
@ -171,9 +175,12 @@ std::string base64_decode(const char* in, size_t len)
auto first = dmap.at(in[0]);
auto second = dmap.at(in[1]);
result[i] = (first << 2) | (second >> 4);
bytes_wr++;
}
};
result.resize(bytes_wr);
return result;
}

View file

@ -2,6 +2,8 @@
#define JWT_HPP
#include <cassert>
#include <cstring>
#include <set>
#include <string>
#include <ostream>
@ -156,12 +158,16 @@ struct write_interface
template <typename Derived>
struct base64_enc_dec
{
/*!
*/
std::string base64_encode(bool with_pretty = false) const
{
std::string jstr = to_json_str(*static_cast<const Derived*>(this), with_pretty);
return jwt::base64_encode(jstr.c_str(), jstr.length());
}
/*!
*/
static std::string base64_decode(const std::string& encoded_str)
{
return jwt::base64_decode(encoded_str.c_str(), encoded_str.length());
@ -233,6 +239,7 @@ public: // Exposed APIs
json_t create_json_obj() const
{
json_t obj = json_t::object();
//TODO: should be able to do with string_view
obj["typ"] = type_to_str(typ_).to_string();
obj["alg"] = alg_to_str(alg_).to_string();
@ -247,10 +254,88 @@ private: // Data members
enum type typ_ = type::JWT;
};
/*!
* JWT Payload
*/
struct jwt_payload
struct jwt_payload: write_interface
, base64_enc_dec<jwt_payload>
{
public: // 'tors
/*!
*/
jwt_payload() = default;
/// Default copy and assignment operations
jwt_payload(const jwt_payload&) = default;
jwt_payload& operator=(const jwt_payload&) = default;
~jwt_payload() = default;
public: // Exposed APIs
/*!
*/
template <typename T>
bool add_claim(const std::string& cname, T&& cvalue, bool overwrite=false)
{
// Duplicate claim names not allowed
// if overwrite flag is set to true.
auto itr = claim_names_.find(cname);
if (itr != claim_names_.end() && !overwrite) {
return false;
}
// Add it to the known set of claims
claim_names_.emplace(cname.data(), cname.length());
//Add it to the json payload
//TODO: claim name copied twice inside json
//and in the set
payload_[cname.data()] = std::forward<T>(cvalue);
return true;
}
/*!
*/
bool has_claim(const std::string& cname) const noexcept
{
return claim_names_.count(cname);
}
/*!
*/
template <typename T>
bool has_claim_with_value(const std::string& cname, T&& cvalue) const
{
auto itr = claim_names_.find(cname);
if (itr == claim_names_.end()) return false;
return (cvalue == payload_[cname]);
}
/*!
*/
const json_t& create_json_obj() const
{
return payload_;
}
private:
/*!
*/
struct case_compare {
bool operator()(const std::string& lhs, const std::string& rhs) const
{
int ret = strcasecmp(lhs.c_str(), rhs.c_str());
return (ret < 0);
}
};
/// JSON object containing payload
json_t payload_;
/// The set of claim names in the payload
std::set<std::string, case_compare> claim_names_;
};
/*!

View 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
include/jwt/test/test_jwt_payload Executable file

Binary file not shown.

View 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
include/jwt/test/test_rsa Executable file

Binary file not shown.

View 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;
}