私はかなり初心者の C++ プログラマーです (私はまだ大学生なので、一般的にかなり初心者のプログラマーだと思います)。C++ で JWT を生成しようとしています。ヘッダーとペイロードを生成してエンコードすることはできますが、openssl の hmac ライブラリを使用して生成した署名は、jwt.io で確認すると無効のようです。これは、私が見ていない微妙な間違いによるものだと感じています。私のバグを見つけていただければ幸いです。私のコードを一般的に改善する方法についての提案もあれば、それもいただければ幸いです。json には openssl と boost を使用する必要があることに注意してください。
****アップデート****
余分な新しい行が追加されており、これが認証中にエラーを引き起こしていることがわかりました。現在、私は str.erase を呼び出してそれらを削除していますが、誰かがどこに来ているかを教えてくれれば、文字列を操作する必要がないように感謝します
char* Auth::genJWT()
{
ptree pt;
std::stringstream jwt;
//Make and encode header
pt.put("typ","JWT");
pt.put("alg","HS256");
std::ostringstream buf;
write_json(buf, pt, false);
std::string header = buf.str();
jwt << base64_encode((unsigned char*)header.c_str(), (int) header.length());
//clear buffer
pt.clear();
buf.clear();
buf.str("");
//make pay load
pt.put("org_guid", Config::organization_guid);
pt.put("agent_guid", Config::agent_guid);
write_json(buf, pt, false);
std::string payload = buf.str();
jwt << '.' << base64_encode((unsigned char*)payload.c_str(), (int) payload.length());
//sign data
std::string signed_data = signToken(jwt.str());
jwt << '.' << base64_encode((unsigned char*) signed_data.c_str(), (int) signed_data.length());
//jwt made
std::cout << "JWT Token: " << jwt.str() << std::endl;
//Note I am testing by copying the token into an online debugger
//returning "" is not my bug
return "";
}
これは私がトークンに署名する方法です
std::string Auth::signToken(std::string to_sign)
{
//std::string key = Config::secret;
std::string key = "foo";
unsigned int len = 32;
unsigned char signed_data[32];
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, &key[0], (int) key.length(), EVP_sha256(), NULL);
HMAC_Update(&ctx, (unsigned char*)&to_sign[0], to_sign.length());
HMAC_Final(&ctx, signed_data, &len);
HMAC_CTX_cleanup(&ctx);
std::stringstream ss;
ss << std::setfill('0');
for(unsigned int i = 0; i < len; i++)
{
ss << signed_data[i];
}
return (ss.str());
}
これは、base64Url でデータをエンコードする方法です
std::string Auth::base64_encode(const unsigned char* input, int length)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
std::stringstream ss;
//make URL safe
for(unsigned int i = 0; i < bptr->length - 1; i++)
{
switch(bptr->data[i])
{
case '+':
ss << '_';
break;
case '/':
ss << '-';
break;
case '=':
//don't add in padding
break;
default:
ss << bptr->data[i];
break;
}
}
BIO_free_all(b64);
return (ss.str());
}