Skip to content

Latest commit

 

History

History
340 lines (247 loc) · 8.56 KB

File metadata and controls

340 lines (247 loc) · 8.56 KB

ALZ Archive Format Specification

License: CC0 1.0.

All multi-byte integers are little-endian unless stated otherwise.


Table of Contents

  1. Archive Layout
  2. Signatures
  3. ALZ File Header
  4. Local File Header
  5. Compression Methods
  6. Encryption
  7. DOS Date/Time Format
  8. Comment Section
  9. File Tail
  10. Central Directory Structure
  11. End of Central Directory
  12. Multi-Volume Archives
  13. CRC32
  14. Filename Encoding

1. Archive Layout

An ALZ archive consists of a sequence of tagged records identified by 4-byte signatures:

[ALZ File Header]         8 bytes
[Local File Header 0]     variable
  [Compressed data]
[Local File Header 1 ...]
[Comment Section]         optional
[Central Directory]       optional, not used for extraction
[End of Central Directory]

The archive is parsed sequentially. The last 16 bytes of the file contain a tail structure (section 9) that is read first to determine the comment section size.

2. Signatures

Signature (LE) Description
0x015a4c41 ALZ file header
0x015a4c42 Local file header
0x015a4c43 Central directory structure
0x025a4c43 End of central directory
0x015a4c45 Comment section
0x035a4c43 Split marker

3. ALZ File Header

Offset Size Description
+0 4 Signature 0x015a4c41
+4 2 Version
+6 2 ID

4. Local File Header

4.1 Fixed Head (9 bytes)

Offset Size Field Description
+0 2 fileNameLength Length of filename in bytes
+2 1 fileAttribute See 4.2
+3 4 fileTimeDate DOS date/time, see 7
+7 1 fileDescriptor See 4.3
+8 1 unknown

4.2 File Attribute

Bit Mask Meaning
0 0x01 Read-only
1 0x02 Hidden
2 0x04 System
4 0x10 Directory
5 0x20 Archive

This byte is the low 8 bits of the Windows FILE_ATTRIBUTE_* value, stored unchanged.

4.3 File Descriptor

Bits Mask Meaning
0 0x01 Encrypted
3 0x08 Data descriptor present
4-7 0xF0 Size field byte width

The high nibble (fileDescriptor >> 4) gives the byte width N of the compressed/uncompressed size fields:

Value N
0x00 0 (no variable part; directory entry)
0x10 1
0x20 2
0x40 4
0x80 8

Only these values are valid. Any other value (e.g., 0x30, 0x50) is an error.

4.4 Variable Part (present when N > 0)

Offset Size Field Description
+0 1 compressionMethod See 5
+1 1 unknown
+2 4 fileCRC CRC32 of uncompressed data
+6 N compressedSize LE integer, zero-padded to 64-bit
+6+N N uncompressedSize LE integer, zero-padded to 64-bit

4.5 Filename and Data

Size Field
fileNameLength Filename (CP949 or UTF-8)
12 (if encrypted) Encryption header, see 6
compressedSize File data

5. Compression Methods

Value Method
0 Store (uncompressed)
1 ALZ-modified bzip2, see 5.1
2 Raw DEFLATE (RFC 1951, no wrapper)

Values 3+ are undefined. Unknown methods are a fatal error.

5.1 ALZ-Modified bzip2

Standard bzip2 with the following changes:

Standard bzip2 ALZ
Stream header BZh[1-9] (4 bytes) Absent
Block size From header Hardcoded 9 (900K)
Block magic 0x314159265359 (6 bytes) DLZ\x01 (4 bytes)
End magic 0x177245385090 (6 bytes) DLZ\x02 (4 bytes)
Block CRC 4 bytes Absent
Randomization bit 1 bit Absent
Combined CRC 4 bytes at end Absent
origPtr 24-bit big-endian Unchanged
Huffman/MTF/BWT/RLE Standard Unchanged

Block parsing:

Read 4 bytes: expect 'D' 'L' 'Z' [type]
  type == 0x01: data block
    Read origPtr (3 bytes, big-endian)
    Decode standard bzip2 block data (Huffman, MTF, BWT, RLE)
  type == 0x02: end of stream

6. Encryption

PKware ZIP traditional encryption (identical to ZIP 2.0).

6.1 Key State

Three 32-bit keys, initialized:

key[0] = 0x12345678
key[1] = 0x23456789
key[2] = 0x34567890

Each password byte is processed through UpdateKeys (6.2).

6.2 UpdateKeys(c)

key[0] = CRC32_TABLE[(key[0] ^ c) & 0xFF] ^ (key[0] >> 8)
key[1] = (key[1] + (key[0] & 0xFF)) * 134775813 + 1
key[2] = CRC32_TABLE[(key[2] ^ (key[1] >> 24)) & 0xFF] ^ (key[2] >> 8)

The constant 134775813 is 0x08088405 in hexadecimal. CRC32 polynomial: 0xEDB88320.

6.3 DecryptByte()

temp = (key[2] | 2) as u16
return (temp * (temp ^ 1)) >> 8

6.4 Decryption

For each ciphertext byte:

plain = cipher ^ DecryptByte()
UpdateKeys(plain)

6.5 Password Validation

The 12-byte encryption header (after filename) is decrypted. The last decrypted byte must equal:

  • (fileCRC >> 24) & 0xFF normally
  • (fileTimeDate >> 8) & 0xFF if data descriptor flag (bit 3) is set

On match, re-initialize keys with the password and re-process the 12-byte header to establish the correct key state for data decryption.

7. DOS Date/Time Format

Bits  0-4:  seconds / 2
Bits  5-10: minutes
Bits 11-15: hours
Bits 16-20: day
Bits 21-24: month
Bits 25-31: year - 1980

8. Comment Section

Signature: 0x015a4c45

The comment section total size (including the 4-byte signature) is stored in endInfos[1] of the file tail (section 9). After the signature, the remaining size is endInfos[1] - 4 bytes.

The section contains a sequence of comment entries:

Offset Size Field Description
+0 4 fileIndex File index (0xFFFFFFFF = archive-level comment)
+4 2 commentSize Comment data size
+6 N comment Comment text (local codepage encoding)

Entries repeat until the section size is consumed. Each entry is 6 + commentSize bytes.

9. File Tail

The last 16 bytes of an ALZ file contain four UInt32 values:

Offset Size Field Description
+0 4 endInfos[0] Unknown
+4 4 endInfos[1] Comment section total size (including signature)
+8 4 endInfos[2] Unknown
+12 4 endInfos[3] Unknown

Read these 16 bytes first (seek to EOF-16), then seek back to the beginning to parse sequentially. If endInfos[1] <= 4, there is no comment data.

10. Central Directory Structure

Offset Size Description
+0 4 Signature 0x015a4c43
+4 4 Unknown
+8 4 Unknown
+12 4 Unknown

Not used for extraction. The archive is parsed sequentially.

11. End of Central Directory

Offset Size Description
+0 4 Signature 0x025a4c43

No additional fields.

12. Multi-Volume Archives

12.1 Volume Naming

Volume Extension
0 .alz
1 .a00
2 .a01
...
100 .a99
101 .b00
...

For volume index i > 0: letter = 'a' + (i-1)/100, number = (i-1) % 100, extension = {letter}{number:02}. Maximum 1000 volumes.

12.2 Volume Layout

First volume (.alz):

[data...]
[16-byte tail]

Middle volumes:

[8-byte header]
[data...]
[16-byte tail]

Last volume:

[8-byte header]  (unless it is also the first)
[data...]

The last volume has no 16-byte tail. For a single-volume archive (first = last), there is no header and no tail subtracted from the data region.

The header and tail are opaque metadata skipped during I/O. Usable data per volume = file_size - header_size - tail_size.

12.3 Constants

Name Value
Header size 8 bytes
Tail size 16 bytes
Max volumes 1000

13. CRC32

Standard CRC32 with polynomial 0xEDB88320. Computed over decompressed (and decrypted) file data. Verified against fileCRC from the local file header.

14. Filename Encoding

Filenames are typically CP949 (a superset of EUC-KR). If the bytes are valid UTF-8, they should be interpreted as UTF-8. Otherwise, decode as CP949.

Path separators may be / or \; normalize to the platform convention.