Commit e5a8581
feat(security): store the device identity key in the Keychain, not a plaintext plist
The identity feature (last wave) generated a persistent Ed25519 signing key but kept it
in UserDefaults — a base64 plist on disk that any local read can lift, letting an
attacker impersonate the device forever. Move it to the Keychain (kSecClassGenericPassword,
AccessibleAfterFirstUnlock). deviceIdentity() now: (1) loads from the Keychain; (2)
one-time MIGRATES a legacy UserDefaults key into the Keychain and scrubs the plist copy,
so existing installs keep their identity and every peer's TOFU pin stays valid; (3) first
run generates + stores. If the Keychain is unavailable (an unsigned build), it falls back
to UserDefaults so the app still runs. Both platforms.
Verified. A standalone harness over the real MeshCrypto (both platforms): first run stores
in the Keychain and NOT the plist; the identity persists across calls; raw save/load
round-trips; and migration returns the SAME identity while moving it to the Keychain and
removing the plist copy — ALL PASS (Keychain confirmed working headless first). Live on
the SIGNED Mac app: a loopback call establishes, the safety number is 16408198304 — the
SAME value as before the migration (identity preserved, pins intact) — and
`defaults read com.trinet.monitor trinetIdentityKeyV1` is now empty (plaintext scrubbed).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>1 parent e930d55 commit e5a8581
2 files changed
Lines changed: 67 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
| |||
1638 | 1639 | | |
1639 | 1640 | | |
1640 | 1641 | | |
| 1642 | + | |
| 1643 | + | |
| 1644 | + | |
| 1645 | + | |
| 1646 | + | |
| 1647 | + | |
| 1648 | + | |
| 1649 | + | |
| 1650 | + | |
| 1651 | + | |
| 1652 | + | |
| 1653 | + | |
| 1654 | + | |
| 1655 | + | |
| 1656 | + | |
| 1657 | + | |
| 1658 | + | |
| 1659 | + | |
| 1660 | + | |
| 1661 | + | |
| 1662 | + | |
1641 | 1663 | | |
1642 | | - | |
1643 | | - | |
1644 | | - | |
| 1664 | + | |
| 1665 | + | |
| 1666 | + | |
| 1667 | + | |
| 1668 | + | |
| 1669 | + | |
| 1670 | + | |
1645 | 1671 | | |
1646 | | - | |
| 1672 | + | |
| 1673 | + | |
| 1674 | + | |
1647 | 1675 | | |
1648 | 1676 | | |
1649 | 1677 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
| |||
73 | 74 | | |
74 | 75 | | |
75 | 76 | | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
76 | 101 | | |
77 | | - | |
78 | | - | |
79 | | - | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
80 | 109 | | |
81 | | - | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
82 | 113 | | |
83 | 114 | | |
84 | 115 | | |
| |||
0 commit comments