javajwtcompressiondeflateinflate

Java inflate exception on raw data


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());

Solution

  • 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.