| 1 | # Password-protected sections |
| 2 | |
| 3 | OneNote 2010 (14.0.4763.1000, Windows 7 lab) setting, changing and removing a section's |
| 4 | password, and Snowbound doing the same to a notebook that a fresh OneNote then cold-opens. |
| 5 | Passwords are fictitious and public ([manifest.json](manifest.json), |
| 6 | `candidate/passwords.json`). |
| 7 | |
| 8 | ## What OneNote does |
| 9 | |
| 10 | - **Set, change, remove.** Each writes the section anew: OneNote deletes the file and |
| 11 | creates one at the same path (a new NTFS file index, its creation time tunnelled), which |
| 12 | grows through some 30 transactions. Every identity is new: the header's file GUID, the root |
| 13 | object space, each page space (one fresh GUID for all of them, each its own `n`), and each payload's |
| 14 | file-data GUID. Each space keeps its labelled revisions, each a checkpoint: the current one |
| 15 | under roles 1 and 4, the version history under its context. The TOC gains an entry for |
| 16 | the new identity and keeps the old one (`native/*.one` from `source/synthetic.one`). |
| 17 | - **The crypto.** Office Agile encryption (MS-OFFCRYPTO 2.3.4.10) inside the |
| 18 | `ObjectDataEncryptionKeyV2FNDX` container (MS-ONESTORE 2.5.19): the words |
| 19 | `3, length, 16, length − 16`, version `4.4` with flags `0x40`, then UTF-8 XML with a CRLF |
| 20 | after the declaration and no data-integrity element. Key data and key encryptor are both |
| 21 | AES-128, CBC, SHA-1, 16-byte salts; `spinCount` 100000. H0 = SHA-1(salt ‖ UTF-16LE |
| 22 | password), Hn = SHA-1(LE32(n) ‖ Hn−1); each block key is SHA-1(H ‖ label)[..16] with the |
| 23 | password salt as IV. The verifier hash is padded with zeros to 32 bytes. A change of |
| 24 | password draws a new 16-byte content key. Property objects are their reference streams, a |
| 25 | length, a random IV and CBC of `u16 padding ‖ bytes ‖ random padding`; payloads are CBC, |
| 26 | IV = SHA-1(key-data salt ‖ LE32(0))[..16], of `u64 length ‖ bytes ‖ random padding`. |
| 27 | Read-only declarations hash the clear bytes zero-padded to 8. Every revision OneNote |
| 28 | writes anew names the key; its later dependent revisions do not. |
| 29 | - **Locking.** Locked, the section shows "This section is password protected. Click here or |
| 30 | press ENTER to unlock this section." with no page list; the Protected Section dialog says |
| 31 | "Password is incorrect." Options › Advanced › Passwords: lock after not being worked in for |
| 32 | 1, 5, 10 (default), 15 or 30 minutes, 1, 2, 4, 8 or 12 hours or 1 day (registry |
| 33 | `Options\Save\PasswordTimeout`, minutes; it takes effect after a restart); lock on |
| 34 | navigating away (off); let add-ins reach unlocked sections (on). With a minute set, a |
| 35 | section idle on screen locked between 72 and 132 seconds. Ctrl+Alt+L and Lock All lock |
| 36 | every section. Locking and unlocking write nothing. |
| 37 | - **Search and Tags Summary** leave locked sections out without saying so, and take them in |
| 38 | once unlocked. |
| 39 | - **Other writers.** With the section locked, OneNote wrote nothing while another writer |
| 40 | appended a revision, and showed it once unlocked; unlocked, it showed the next one live. |
| 41 | When the other writer gave the section a new password (a new file, as above), OneNote |
| 42 | showed it locked again, refused the old password and took the new one |
| 43 | (`native/observed/`). Observed on a local folder with one OneNote; two OneNotes on a share |
| 44 | were not tried. |
| 45 | |
| 46 | `native/snowbound-changed-then-onenote-edit.one` is a section Snowbound protected, edited and |
| 47 | gave another password, after OneNote unlocked it and typed into it. |
| 48 | |
| 49 | ## Snowbound |
| 50 | |
| 51 | `candidate/notebook` comes from `a_notebook_protected_through_its_sessions` |
| 52 | (`crates/notebook/tests/protected.rs`, `ONESTORE_PROTECTED_EXPORT`): OneNote's pages imported |
| 53 | into five sections, each given a password through `Notebook::set_password`; `Edited` edited |
| 54 | through its session three times, `Changed` given another password and edited, `Removed` |
| 55 | unprotected, `Conflicted` edited offline by two replicas into conflict pages. |
| 56 | `tools/native_protected.py` cold-opened it in a fresh clone, unlocked each section in OneNote's |
| 57 | dialog, typed into `Edited` through COM and read every page (`cold/`, with the notebook |
| 58 | OneNote left). `tools/test_protected_sections.py` checks both directions without a VM. |