gildas-lormeau / zip.js

JavaScript library to zip and unzip files supporting multi-core compression, compression streams, zip64, split files and encryption.
https://gildas-lormeau.github.io/zip.js
BSD 3-Clause "New" or "Revised" License
3.42k stars 512 forks source link

rawExtraField not present in each entry #227

Closed JCarlesVilaseca closed 3 years ago

JCarlesVilaseca commented 3 years ago

Using AES encription, WinZip writes 7 bytes extrafield in each file entry. Some other libraries (Zip4jUtil) can't open the zip file if extrafield is not present.

https://github.com/gildas-lormeau/zip.js/blob/103ca465742295168aca1cd60b78337d3aa56f94/lib/core/zip-writer.js#L408

Adding using options doesn't help:

    await writer.add('json.txt', new TextReader(json), {
      extraField: new Map([
        [0x9901, Uint8Array.from([0x02, 0x00, 0x41, 0x45, 0x03, 0x08, 0x00])],
      ]),
    });

WinZip:

Local directory entry PK0304 (4+26): #1
------------------------------------
    operat. system version needed to extract (00):  MS-DOS, OS/2, NT FAT
    unzip software version needed to extract (51):  5.1
    general purpose bit flag (0x0001) (bit 15..0):  0000.0000 0000.0001
      file security status  (bit 0):                encrypted
      extended local header (bit 3):                no
    compression method (99):                        AES encryption
    file last modified on (0x00005268 0x00008552):  2021-03-08 16:42:36
    32-bit CRC value:                               0x00000000
    compressed size:                                17748 bytes
    uncompressed size:                              29091 bytes
    length of filename:                             8 characters
    length of extra field:                          11 bytes
Current Location part 1 offset 30
    filename:json.txt
Current Location part 1 offset 38
    extra field 0x9901 (AES Encryption Tag), 4 header and 7 data bytes:
    02 00 41 45 03 08 00                            ..AE...
      Encryption Tag Version:           AE-2
      Encryption Key Bits:              256
      Compression Method (08):          deflated
      Compression Sub-Type (deflation): normal
Current Location part 1 offset 49
    testing: json.txt                 OK

zip.js

Local directory entry PK0304 (4+26): #1
------------------------------------
    operat. system version needed to extract (00):  MS-DOS, OS/2, NT FAT
    unzip software version needed to extract (51):  5.1
    general purpose bit flag (0x0809) (bit 15..0):  0000.1000 0000.1001
      file security status  (bit 0):                encrypted
      extended local header (bit 3):                yes
    compression method (99):                        AES encryption
    file last modified on (0x00005269 0x00004719):  2021-03-09 08:56:50
    32-bit CRC value:                               0x00000000
    compressed size:                                0 bytes
    uncompressed size:                              0 bytes
  note: "real" crc and sizes are in the extended local header
    length of filename:                             8 characters
    length of extra field:                          0 bytes
  caution: value of lrec.csize (compressed size) changed from 0 to 17704
Current Location part 1 offset 30
    filename:json.txt
Current Location part 1 offset 38
    testing: json.txt                 OK
Current Location part 1 offset 17742
Zip64 extended local dir entry PK0708 (4+20): #1
---------------------------------------------
    32-bit CRC value:                               0x00000000
    compressed size:                                17704 bytes
    uncompressed size:                              29091 bytes
gildas-lormeau commented 3 years ago

The extra field is present in the central directory of the zip file. The specification does not require it to be present in the local header.

JCarlesVilaseca commented 3 years ago

Ok.

Anyway,

WinZip 9 (obsolete) warns with bad header about uncompressed size = 0

compressed size:                                0 bytes
uncompressed size:                              0 bytes

Zip4jUtil (current version) can't open the file: java.lang.RuntimeException: AesExtraDataRecord not present in local header for aes encrypted data at net.lingala.zip4j.util.Zip4jUtil.getCompressionMethod(Zip4jUtil.java:112)

    const blobWriter = new BlobWriter('application/zip');

    const writer = new ZipWriter(blobWriter, {
      password: 'password',
      encryptionStrength: 3,
      useWebWorkers: false,
    });

    await writer.add('hello.txt', new TextReader('Hello world'));

    await writer.close();
gildas-lormeau commented 3 years ago

It's a bug in Zip4jUtil. It should be able to rely on the extra field data located in the central directory. 7zip does not display any warning or error for example.

The values of the sizes are correct, the real values are stored in the "data descriptor record". I guess setting the option dataDescriptor to false should fix the issue.

gildas-lormeau commented 3 years ago

It's fixed. In the version 2.2.22, the AES and the custom extra field data is written in the local header.

gildas-lormeau commented 3 years ago

@JCarlesVilaseca Could you confirm the encrypted zip files produced with zip.js can now be read with Zip4jUtil?

JCarlesVilaseca commented 3 years ago

It works like a charm! Thank you so much!

gildas-lormeau commented 3 years ago

Great! Thank you for the feedback