QByteArray encode(const QVariant &claim, const QByteArray &key) { if(!QCA::isSupported("hmac(sha256)")) return QByteArray(); QJson::Serializer serializer; QVariantMap header; header["typ"] = "JWT"; header["alg"] = "HS256"; QByteArray headerJson = serializer.serialize(header); if(headerJson.isNull()) return QByteArray(); QByteArray claimJson = serializer.serialize(claim); if(claimJson.isNull()) return QByteArray(); QByteArray headerPart = base64url(headerJson); QByteArray claimPart = base64url(claimJson); QByteArray sig = jws_sign(headerPart, claimPart, key); return headerPart + '.' + claimPart + '.' + sig; }
std::string fostlib::jws::sign_base64_string( f5::u8view header_b64, f5::u8view payload_b64, alg algorithm, f5::buffer<const f5::byte> key) { switch (algorithm) { case alg::HS256: { hmac digester{sha256, key}; digester << header_b64 << "." << payload_b64; return static_cast<std::string>( header_b64 + "." + payload_b64 + "." + base64url(digester.digest())); } case alg::EdDSA: { ed25519::keypair const kp{key}; auto const b64 = header_b64 + "." + payload_b64; auto const signature = kp.sign(f5::buffer<const f5::byte>{ reinterpret_cast<unsigned char const *>(b64.data()), b64.bytes()}); return static_cast<std::string>( string{b64 + "." + base64url(signature)}); } } #ifdef __GNUC__ /// g++ doesn't get the analysis correct here throw std::domain_error("This line can never be reached"); #endif }
std::string fostlib::jwt::mint::token(f5::buffer<const f5::byte> key) { std::string str_header, str_payload; json::unparse(str_header, header, false); json::unparse(str_payload, m_payload, false); auto buffer_header = base64url( std::vector<unsigned char>(str_header.begin(), str_header.end())); auto buffer_payload = base64url( std::vector<unsigned char>(str_payload.begin(), str_payload.end())); return jws::sign_base64_string( buffer_header, buffer_payload, algorithm, key); }
static QByteArray jws_sign(const QByteArray &header, const QByteArray &claim, const QByteArray &key) { QByteArray si = header + '.' + claim; return base64url(QCA::MessageAuthenticationCode("hmac(sha256)", key).process(si).toByteArray()); }