I was trying to decode the JWT payload in java but this payload is compressed/deflated
"zip": "DEF"
java.util.zip.DataFormatException: incorrect header check
private static byte[] decompress(byte[] value) throws DataFormatException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(value.length);
Inflater decompressor = new Inflater();
try {
decompressor.setInput(value);
final byte[] buf = new byte[1024];
while (!decompressor.finished()) {
int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
}
} finally {
decompressor.end();
}
return bos.toByteArray();
}
public static void main(String[] args) throws Exception {
String payload = "7VPbjtMwEP2X4TUXO9CumjdYkFghoZVaFiHUB9eZNka-RLYTUVb5d8ZuKxW09AuQ8jL2mTPnHGeeYZLQPkM8Dgjtd-hjHEJb18EIH3sUOvaVFL4Lr6SbVMdXUNzAnIoyFTdxypjRql8iKmdhW4D02KGNSuj1uPuBMiZJ-175J_QhYVp4U7GKE2k6fTfaTmPCeAxu9BI3WT6cL4qzHZBOa2JLDAXQAH8kj8Q8av3FawJc-ltGgEvxAvEjSaV-Allh8EQijNLEB-vN280HujmoCW3K8OvHh_Wnb7CdydlOkfX3IiYSvlqxkr2mD-a5eFEGvy3j4Tq3AkIUcQzZpxk0RkypT0JKZfHedZlBuk7ZQ1YcjiGiIXh6GHqXXt9Vzh_qFGkdVFfL6ScRyNwJDbuDeTsXMJy9Zzl79GiTtuvoEgj93nmDPk8SMjqfGjoVBi1SSvdP68deeCPkkdxTMk7K0WeyFM9GmdPQhpdsWTZLEqJd_DyaXeIE_s_Imv-RnSJb_BUZS5ltZ8oNlCAtfNks2HLBOKe_eLf_80CFcHaZN1ZFXopBVXIKl8V15nqR64nXec3n3w";
byte[] byt = Base64.getUrlDecoder().decode(new String(payload).getBytes("UTF-8"));
byte[] b = decompress(byt);
String s = new String(b, StandardCharsets.UTF_8);
}
Some other folks in other programming language was able to crack this out using this, wondering how will I accomplish this in java?
const decompressedCard = zlib.inflateRawSync(decodedPayload);
const card = JSON.parse(decompressedCard.toString());
Ususally compressed payload is used in encrypted JWTs (JWE), but SMART Health Cards also use it in signed tokens (JWS). In both cases, the DEFLATE format as defined in RFC1951 is used. For Zlib (as shown in the example on the bottom of the question) you have to use deflateRaw
/inflateRaw
(DEFLATE without any Zlib or gz headers).
In case of the java.util.zip.Inflater
, initializing the inflater with
Inflater decompressor = new Inflater(true);
is setting the nowrap
parameter to true to decompress in raw mode (without header) data,
which is equal to using inflateRaw
in Node.js.
(see also https://docs.oracle.com/javase/7/docs/api/java/util/zip/Inflater.html)
With this setting, the code in the question works fine and the given example data can be inflated to a JSON.