Search code examples
javascriptpythonnode.jsbase64zlib

zlib nodejs incorrect header check, why?


I have a problem which i can't understand.

i'm trying to decompress a base64 string with zlib in javascript (nodejs)

const {inflateSync} = require('zlib')
const base64Data = "7ZW9DoIwEIDf5WYwvesfdnfWRAbFOBDDQIxgoE6Edxd9AXuTDLdc0uQbrl/zpRMc+rGNbd9BuExQto9mjPXjCQFIkc7VNkdXIgVrgvYbhVhYchVksOvi0DYjhAnwM46xjq/lCPuuHOrbfUFOEFQG5++sljlnQOmoSUdRMVjGtsjZwTHYgmGMcTdi6CXNYBkeyKezmvEWhuHBMPa1Np11DGee4aFI9jDP2e9KtcZCGYlUIpVIVxup1ei9lq9UKpVK11upt+iNIqlUKpVK/1PpdX4D"

try{
    const decoded_data = inflateSync(Buffer.from(base64Data, 'base64'));
    console.log(decoded_data.toString());
}catch (error) {
    console.error(error)
}

but it throws me an error

Error: incorrect header check
    at Zlib.zlibOnError [as onerror] (node:zlib:189:17)
    at processChunkSync (node:zlib:457:12)
    at zlibBufferSync (node:zlib:178:12)
    at syncBufferWrapper (node:zlib:792:14)
    at Object.<anonymous> (/Users/docs/index.js:15:26)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12) {
  errno: -3,
  code: 'Z_DATA_ERROR'
}

Process finished with exit code 0

do i need to add something more?

am i doing something wrong?

What i understand is that the windows size bits is wrong , but javascript doesn't allow negative windows as python allows

Thanks to all

In Python I have de following script to decompress some data from base64 and it works well

import base64
import zlib

data="7ZW9DoIwEIDf5WYwvesfdnfWRAbFOBDDQIxgoE6Edxd9AXuTDLdc0uQbrl/zpRMc+rGNbd9BuExQto9mjPXjCQFIkc7VNkdXIgVrgvYbhVhYchVksOvi0DYjhAnwM46xjq/lCPuuHOrbfUFOEFQG5++sljlnQOmoSUdRMVjGtsjZwTHYgmGMcTdi6CXNYBkeyKezmvEWhuHBMPa1Np11DGee4aFI9jDP2e9KtcZCGYlUIpVIVxup1ei9lq9UKpVK11upt+iNIqlUKpVK/1PpdX4D"

decoded_data =  zlib.decompress(base64.b64decode(data), -zlib.MAX_WBITS)
print(decoded_data)

the result is something like this

{
  "Position":[
    {
      "Timestamp":"2023-09-16T12:54:37.0118526Z",
      "Entries":{
        "1":{"Status":"OnTrack","X":0,"Y":0,"Z":0},
        "2":{"Status":"OnTrack","X":0,"Y":0,"Z":0}
      }
    }
    ....
  ]
}

Solution

  • Use inflateRawSync instead of inflateSync. Then it will work.

    const {inflateRawSync} = require('zlib')
    const base64Data = "7ZW9DoIwEIDf5WYwvesfdnfWRAbFOBDDQIxgoE6Edxd9AXuTDLdc0uQbrl/zpRMc+rGNbd9BuExQto9mjPXjCQFIkc7VNkdXIgVrgvYbhVhYchVksOvi0DYjhAnwM46xjq/lCPuuHOrbfUFOEFQG5++sljlnQOmoSUdRMVjGtsjZwTHYgmGMcTdi6CXNYBkeyKezmvEWhuHBMPa1Np11DGee4aFI9jDP2e9KtcZCGYlUIpVIVxup1ei9lq9UKpVK11upt+iNIqlUKpVK/1PpdX4D"
    
    try{
        const decoded_data = inflateRawSync(Buffer.from(base64Data, 'base64'));
        console.log(decoded_data.toString());
    }catch (error) {
        console.error(error)
    }
    

    (By the way: I thought unzipSync should also work, given its description below, but for some reason, unzipSync throws Error: incorrect header check too.)

    References:

    From https://nodejs.org/api/zlib.html:

    • zlib.inflateRawSync(buffer[, options]): Decompress a chunk of data with InflateRaw.
    • Class: zlib.InflateRaw: Decompress a raw deflate stream.
    • zlib.unzipSync(buffer[, options]): Decompress a chunk of data with Unzip.
    • Class: zlib.Unzip: Decompress either a Gzip- or Deflate-compressed stream by auto-detecting the header.

    From https://docs.python.org/3/library/zlib.html:

    The wbits parameter controls the size of the history buffer (or “window size”), and what header and trailer format is expected. It is similar to the parameter for compressobj(), but accepts more ranges of values:

    • +8 to +15: The base-two logarithm of the window size. The input must include a zlib header and trailer.
    • 0: Automatically determine the window size from the zlib header. Only supported since zlib 1.2.3.5.
    • −8 to −15: Uses the absolute value of wbits as the window size logarithm. The input must be a raw stream with no header or trailer.
    • +24 to +31 = 16 + (8 to 15): Uses the low 4 bits of the value as the window size logarithm. The input must include a gzip header and trailer.
    • +40 to +47 = 32 + (8 to 15): Uses the low 4 bits of the value as the window size logarithm, and automatically accepts either the zlib or gzip format.