From 733696bf49ba5af51e2a9b7a5b03d75d7ceec99a Mon Sep 17 00:00:00 2001 From: Arun M Date: Fri, 3 Nov 2017 19:55:17 +0530 Subject: [PATCH] Added RSA algorithms (Not tested) --- include/jwt/algorithm.hpp | 172 +++++++++++++++++++++++++++++++++++++ include/jwt/test/test_hmac | Bin 16764 -> 16764 bytes 2 files changed, 172 insertions(+) diff --git a/include/jwt/algorithm.hpp b/include/jwt/algorithm.hpp index f9904f4..9cdb08d 100644 --- a/include/jwt/algorithm.hpp +++ b/include/jwt/algorithm.hpp @@ -4,9 +4,12 @@ #include #include +#include #include +#include #include #include +#include #include #include "jwt/string_view.hpp" @@ -225,7 +228,176 @@ struct HMACSign /*! */ +template +struct PEMSign +{ +public: + /// The type of Hashing algorithm + using hasher_type = Hasher; + /*! + */ + static sign_result_t sign(string_view key, string_view data) + { + std::error_code ec{}; + + EVP_PKEY* pkey = load_key(key); + if (!pkey) { + //TODO: set valid error code + return {std::string{}, ec}; + } + + //TODO: Use stack string here ? + std::string sign = evp_digest(pkey, data, ec); + if (ec) { + //TODO: handle error_code + return {std::move(sign), ec}; + } + + if (Hasher::type != EVP_PKEY_EC) { + return {std::move(sign), ec}; + } else { + sign = public_key_ser(pkey, sign, ec); + } + + return {std::move(sign), ec}; + } + +private: + /*! + */ + static EVP_PKEY* load_key(const string_view key) + { + auto bio_deletor = [](BIO* ptr) { + if (ptr) BIO_free(ptr); + }; + + std::unique_ptr + bio_ptr{BIO_new_mem_buf((void*)key.data(), key.length()), bio_deletor}; + + if (!bio_ptr) { + return nullptr; + } + + EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio_ptr.get(), nullptr, nullptr, nullptr); + if (!pkey) { + return nullptr; + } + + return pkey; + } + + /*! + */ + static std::string evp_digest(EVP_PKEY* pkey, const string_view data, std::error_code& ec) + { + auto md_deletor = [](EVP_MD_CTX* ptr) { + if (ptr) EVP_MD_CTX_destroy(ptr); + }; + + std::unique_ptr + mdctx_ptr{EVP_MD_CTX_create(), md_deletor}; + + if (!mdctx_ptr) { + //TODO: set appropriate error_code + return std::string{}; + } + + //Initialiaze the digest algorithm + if (EVP_DigestSignInit( + mdctx_ptr.get(), nullptr, Hasher{}(), nullptr, pkey) != 1) { + //TODO: set appropriate error_code + return std::string{}; + } + + //Update the digest with the input data + if (EVP_DigestSignUpdate(mdctx_ptr.get(), data.data(), data.length()) != 1) { + //TODO: set appropriate error_code + return std::string{}; + } + + uint32_t len = 0; + + if (EVP_DigestSignFinal(mdctx_ptr.get(), nullptr, &len) != 1) { + //TODO: set appropriate error_code + return std::string{}; + } + + std::string sign; + sign.resize(len); + + //Get the signature + if (EVP_DigestSignFinal(mdctx_ptr.get(), &sign[0], &len) != 1) { + //TODO: set appropriate error_code + return std::string{}; + } + + return sign; + } + + + static std::string public_key_ser(EVP_PKEY* pkey, string_view sign, std::error_code& ec) + { + // Get the EC_KEY representing a public key and + // (optionaly) an associated private key + std::string new_sign; + + auto eckey_deletor = [](EC_KEY* ptr) { + if (ptr) EC_KEY_free(ptr); + }; + + std::unique_ptr + ec_key{EVP_PKEY_get1_EC_KEY(pkey), eckey_deletor}; + + if (!ec_key) { + //TODO set a valid error code + return std::string{}; + } + + 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()); + if (!ec_sig) { + //TODO set a valid error code + return std::string{}; + } + + const BIGNUM* ec_sig_r = nullptr; + const BIGNUM* ec_sig_s = nullptr; + +#if 1 + //Taken from https://github.com/nginnever/zogminer/issues/39 + auto ECDSA_SIG_get0 = [](const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) + { + if (pr != nullptr) *pr = sig->r; + if (ps != nullptr) *ps = sig->s; + }; + +#endif + + ECDSA_SIG_get0(ec_sig, &ec_sig_r, &ec_sig_s); + + auto r_len = BN_num_bytes(ec_sig_r); + auto s_len = BN_num_bytes(ec_sig_s); + auto bn_len = (degree + 7) / 8; + + if ((r_len > bn_len) || (s_len > bn_len)) { + //TODO set a valid error code + return std::string{}; + } + + auto buf_len = 2 * bn_len; + new_sign.resize(buf_len); + + BN_bn2bin(ec_sig_r, (unsigned char*)&new_sign[0] + bn_len - r_len); + BN_bn2bin(ec_sig_s, (unsigned char*)&new_sign[0] + buf_len - s_len); + + return new_sign; + } + +}; } // END namespace jwt diff --git a/include/jwt/test/test_hmac b/include/jwt/test/test_hmac index e2518551bce2b2213f1153f6f9f8e45f2343a301..2f78e44f2fe6aa05d82101378a8100e369cca989 100755 GIT binary patch delta 1683 zcmY*aUuc_E6u)1)+OMrPsTEtLF`t4MABwGXI)u?U2wt_F^}$iWKa)Ku_|iQneXu6k zyqLq~LdHj+Pa}e0>QgjEA`(d5MoQggoCtjoj6U7qpxav+tMQz36VyQN@BV(@Ip^Mc z&bi-r_nde4oR@D+1j9mjLWu7lzyW{3SAQ%XiJo}+%aaE`&TpO9`|muvpS>B*4JEwO zmDh)wUbr$m{_xjRLP)dGwx6M!G)K1_Z`ljs`tV%hV^lj74Q+DvEw889DpyIuQ>GuyPg z;miI*GdCS=*)RI;7ipq5GWL})UK>CW4x}-we|NhQ%o>4q0A}4W1~3_9 zOIk62$~ndWD(@Hrs7>+%Qzp<3z|*de1@uEs2?15 zyV*Kf4We1({49=|y4`^$$lhTeP&>R`(?E!P@)U|vtHxpYMkJPwVl8W^ zcaHaEI$5fLD>QJ09mE~P7Gg_gw<+gH_mJ)(wh`OC2pE$B$-z_}lUC*>+tL`ykOUu( zY)R8q%7f;UOPw}!TMOLU4b;uQA$v(Y@L9P7EzDm*a>jJ+EDfB z-l!Ftm?a$Trx>c!!Ch;v6tt1MzSIZMk>J=1oktZL&_bHJhlye_mL7~ieSOjntK z3HVuc+C5{Y9fN9u#cCqFdhbk{Ex;t5Ap;oc7z3CU#~8pILx$~*Bc%efTEvrP>m>a5 zf)eKoO7{O=P?CEWl%}0Cd_%S3!dn{^B0nky%80E|;YG)USQ!&uF(SNtxE+7j%Y;t` zPk80ZtHJM+(c-um6z!-ejyDE^x#DP;TnHvIzWdB9;`)zx8BwmBT}adNw~xm0!!q&A H`(ytAbNE>g delta 1564 zcmYjRU1(fI6rQ_jx;Kg0A7jZz6L%vNBN$yF)gZ*iV(M5LS;3crrSYjjLDGj33x?f| z9oTUgSh*}Lc_;x9`l6()D=oN~*us{Ab=$raeefzi%%b4-ZIQO?cV^P)!p=A6o9~>N zbI#1YzwX^%_sXqgF3On47*kJRz%O^{x5N7qlXK_7KQ>-F^4Y0-tLZyez6!GaQ(n1t zqQB_{EBmuSCK`KkeUve-*Ftj!u3R5F=j@hwKj6{q)Z1X&6cL(|dBJMds^%a~)ZEb& zEu6h*P6nINiOAp4;QQz^ug0CKWp0dEztHT^qGgW%3n#0Z zjo>MNZ2UWCw#@1y_m60z)(R#aQb*PUfS>K0jf=uCviPUd7?t&sJ6u&L2ygDYK_ML7PyLiu(Y}f@aV?f@s0G8D3t@g9%P5Mu zLKAuOrQ7DjmAG6h1IxfFup0k%wD`NnCK)UKW8I{p^gIY%+Eo zTzhVhIy*L#Ckg@!eRg+LW7~!ZaX3nyOCPyVwp`UIL1j}yi6{+RB--&ft_Q#r6WCCS z%b2^uD?0}@OQDJl0y=429K@J!XE37Z)J=K^Vu>dDJ&fjE#A;tc=h1E3y}e>BQ?ZnG zQ1Kzg6*CreXhGa1P{NWpskQ2sM7POZ>h8ndX<)tMq?T30(xUISuz*|aJW`Idma1Dz z>a1O>Pq{T~DQC(0tR?HS!L7%}4_JlNIVZFrb#Ngyp68%&&oH7IRKG3Muh<~s{||(0 z`#?zl-vc3f_kqyVJrE^qT2drPt9AjMtWaz&kEOVp_qjZh;rbO@{-$^ysnbIwrBV&*jrkdC@$`8*Xzi!rKjS0AaJh;95FPawXon-UA16+EUM`qUj}Fk+ zxHQ377%ZmWoG$EVtn4$dFu>UM0Q2St8Cx1;kpggYka;06GsL`=IP;c*o%CsMD|jyR ztQXea$^1H!XvJ6`D<@eiwjIf2I|IS|OeVSIyYKyB?Ekb^U}5ddOrEyCcPNc7eDdWF GhyDdAco8!I