diff --git a/include/jwt/algorithm.hpp b/include/jwt/algorithm.hpp index 439b505..7dd0f08 100644 --- a/include/jwt/algorithm.hpp +++ b/include/jwt/algorithm.hpp @@ -341,6 +341,25 @@ struct HMACSign } /** + * Verifies the JWT string against the signature using + * the provided key. + * + * Arguments: + * @key : The secret/key to use for the signing. + * Cannot be empty string. + * @head : The part of JWT encoded string representing header + * and the payload claims. + * @sign : The signature part of the JWT encoded string. + * + * Returns: + * verify_result_t + * verify_result_t::first set to true if verification succeeds. + * false otherwise. + * verify_result_t::second set to relevant error if verification fails. + * + * Exceptions: + * Any allocation failure will result in jwt::MemoryAllocationException + * being thrown. */ static verify_result_t verify(const string_view key, const string_view head, const string_view sign); @@ -382,6 +401,7 @@ struct HMACSign } /** + * Basically a no-op. Sets the error code to NoneAlgorithmUsed. */ static verify_result_t verify(const string_view key, const string_view head, const string_view sign) @@ -446,17 +466,10 @@ public: 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}; - } + verify(const string_view key, const string_view head, const string_view sign); private: /*! diff --git a/include/jwt/impl/algorithm.ipp b/include/jwt/impl/algorithm.ipp index df40b75..6352388 100644 --- a/include/jwt/impl/algorithm.ipp +++ b/include/jwt/impl/algorithm.ipp @@ -70,6 +70,31 @@ verify_result_t HMACSign::verify( return { ret, ec }; } + +template +verify_result_t PEMSign::verify( + const string_view key, + const string_view head, + const string_view jwt_sign) +{ + /* + * unsigned char *sig = NULL; + * EVP_MD_CTX *mdctx = NULL; + * ECDSA_SIG *ec_sig = NULL; + * BIGNUM *ec_sig_r = NULL; + * BIGNUM *ec_sig_s = NULL; + * EVP_PKEY *pkey = NULL; + * const EVP_MD *alg; + * int type; + * int pkey_type; + * BIO *bufkey = NULL; + * int ret = 0; + * int slen; + */ + std::error_code ec{}; + return { true, ec }; +} + template EVP_PKEY* PEMSign::load_key( const string_view key, diff --git a/include/jwt/impl/jwt.ipp b/include/jwt/impl/jwt.ipp index 3112a91..a5dfe56 100644 --- a/include/jwt/impl/jwt.ipp +++ b/include/jwt/impl/jwt.ipp @@ -5,7 +5,7 @@ namespace jwt { -template +template std::string to_json_str(const T& obj, bool pretty) { return pretty ? obj.create_json_obj().dump(2) @@ -248,7 +248,7 @@ void jwt_object::set_parameters() } template -jwt_payload& jwt_object::add_claim(const std::string& name, T&& value) +jwt_payload& jwt_object::add_claim(const string_view name, T&& value) { payload_.add_claim(name, std::forward(value)); return payload_; diff --git a/include/jwt/impl/string_view.ipp b/include/jwt/impl/string_view.ipp index e797776..8cdfd50 100644 --- a/include/jwt/impl/string_view.ipp +++ b/include/jwt/impl/string_view.ipp @@ -243,6 +243,75 @@ std::ostream& operator<< (std::ostream& os, basic_string_view sv) return os; } +namespace { + +/* + * Copy of gcc implementation of murmurhash + * hash_bytes.cc + */ + +inline size_t +unaligned_load(const char* p) +{ + std::size_t result; + std::memcpy(&result, p, sizeof(result)); + return result; +} + +inline size_t +hash_bytes(const void* ptr, size_t len, size_t seed) +{ + const size_t m = 0x5bd1e995; + size_t hash = seed ^ len; + const char* buf = static_cast(ptr); + + // Mix 4 bytes at a time into the hash. + while(len >= 4) + { + size_t k = unaligned_load(buf); + k *= m; + k ^= k >> 24; + k *= m; + hash *= m; + hash ^= k; + buf += 4; + len -= 4; + } + + // Handle the last few bytes of the input array. + switch(len) + { + case 3: + hash ^= static_cast(buf[2]) << 16; + //FALLTHROUGH + case 2: + hash ^= static_cast(buf[1]) << 8; + //FALLTHROUGH + case 1: + hash ^= static_cast(buf[0]); + hash *= m; + }; + + // Do a few final mixes of the hash. + hash ^= hash >> 13; + hash *= m; + hash ^= hash >> 15; + return hash; +} +} + } // END namespace jwt +/// Provide a hash specialization +namespace std { + template <> + struct hash + { + size_t operator()(const jwt::string_view& sv) const + { + return jwt::hash_bytes((void*)sv.data(), sv.length(), static_cast(0xc70f6907UL)); + } + }; +} + #endif diff --git a/include/jwt/jwt.hpp b/include/jwt/jwt.hpp index 8241383..8f4af64 100644 --- a/include/jwt/jwt.hpp +++ b/include/jwt/jwt.hpp @@ -94,7 +94,8 @@ string_view reg_claims_to_str(enum registered_claims claim) noexcept // Fwd declaration for friend functions to specify the // default arguments // See: https://stackoverflow.com/a/23336823/434233 -template +template {}>::type> std::string to_json_str(const T& obj, bool pretty=false); template @@ -106,7 +107,7 @@ struct write_interface { /*! */ - template + template friend std::string to_json_str(const T& obj, bool pretty); /*! @@ -284,7 +285,7 @@ public: // Exposed APIs /** */ template - bool add_claim(const std::string& cname, T&& cvalue, bool overwrite=false) + bool add_claim(const string_view cname, T&& cvalue, bool overwrite=false) { // Duplicate claim names not allowed // if overwrite flag is set to true. @@ -297,8 +298,6 @@ public: // Exposed APIs 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(cvalue); return true; @@ -521,7 +520,7 @@ public: // Exposed APIs /** */ template - jwt_payload& add_claim(const std::string& name, T&& value); + jwt_payload& add_claim(const string_view name, T&& value); /** */ diff --git a/include/jwt/test/test_jwt_object b/include/jwt/test/test_jwt_object index b7b02b1..c9600cf 100755 Binary files a/include/jwt/test/test_jwt_object and b/include/jwt/test/test_jwt_object differ diff --git a/include/jwt/test/test_jwt_object.cc b/include/jwt/test/test_jwt_object.cc index 34f4ee0..b41ffbc 100644 --- a/include/jwt/test/test_jwt_object.cc +++ b/include/jwt/test/test_jwt_object.cc @@ -1,4 +1,7 @@ #include +#include +#include +#include #include "jwt/jwt.hpp" void basic_jwt_object_test() @@ -8,6 +11,27 @@ void basic_jwt_object_test() {"a", "b"}, {"c", "d"} })); + //check with std::map + std::map m; + m["a"] = "b"; + m["c"] = "d"; + + jwt::jwt_object obj1{payload(m)}; + auto obj2 = std::move(obj1); + + std::cout << obj2.payload() << std::endl; + + //check with unordered map of string_view + std::unordered_map um = { + {"a", "b"}, + {"c", "d"} + }; + jwt::jwt_object obj3{payload(um)}; + + obj3.add_claim("f", true) + .add_claim("time", 176353563); + + std::cout << jwt::to_json_str(obj3.payload(), true) << std::endl; } int main() {