| … | … | @@ -1,331 +1,257 @@ |
| 1 | 1 | # Hyperident |
| 2 | 2 | |
| 3 | | **Deterministic Identity Management for Hyperswarm Networks** |
| 3 | **Deterministic identity + signing + device-chain CLI for Hyperswarm applications** |
| 4 | 4 | |
| 5 | | Hyperident provides deterministic, cross-device identity management for Hyperswarm applications, enabling consistent network addresses through named profiles. |
| 5 | Standalone command-line tool that wraps `keet-identity-key` to give a |
| 6 | local identity vault (`~/.hyperident/`), named profiles that resolve |
| 7 | deterministically to Hyperswarm topics, file signing, and device |
| 8 | chain export/import + network mesh pairing. |
| 6 | 9 | |
| 7 | | ## 🚀 Quick Start |
| 10 | > **Naming caveat — read first.** This CLI is a different codebase |
| 11 | > from `packages/hyper-identity` (the shared library used by |
| 12 | > pear-git-v3, hypernote, pear-git, hyper-social-web). Both consume |
| 13 | > `keet-identity-key`; both manage device chains; that is the only |
| 14 | > overlap. If you are looking for the multi-app `IdentityRegistry` / |
| 15 | > `DeviceLinker` shared library, see `packages/hyper-identity`. If |
| 16 | > you want a one-shot identity + deterministic Hyperswarm topic CLI, |
| 17 | > you are in the right place. |
| 18 | |
| 19 | ## Quick start |
| 8 | 20 | |
| 9 | 21 | ```bash |
| 10 | | # Initialize your identity |
| 11 | | node index.js init |
| 22 | # Initialize identity (creates ~/.hyperident/) |
| 23 | bare index.js init |
| 12 | 24 | |
| 13 | | # Create a profile |
| 14 | | node index.js create-profile work "Work projects" |
| 25 | # Create a profile for deterministic addressing |
| 26 | bare index.js create-profile work "Work projects" |
| 15 | 27 | |
| 16 | | # Start SOCKS proxy with deterministic address |
| 17 | | node socks-server.js server --profile work |
| 28 | # Get the deterministic Hyperswarm topic for that profile |
| 29 | bare index.js address work |
| 18 | 30 | ``` |
| 19 | 31 | |
| 20 | | ## 📦 Installation |
| 32 | ## Installation |
| 33 | |
| 34 | ### Local development |
| 21 | 35 | |
| 22 | | ### Local Development |
| 23 | 36 | ```bash |
| 24 | 37 | git clone <repository-url> |
| 25 | 38 | cd hyperident |
| 26 | 39 | npm install |
| 27 | 40 | ``` |
| 28 | 41 | |
| 29 | | ### Global Installation (Optional) |
| 30 | | ```bash |
| 31 | | npm install -g . |
| 32 | | # Then use: hyperident init (instead of node index.js init) |
| 33 | | ``` |
| 42 | ### Bare runtime (recommended) |
| 34 | 43 | |
| 35 | | ### Bare Runtime (recommended) |
| 36 | 44 | ```bash |
| 45 | npm install -g bare-runtime |
| 37 | 46 | bare index.js init |
| 38 | 47 | bare index.js list-profiles |
| 39 | 48 | ``` |
| 40 | 49 | |
| 41 | | ### Pear Runtime (legacy) |
| 42 | | ```bash |
| 43 | | pear run pear://bdkaqufc8o6h75cbxrkzxjqadzqkyq11bws3iuxsb8kk5jjpuado |
| 44 | | ``` |
| 45 | | |
| 46 | | ## 🔧 Commands |
| 47 | | |
| 48 | | ### `node index.js init [--with-passphrase]` |
| 49 | | Initialize a new identity with optional passphrase protection. |
| 50 | | |
| 51 | | ```bash |
| 52 | | # Create unencrypted identity |
| 53 | | node index.js init |
| 54 | | |
| 55 | | # Create encrypted identity |
| 56 | | node index.js init --with-passphrase |
| 57 | | ``` |
| 58 | | |
| 59 | | ### `node index.js create-profile <name> [description]` |
| 60 | | Create a new profile for deterministic addressing. |
| 61 | | |
| 62 | | ```bash |
| 63 | | node index.js create-profile work "Work projects" |
| 64 | | node index.js create-profile personal |
| 65 | | ``` |
| 66 | | |
| 67 | | ### `node index.js list-profiles` |
| 68 | | List all created profiles. |
| 69 | | |
| 70 | | ```bash |
| 71 | | node index.js list-profiles |
| 72 | | ``` |
| 73 | | |
| 74 | | ### `node index.js delete-profile <name>` |
| 75 | | Delete an existing profile. |
| 76 | | |
| 77 | | ```bash |
| 78 | | node index.js delete-profile work |
| 79 | | ``` |
| 80 | | |
| 81 | | ### `node index.js address <profile> [--cached]` |
| 82 | | Get the deterministic address for a profile. |
| 83 | | |
| 84 | | ```bash |
| 85 | | node index.js address work |
| 86 | | node index.js address work --cached # Use cached address |
| 87 | | ``` |
| 88 | | |
| 89 | | ### `node index.js refresh-addresses` |
| 90 | | Refresh all cached addresses. |
| 50 | ### Pear app install (production) |
| 91 | 51 | |
| 92 | 52 | ```bash |
| 93 | | node index.js refresh-addresses |
| 53 | pgh app install pear://bdkaqufc8o6h75cbxrkzxjqadzqkyq11bws3iuxsb8kk5jjpuado --name hyperident |
| 54 | hyperident init |
| 94 | 55 | ``` |
| 95 | 56 | |
| 96 | | ### `node index.js export-addresses [file] [--enhanced]` |
| 97 | | Export addresses for external programs. |
| 57 | The `pear run pear://...` flow that older docs mention is being |
| 58 | removed from the Pear runtime. Use `pgh app install` instead. |
| 98 | 59 | |
| 99 | | ```bash |
| 100 | | # Basic export to console |
| 101 | | node index.js export-addresses |
| 102 | | |
| 103 | | # Export to file |
| 104 | | node index.js export-addresses addresses.json |
| 105 | | |
| 106 | | # Enhanced export with multiple formats |
| 107 | | node index.js export-addresses --enhanced |
| 108 | | node index.js export-addresses addresses-enhanced.json --enhanced |
| 109 | | ``` |
| 110 | | |
| 111 | | ### Data Signing Commands |
| 60 | ## Commands |
| 112 | 61 | |
| 113 | | ### `node index.js sign <file>` |
| 114 | | Sign a file with your device identity. |
| 62 | All commands accept the binary as either `bare index.js`, `node |
| 63 | index.js`, or — once installed via Pear — `hyperident`. Examples |
| 64 | below use `bare index.js`. |
| 115 | 65 | |
| 116 | | ```bash |
| 117 | | node index.js sign document.pdf |
| 118 | | # Creates document.pdf.sig |
| 119 | | ``` |
| 120 | | |
| 121 | | ### `node index.js verify <signature> <file>` |
| 122 | | Verify a signature against the original file. |
| 66 | ### Identity |
| 123 | 67 | |
| 124 | 68 | ```bash |
| 125 | | node index.js verify document.pdf.sig document.pdf |
| 69 | bare index.js init # plaintext mnemonic |
| 70 | bare index.js init --with-passphrase # encrypted at rest |
| 71 | bare index.js init --device-name "laptop" |
| 126 | 72 | ``` |
| 127 | 73 | |
| 128 | | ### `node index.js export-signing-config` |
| 129 | | Export signing configuration for applications. |
| 74 | ### Profiles |
| 130 | 75 | |
| 131 | 76 | ```bash |
| 132 | | node index.js export-signing-config |
| 77 | bare index.js create-profile <name> [description] |
| 78 | bare index.js list-profiles |
| 79 | bare index.js delete-profile <name> |
| 80 | bare index.js address <profile> [--cached] |
| 81 | bare index.js refresh-addresses |
| 82 | bare index.js export-addresses [file] [--enhanced] |
| 133 | 83 | ``` |
| 134 | 84 | |
| 135 | | ### Device Management Commands |
| 136 | | |
| 137 | | ### `node index.js device list` |
| 138 | | List device information. |
| 85 | `address <profile>` returns a 32-byte hex string that can be used |
| 86 | directly as a Hyperswarm topic. Two devices using the same profile |
| 87 | name resolve to the same topic. |
| 139 | 88 | |
| 140 | | ```bash |
| 141 | | node index.js device list |
| 142 | | ``` |
| 143 | | |
| 144 | | ### `node index.js device export [file]` |
| 145 | | Export device bundle for cross-device sync. |
| 89 | ### File signing |
| 146 | 90 | |
| 147 | 91 | ```bash |
| 148 | | node index.js device export |
| 149 | | node index.js device export device-bundle.json |
| 92 | bare index.js sign <file> # writes <file>.sig |
| 93 | bare index.js verify <signature> <file> |
| 94 | bare index.js export-signing-config # JSON for app integration |
| 150 | 95 | ``` |
| 151 | 96 | |
| 152 | | ### `node index.js device import <file> --device-name <name>` |
| 153 | | Import device bundle on a new device. |
| 154 | | |
| 155 | | ```bash |
| 156 | | node index.js device import device-bundle.json --device-name "laptop" |
| 157 | | ``` |
| 97 | ### Device chain — manual export/import |
| 158 | 98 | |
| 159 | | ### `node index.js device verify` |
| 160 | | Verify device chain integrity. |
| 99 | For copying an identity onto another device by transferring a bundle |
| 100 | file out-of-band (USB stick, encrypted email, etc). |
| 161 | 101 | |
| 162 | 102 | ```bash |
| 163 | | node index.js device verify |
| 103 | bare index.js device list |
| 104 | bare index.js device export [file] # default: device-bundle.json |
| 105 | bare index.js device import <file> --device-name <name> |
| 106 | bare index.js device verify |
| 164 | 107 | ``` |
| 165 | 108 | |
| 166 | | ### Debug Commands |
| 167 | | |
| 168 | | ### `node index.js debug inspect [--passphrase]` |
| 169 | | Inspect identity and system state. |
| 170 | | |
| 171 | | ```bash |
| 172 | | node index.js debug inspect |
| 173 | | node index.js debug inspect --passphrase # For encrypted identities |
| 174 | | ``` |
| 109 | ### Device chain — network pairing (identity mesh) |
| 175 | 110 | |
| 176 | | ### `node index.js debug health` |
| 177 | | Run comprehensive health check. |
| 111 | For linking devices over a Hyperswarm-discovered identity mesh. |
| 112 | The first device bootstraps; subsequent devices join via a shared |
| 113 | code. |
| 178 | 114 | |
| 179 | 115 | ```bash |
| 180 | | node index.js debug health |
| 116 | bare index.js device bootstrap # be the first node |
| 117 | bare index.js device create-network # spin up a mesh |
| 118 | bare index.js device share [--timeout <minutes>] |
| 119 | bare index.js device join <code> --device-name <name> |
| 120 | bare index.js device status |
| 121 | bare index.js device sync # pull peer profiles |
| 122 | bare index.js device mesh join |
| 123 | bare index.js device mesh leave |
| 124 | bare index.js device revoke <device-id> |
| 181 | 125 | ``` |
| 182 | 126 | |
| 183 | | ### `node index.js debug network` |
| 184 | | Run network diagnostics. |
| 127 | ### Debug |
| 185 | 128 | |
| 186 | 129 | ```bash |
| 187 | | node index.js debug network |
| 130 | bare index.js debug inspect [--passphrase] |
| 131 | bare index.js debug health |
| 132 | bare index.js debug network |
| 133 | bare index.js debug trust |
| 134 | bare index.js debug system |
| 188 | 135 | ``` |
| 189 | 136 | |
| 190 | | ### `node index.js debug trust` |
| 191 | | Verify trust relationships. |
| 137 | ## SOCKS proxy integration |
| 192 | 138 | |
| 193 | | ```bash |
| 194 | | node index.js debug trust |
| 195 | | ``` |
| 196 | | |
| 197 | | ### `node index.js debug system` |
| 198 | | Show system information. |
| 139 | Optional companion: a SOCKS proxy bound to a profile's deterministic |
| 140 | address. |
| 199 | 141 | |
| 200 | 142 | ```bash |
| 201 | | node index.js debug system |
| 143 | node socks-server.js server --profile work # bound to profile address |
| 144 | node socks-server.js server # random address |
| 145 | node socks-server.js server --profile work --port 8080 |
| 202 | 146 | ``` |
| 203 | 147 | |
| 204 | | ## 🌐 SOCKS Proxy Integration |
| 148 | ## Storage layout |
| 205 | 149 | |
| 206 | | ### Start with Profile (Deterministic) |
| 207 | | ```bash |
| 208 | | node socks-server.js server --profile work |
| 209 | 150 | ``` |
| 210 | | |
| 211 | | ### Start without Profile (Random) |
| 212 | | ```bash |
| 213 | | node socks-server.js server |
| 151 | ~/.hyperident/ |
| 152 | ├── identity private mnemonic (encrypted if --with-passphrase). 600. |
| 153 | ├── identity.pub public key, hex. 644. |
| 154 | ├── profiles.json profile name → metadata + cached address. 644. |
| 155 | └── device-chain keet-identity-key device proof chain. |
| 214 | 156 | ``` |
| 215 | 157 | |
| 216 | | ### Custom Port |
| 217 | | ```bash |
| 218 | | node socks-server.js server --profile work --port 8080 |
| 219 | | ``` |
| 158 | ## Cross-device sync |
| 220 | 159 | |
| 221 | | ## 🔐 Security Features |
| 160 | Two paths: |
| 222 | 161 | |
| 223 | | - **Secure File Permissions**: Identity files protected with 600 permissions |
| 224 | | - **Optional Encryption**: Passphrase-protected identities using SHA256 + XOR |
| 225 | | - **Cross-Platform**: Works on Linux, macOS, Windows, and mobile via Pear |
| 226 | | - **Deterministic**: Same profile generates identical addresses across devices |
| 162 | 1. **Manual bundle transfer** — `device export` produces a |
| 163 | self-contained JSON bundle. Move it to the second device via any |
| 164 | trusted channel, then `device import bundle.json --device-name |
| 165 | "phone"`. |
| 166 | 2. **Identity mesh over Hyperswarm** — bootstrap a mesh on device A, |
| 167 | `device share` to print a code, then on device B run `device join |
| 168 | <code> --device-name "phone"`. Subsequent profile changes |
| 169 | propagate via `device sync`. |
| 227 | 170 | |
| 228 | | ## 📁 File Structure |
| 171 | ## Architecture |
| 229 | 172 | |
| 230 | 173 | ``` |
| 231 | | ~/.hyperident/ |
| 232 | | ├── identity # Private identity (600 permissions) |
| 233 | | ├── identity.pub # Public key (644 permissions) |
| 234 | | └── profiles.json # Profile definitions (644 permissions) |
| 174 | index.js CLI dispatcher |
| 175 | lib/identity-manager.js IdentityManager (all static methods) |
| 176 | lib/crypto.js CryptoManager — passphrase encryption, |
| 177 | raw device-keypair generation, hashing |
| 178 | lib/file-ops.js FileManager — ~/.hyperident/* I/O with |
| 179 | proper file permissions |
| 180 | lib/validation.js CLI arg + profile-name validation |
| 181 | lib/device-linking-manager.js Network device pairing — share/join codes, |
| 182 | blind-pair flow over Hyperswarm |
| 183 | lib/device-mesh-manager.js Identity mesh discovery + cross-device |
| 184 | profile sync |
| 185 | lib/debug-manager.js Health / network / trust / system |
| 186 | diagnostics for `debug` subcommands |
| 187 | socks-server.js Optional SOCKS proxy |
| 235 | 188 | ``` |
| 236 | 189 | |
| 237 | | ## 🔄 Cross-Device Sync |
| 238 | | |
| 239 | | To use the same identity across devices: |
| 190 | `IdentityManager` exposes only static methods — |
| 191 | `generateIdentity`, `saveIdentity`, `loadIdentity`, |
| 192 | `createProfile`, `listProfiles`, `getProfileAddress`, `signData`, |
| 193 | `verifySignature`, `exportSigningConfig`, `identityExists`. There |
| 194 | is no `new IdentityManager()` instance form; older example code that |
| 195 | shows `await identity.init()` is wrong. |
| 240 | 196 | |
| 241 | | 1. **Backup**: Copy `~/.hyperident/` directory |
| 242 | | 2. **Restore**: Place files in `~/.hyperident/` on new device |
| 243 | | 3. **Verify**: Run `node index.js list-profiles` |
| 197 | ## Security |
| 244 | 198 | |
| 245 | | ## 🛠️ Development |
| 199 | - Identity files written with `600` permissions; public key with |
| 200 | `644`. |
| 201 | - Optional passphrase encryption (`--with-passphrase`) — passphrase |
| 202 | must be ≥8 chars; lost passphrase = lost identity. |
| 203 | - Device-chain proofs via `keet-identity-key.bootstrap()`; chain |
| 204 | validity checkable with `device verify`. |
| 205 | - Cross-platform: Linux, macOS, Windows; mobile via Pear. |
| 246 | 206 | |
| 247 | | ### Run Tests |
| 248 | | ```bash |
| 249 | | npm test |
| 250 | | ``` |
| 207 | ## Tests |
| 251 | 208 | |
| 252 | | ### Development Mode |
| 253 | 209 | ```bash |
| 254 | | npm run dev |
| 210 | npm test # brittle test/*.test.js |
| 211 | npm run dev # bare index.js |
| 212 | npm run socks # node socks-server.js |
| 255 | 213 | ``` |
| 256 | 214 | |
| 257 | | ### SOCKS Server |
| 258 | | ```bash |
| 259 | | npm run socks |
| 260 | | ``` |
| 215 | The root-level `test-keet-api*.js`, `demo.js`, `verify.js`, |
| 216 | `test-device-chain-workflow.js` and `tampered-file.txt` / |
| 217 | `test-file.txt*` fixtures are scratch scripts from the initial |
| 218 | build; they are **not** wired into `npm test` and may be out of date. |
| 261 | 219 | |
| 262 | | ## 📊 Performance |
| 220 | ## Performance |
| 263 | 221 | |
| 264 | | - **Startup Time**: <250ms without passphrase, <2s with passphrase |
| 265 | | - **Memory Usage**: Minimal footprint |
| 266 | | - **File I/O**: Atomic operations with proper error handling |
| 222 | - Startup: <250ms without passphrase, <2s with passphrase decryption. |
| 223 | - File I/O: atomic writes with proper error handling. |
| 224 | - Memory: minimal footprint (single CLI process, no background |
| 225 | daemon). |
| 267 | 226 | |
| 268 | | ## 🔍 Troubleshooting |
| 227 | ## Troubleshooting |
| 269 | 228 | |
| 270 | | ### Identity Not Found |
| 271 | | ```bash |
| 272 | | # Initialize first |
| 273 | | node index.js init |
| 274 | | ``` |
| 229 | **Identity not found.** Run `bare index.js init` first. |
| 275 | 230 | |
| 276 | | ### Profile Not Found |
| 277 | | ```bash |
| 278 | | # List available profiles |
| 279 | | node index.js list-profiles |
| 231 | **Profile not found.** Run `bare index.js list-profiles` to see what |
| 232 | exists, then `bare index.js create-profile <name>` if needed. |
| 280 | 233 | |
| 281 | | # Create the profile |
| 282 | | node index.js create-profile <name> |
| 283 | | ``` |
| 234 | **Permission errors.** Check directory permissions: |
| 284 | 235 | |
| 285 | | ### Permission Errors |
| 286 | 236 | ```bash |
| 287 | | # Check directory permissions |
| 288 | 237 | ls -la ~/.hyperident/ |
| 289 | | |
| 290 | | # Fix permissions if needed |
| 291 | 238 | chmod 700 ~/.hyperident/ |
| 292 | 239 | chmod 600 ~/.hyperident/identity |
| 293 | 240 | ``` |
| 294 | 241 | |
| 295 | | ## 🏗️ Architecture |
| 296 | | |
| 297 | | ### Core Components |
| 242 | **Encrypted identity won't unlock.** Run `bare index.js debug inspect |
| 243 | --passphrase` to confirm the passphrase is correct before moving on |
| 244 | to other diagnostics. |
| 298 | 245 | |
| 299 | | - **CryptoManager**: Handles encryption, key derivation, and hashing |
| 300 | | - **FileManager**: Manages secure file operations with proper permissions |
| 301 | | - **IdentityManager**: Coordinates identity and profile management |
| 302 | | - **SOCKS Integration**: Bridges Hyperident with hyperswarm-socks |
| 246 | ## Related |
| 303 | 247 | |
| 304 | | ### Key Features |
| 248 | - [`packages/hyper-identity`](../../packages/hyper-identity) — the |
| 249 | shared `IdentityRegistry` + `DeviceLinker` library used by |
| 250 | pear-git-v3, hypernote, pear-git. **Different codebase.** |
| 251 | - [keet-identity-key](https://github.com/holepunchto/keet-identity-key) — upstream identity key generation |
| 252 | - [hyperswarm](https://github.com/hyperswarm/hyperswarm) — P2P networking |
| 253 | - [Pear Runtime](https://pears.com) — cross-platform P2P runtime |
| 305 | 254 | |
| 306 | | - **Deterministic Addressing**: Same profile → same address across devices |
| 307 | | - **Profile Management**: Named profiles for different use cases |
| 308 | | - **Security First**: Proper file permissions and optional encryption |
| 309 | | - **Backward Compatible**: Works with existing hyperswarm-socks functionality |
| 310 | | |
| 311 | | ## 📄 License |
| 255 | ## License |
| 312 | 256 | |
| 313 | 257 | Apache-2.0 |
| 314 | | |
| 315 | | ## 🤝 Contributing |
| 316 | | |
| 317 | | 1. Fork the repository |
| 318 | | 2. Create a feature branch |
| 319 | | 3. Add tests for new functionality |
| 320 | | 4. Ensure all tests pass |
| 321 | | 5. Submit a pull request |
| 322 | | |
| 323 | | ## 🔗 Related Projects |
| 324 | | |
| 325 | | - [keet-identity-key](https://github.com/holepunchto/keet-identity-key) - Identity key generation |
| 326 | | - [hyperswarm](https://github.com/hyperswarm/hyperswarm) - P2P networking |
| 327 | | - [Pear Runtime](https://pears.com) - Cross-platform runtime |
| 328 | | |
| 329 | | --- |
| 330 | | |
| 331 | | **Made with ❤️ for the Hypercore ecosystem** |