JWT/QByteArray::toBase64() adding a character at the end
-
I am trying to validate a JWT received by a server running PHP5. The debugger of the jwt.io website says my jwt is valid but validation isn't working out for me with QT5.5.
Below is my jwt:
eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJtaWtlLmdyZWVuaXNoQGFkZGhhcHRpY3MuY29tIiwiZGF0YSI6eyJjaWQiOiIxMDgwMTA4MDAwIiwibGljX2lkIjoiNSIsIm1vZHVsZXMiOjF9LCJleHAiOiIyMDE4LTA5LTI5VDE2OjE0OjQ0LTA0OjAwIiwiaWF0IjoiMjAxNy0wOS0yOVQxNjoxNDo0NC0wNDowMCIsImlzcyI6IkFkZCBIYXB0aWNzIn0.wiJ5D6zkk_K0JYizYQ-nAjlrEfZKyhIjOF8NcDLXnwWEGEzAjovcfUsLAcioVYBKhzVlOMydAPluTOfAD81H0QQT correctly base64 decodes the header and payload
Header:
{
"alg": "HS512",
"typ": "JWT"
}
Payload:
{
"aud": "mike.greenish@addhaptics.com",
"data": {
"cid": "1080108000",
"lic_id": "5",
"modules": 1
},
"exp": "2018-09-29T16:14:44-04:00",
"iat": "2017-09-29T16:14:44-04:00",
"iss": "Add Haptics"
}When I re-base64 encode the header, it matches the original. When I re-base64 encode the payload it matches the original plus there is an extra '=' at the end.
Header, json compacted then base64 encoded:
qDebug() << m_jdocHeader.toJson(QJsonDocument::JsonFormat::Compact).toUtf8().toBase64();eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9
Payload, json compacted then base64 encoded:
qDebug() << m_jdocPayload.toJson(QJsonDocument::JsonFormat::Compact).toUtf8().toBase64();eyJhdWQiOiJtaWtlLmdyZWVuaXNoQGFkZGhhcHRpY3MuY29tIiwiZGF0YSI6eyJjaWQiOiIxMDgwMTA4MDAwIiwibGljX2lkIjoiNSIsIm1vZHVsZXMiOjF9LCJleHAiOiIyMDE4LTA5LTI5VDE2OjE0OjQ0LTA0OjAwIiwiaWF0IjoiMjAxNy0wOS0yOVQxNjoxNDo0NC0wNDowMCIsImlzcyI6IkFkZCBIYXB0aWNzIn0=
From my jwt above, the payload should be
eyJhdWQiOiJtaWtlLmdyZWVuaXNoQGFkZGhhcHRpY3MuY29tIiwiZGF0YSI6eyJjaWQiOiIxMDgwMTA4MDAwIiwibGljX2lkIjoiNSIsIm1vZHVsZXMiOjF9LCJleHAiOiIyMDE4LTA5LTI5VDE2OjE0OjQ0LTA0OjAwIiwiaWF0IjoiMjAxNy0wOS0yOVQxNjoxNDo0NC0wNDowMCIsImlzcyI6IkFkZCBIYXB0aWNzIn0So it seems is an extra '=' generated by QT that php doesn't.
-
Actually, I have to correct my above statement, the php code passes the base64 encoded string through a filter to make it url safe, apparently:
public static function urlsafeB64Encode($input) { return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); }
So that is how the extra '=' doesn't show up in the jwt generated by php.
Nonetheless, even without the extra '=', when the 'header.payload' string is HMACSHA512 encoded, the signature calculated by QT doesn't match the signature in the jwt, so the validation fails.
The signature is calculated as follows during validation:
byteSignature = QMessageAuthenticationCode::hash( qba_Header + "." + qba_Payload, qbaSecret, QCryptographicHash::Sha512);original signature:
"\xC2"y\x0F\xAC\xE4\x90\xAD\tb,\xD8""Bp#\x96\xB1\x1F""d\xAC\xA1"3\x85\xF0\xD7\x03-y\xF0XA\x84\xCC\b\xE8\xBD\xC7\xD4\xB0\xB0\x1C\x8A\x85X\x04\xA8sVS\x8C\xC9\xD0\x0F\x96\xE4\xCE|\x00\xFC\xD4}\x10"calculated signature:
"\x84\fA%\xE1\td \x9A\x1F\xCDH\xA7\x83\xB1\x85g\xAC\xE6\x1B\xA9\x00,\x1C""c\xCF\x00\x83\xD6\xC4\x98~X\xF1}D\x9C\x9A\xEE-O\xDAT\x1E\i=2\xDA%T\x16""f\xC2\xA3M\x99\x1C\x17?\xA6\x15)R"As a reference, the signature is calculated as follows in php:
$segments = array(); $segments[] = static::urlsafeB64Encode(static::jsonEncode($header)); $segments[] = static::urlsafeB64Encode(static::jsonEncode($payload)); $signing_input = implode('.', $segments); $signature = static::sign($signing_input, $key, $alg); $segments[] = static::urlsafeB64Encode($signature); return implode('.', $segments);
Where static::sign returns:
hash_hmac($alg, $signing_input, $key, true);Why is QT not calculating the signature in the same way?
-
Hi,
For the motivation behind the implementation, you should rather bring this question to the interest mailing list. You'll find there Qt's developers/maintainers. This forum is more user oriented.