我对openssl接口和base64解码规则很陌生,并尝试使用解决方案验证用私钥(RS256 alg)签名的JWT:Segmentation Fault while verifying JWT token using a public key through openSSL in C++但是我的示例JWT失败了验证。
我只是没有base64 url解码功能,所以我按照我的理解手动执行了这些步骤-在调用我的base64解码功能之前,我替换了'-'->'+'和'_'->'/'。为了能够获得正确的签名长度,我还必须手动添加填充('=')。是否有一些我遗漏的base64 url解码规则,或者首先替换符号的方法是否有任何错误?
我首先尝试使用 RSA_verify,但错误是一样的。
使用 python 和在线 JWT 验证来验证相同的令牌和密钥,所以它们应该没问题。我在gdb上的十六进制b64解码和python上的urlsafe_b64decode之后打印了签名,并且值是相同的(除了python版本末尾的一些符号),这更让人相信替换策略应该是在职的。
// This is the original token
static constexpr const char* buffer_token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiYXBpLXJlc291cmNlIl0sInNjb3BlIjpbInJlYWQiXSwiZXhwIjoxNTYzNDUwODkzLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMzVhYmVjZDEtNjcxMi00M2M3LWE4MDItZjg3MGYzMTY4MmI0IiwiY2xpZW50X2lkIjoidGVzdCJ9.ZCXtI2nN-d0Cn5dgb3K9JMI41nrEaK_AVSMRG9c5cyZqXpnMQETfGcDEs0jPzmRh-jDc-Kuq53naOtjkItMcR_vYPn72dKZ4Fpp8mvOAZXypkVCLzof3Lsxrtqq9G3V4LNTuOHiXW_q-9mEu51zWg1HDr1-rSt3YXkFFSWp5e4MWS2TNP1MB7lBbZC-kdMZ_GqZ9lrfNo2YqJR7tqcHOrfOmFTzqxVivEB8s-A0iEv_MwdlS6LpJBKU9-d94i1P9Lsqzlg7b_0ekRoYJEG4DXeNp2zxxBxZ1u3FBlIbyJoOGDmX-EU4A5eh2RlDdEvG1YF_zcMARpP1bFV86WTSOuQ";
// This is token with replaced symbols that I am testing before writing the method for url decode
static constexpr const char* buffer_token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiYXBpLXJlc291cmNlIl0sInNjb3BlIjpbInJlYWQiXSwiZXhwIjoxNTYzNDUwODkzLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMzVhYmVjZDEtNjcxMi00M2M3LWE4MDItZjg3MGYzMTY4MmI0IiwiY2xpZW50X2lkIjoidGVzdCJ9.ZCXtI2nN+d0Cn5dgb3K9JMI41nrEaK/AVSMRG9c5cyZqXpnMQETfGcDEs0jPzmRh+jDc+Kuq53naOtjkItMcR/vYPn72dKZ4Fpp8mvOAZXypkVCLzof3Lsxrtqq9G3V4LNTuOHiXW/q+9mEu51zWg1HDr1+rSt3YXkFFSWp5e4MWS2TNP1MB7lBbZC+kdMZ/GqZ9lrfNo2YqJR7tqcHOrfOmFTzqxVivEB8s+A0iEv/MwdlS6LpJBKU9+d94i1P9Lsqzlg7b/0ekRoYJEG4DXeNp2zxxBxZ1u3FBlIbyJoOGDmX+EU4A5eh2RlDdEvG1YF/zcMARpP1bFV86WTSOuQ==";
// this is how I create the RSA from a key, hopefully successfully because a key is returned with no error
RSA* create_public_rsa(const unsigned char* p_key)
{
BIO *keybio = BIO_new_mem_buf(p_key, -1); // -1: assume string is null terminated
if (!keybio)
{
return nullptr;
}
RSA* l_res = nullptr;
l_res = PEM_read_bio_RSA_PUBKEY(keybio, NULL, NULL, NULL);
BIO_free(keybio);
return l_res;
}
bool RSAVerifySignature(RSA* rsa, std::string const& token)
{
auto pub_key_handle = std::shared_ptr<EVP_PKEY>(EVP_PKEY_new(), EVP_PKEY_free);
if (!pub_key_handle)
{
return false;
}
RSA_up_ref(rsa);
EVP_PKEY_assign_RSA(pub_key_handle.get(), rsa);
std::string decoded_header(token, 0, token.find('.'));
std::string decoded_body;
decoded_body.append(token.begin()+ token.find('.')+1, token.begin() + token.rfind('.')-1);
std::string sig;
sig.append(token.begin() + token.rfind('.') + 1, token.end());
std::string sig_decoded;
base64_decode(sig.c_str(), sig.size(), sig_decoded);
EVP_MD_CTX* l_ctx = EVP_MD_CTX_create();
EVP_MD_CTX_init(l_ctx);
EVP_PKEY_CTX *pctx;
if (1 != EVP_DigestVerifyInit(l_ctx, /*&pctx*/nullptr,
EVP_sha256(), nullptr, pub_key_handle.get())) return false;
//pub_key_handle.reset();
if (1 != EVP_DigestVerifyUpdate(l_ctx, reinterpret_cast<const unsigned char*>(decoded_header.data()), decoded_header.length())) return false;
if (1 != EVP_DigestVerifyUpdate(l_ctx, ".", 1)) return false;
if (1 != EVP_DigestVerifyUpdate(l_ctx, reinterpret_cast<const unsigned char*>(decoded_body.data()), decoded_body.length())) return false;
if(1 == EVP_DigestVerifyFinal(l_ctx, reinterpret_cast<const unsigned char*>(sig_decoded.data()), sig_decoded.length())) return true;
// ERR_print_errors_fp(stdout);
ERR_load_crypto_strings();
char err[130];
while(auto e = ERR_get_error())
{
ERR_error_string(e, err);
fprintf(stderr, "Error verifying message: %s\n", err);
}
return false;
}
错误是:
header: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
body: eyJhdWQiOlsiYXBpLXJlc291cmNlIl0sInNjb3BlIjpbInJlYWQiXSwiZXhwIjoxNTYzNDUwODkzLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMzVhYmVjZDEtNjcxMi00M2M3LWE4MDItZjg3MGYzMTY4MmI0IiwiY2xpZW50X2lkIjoidGVzdCJ
sig: ZCXtI2nN+d0Cn5dgb3K9JMI41nrEaK/AVSMRG9c5cyZqXpnMQETfGcDEs0jPzmRh+jDc+Kuq53naOtjkItMcR/vYPn72dKZ4Fpp8mvOAZXypkVCLzof3Lsxrtqq9G3V4LNTuOHiXW/q+9mEu51zWg1HDr1+rSt3YXkFFSWp5e4MWS2TNP1MB7lBbZC+kdMZ/GqZ9lrfNo2YqJR7tqcHOrfOmFTzqxVivEB8s+A0iEv/MwdlS6LpJBKU9+d94i1P9Lsqzlg7b/0ekRoYJEG4DXeNp2zxxBxZ1u3FBlIbyJoOGDmX+EU4A5eh2RlDdEvG1YF/zcMARpP1bFV86WTSOuQ==
Error verifying message: error:04091068:rsa routines:INT_RSA_VERIFY:bad signature
error:04091068:rsa routines:INT_RSA_VERIFY:bad signature