Export
What is in the file.
A backup you cannot read without the vendor's app is not really yours. This is the whole format, including how to open an encrypted export with ten lines of Python.
Two kinds of file
An unencrypted export is an Apple property list. Its top level has three
lists: Days, Cycles and Partners. Dates are stored as
midnight UTC of the calendar day.
An encrypted export is a binary property list that wraps exactly that file.
Its top level has Format = "iWoman.EncryptedBackup" and these fields:
| Field | Value |
|---|---|
Version | 1 |
KDF | PBKDF2-HMAC-SHA256 |
Iterations | 300,000 for new files |
Salt | 16 random bytes |
Cipher | AES-GCM-256 |
SealedBox | 12-byte nonce, ciphertext, 16-byte tag |
The key is derived from your password (Unicode-normalised to NFC) and the salt. The password is never stored, not in the file and not anywhere else, which is why nobody can recover it for you. A wrong password and a modified file fail the same authentication check.
Opening an encrypted export without iWoman
With Python 3 and the cryptography package:
import plistlib, unicodedata
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
env = plistlib.load(open("iWoman.backup", "rb"))
password = unicodedata.normalize("NFC", input("Password: ")).encode()
key = PBKDF2HMAC(hashes.SHA256(), 32, env["Salt"], env["Iterations"]).derive(password)
box = env["SealedBox"]
backup = plistlib.loads(AESGCM(key).decrypt(box[:12], box[12:], None))
print(len(backup["Days"]), "days,", len(backup["Cycles"]), "cycles")
Why the cryptography is Apple's
Encryption uses the operating system's own CryptoKit (AES-GCM) and CommonCrypto (PBKDF2). iWoman bundles no cryptography library of its own, and the file never leaves your device unless you send it somewhere.
Back to Export your data.