WordPerfect 5 documents start with a 16-byte header whose bytes 1 to 3 are
WPC. It says where the document text starts, what kind of file it is and
which version wrote it. Corel’s own format documentation is not freely published; this
page follows libwpd, the open-source WordPerfect reader used by LibreOffice, and says
where something is not known.
The WPC header
Numbers are little-endian, except where the table says otherwise.
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 1 | – | 0xFF. |
1 | 3 | Signature | WPC (57 50 43). A reader checks these three bytes. |
4 | 4 | Document pointer | Offset of the start of the document area (the text and codes), after the prefix packets. |
8 | 1 | Product type | The program family that wrote the file: 1 for WordPerfect. |
9 | 1 | File type | 0x0A WordPerfect document. Other values are other WordPerfect Corporation files (templates, macros, dictionaries and so on), which libwpd does not read. |
10 | 1 | Major version | 0 for every 5.x file. |
11 | 1 | Minor version | 0 or 1, see versions. |
12 | 2 | Encryption | 0 when the file is not encrypted; otherwise a checksum of the password (see encryption). In 5.x files this field is stored high byte first. |
14 | 2 | Reserved | Reserved in 5.x files. |
16 | … | Prefix | The packet index, a chain of index blocks that lists the font lists and graphics. |
Versions
| File type | Major | Minor | Format |
|---|---|---|---|
0x0A | 0 | 0 | WordPerfect 5.0 for DOS. |
0x0A | 0 | 1 | WordPerfect 5.1 for DOS, 5.1 and 5.2 for Windows. |
The minor version mainly changes which packets the prefix has: 5.0 lists the fonts used in packet type 2, 5.1 in packet type 15.
Encryption
WordPerfect 5 protects a document by scrambling its bytes with the password; this is not secure and is easily reversed. No description of WordPerfect’s encryption was ever made available by WordPerfect or its later owners (WordPerfect for DOS Updated); libwpd’s method was worked out independently. It handles a 5.x file as follows:
- The password is turned to upper case (letters a to z only).
- The checksum is built over the password’s characters: start at 0; for each character, rotate the 16-bit value right by one bit and XOR it with the character shifted left eight bits. A file is protected when its stored checksum is not 0, and the password is right when the checksums match.
- The first 16 bytes are not encrypted, so the whole header stays readable.
- The byte at position
iafter those 16 is XORed with the password characteri mod lengthand with the mask(length + 1 + i) mod 256.