Apple has not published the Pages format. This page follows Sean O’Brien’s iWorkFileFormat project, which describes the iWork ’13 format used by Pages 5 and later, and its iWorkFileInspector source code. It covers the files of a document; the objects inside them are on the IWA archives page. Pages ’09 and earlier used an XML format that is not described here.
Bundle and single file
A Pages document is either a bundle, a macOS package folder named
….pages, or a single file, a
ZIP archive of the same files. The iWorkFileFormat
description is of the bundle, in which the objects are kept in a file
Index.zip. In the single-file form, which is how documents usually travel
today, the ZIP holds the Index/ folder of .iwa files
directly, so the overview’s “Index folder” is right for single files and
Index.zip for bundles.
Report.pages/
Data/
image-1234.jpg …
Index.zip (in a bundle; Index/… entries in a single-file document)
Metadata/
BuildVersionHistory.plist
DocumentIdentifier
Properties.plist
preview-micro.jpg
preview-web.jpg
preview.jpg
Files
| Path | Contents |
|---|---|
Index.zip or Index/ | The document’s objects, grouped into components, one .iwa file per component: Document.iwa, DocumentStylesheet.iwa, AnnotationAuthorStorage.iwa, CalculationEngine.iwa and others. |
Data/ | Pictures, movies and other media, as ordinary files referred to from the objects. |
Metadata/Properties.plist | Document properties, as a property list; iWorkFileInspector reads its documentUUID and versionUUID strings. |
.iwpv2, .iwph | Only in a password-protected document: the password verifier and the password hint (see below). |
Metadata/BuildVersionHistory.plist | The builds of Pages that have saved the document. |
Metadata/DocumentIdentifier | A unique identifier of the document. |
preview.jpg, preview-web.jpg, preview-micro.jpg | Preview images of the first page, in three sizes (JPEG). |
Index.zip
The ZIP writer iWork uses for Index.zip is minimal: it stores files
without compression (the .iwa files are already compressed) and does not
support Zip64 or other extensions. Unpacking Index.zip and packing it
again with an ordinary ZIP tool can make a document that Pages refuses to open, so
writers should store entries uncompressed.
Password encryption
When a document has a password, nearly every file in it is encrypted with AES-128 in
CBC mode with PKCS#7 padding. The bundle then also holds a password verifier, a
104-byte file named .iwpv2 at the top of the bundle, and may hold the
password hint as UTF-8 text in a file named .iwph (the names are those
iWorkFileInspector’s IWBundle.m reads):
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 2 | Version | 2. |
2 | 2 | Format | 1. |
4 | 4 | Iterations | PBKDF2 iteration count. |
8 | 16 | Salt | PBKDF2 salt. |
24 | 16 | IV | Initialisation vector for checking the key. |
40 | 64 | Check data | Encrypted check block. |
Numbers are little-endian; iWorkFileInspector refuses any verifier whose version is not 2 or whose format is not 1, and any file that is not exactly 104 bytes. The key is 16 bytes of PBKDF2 with HMAC-SHA-1 over the password’s UTF-8 bytes, with this salt and iteration count. To check it, decrypt the 64 check bytes with AES-128-CBC (no padding) and the verifier’s IV: the SHA-256 of the first 32 decrypted bytes must equal the last 32.
Each encrypted file is laid out as a 16-byte IV, the AES-128-CBC ciphertext, and 20
more bytes at the end, which the inspector’s source calls “garbage” and skips; their
purpose is not explained in any public source. The inspector decrypts each .iwa entry it
reads from Index.zip this way before the Snappy step. After
decryption the first 16 bytes of plain text are thrown away; the rest is the original
file. iWorkFileFormat calls its description of this “forthcoming”, so the details come
from its inspector’s source code.