Skip to content
Mostafa13447Public

Latest commit

 

History

46 Commits

Folders and files

Repository files navigation

JianMi

Release Platform Swift Rust Tests License

English · 简体中文

Your passwords never leave your hands — not ours, not anyone's.

Install · How it feels · Security · Self-hosting · FAQ


Why JianMi?

Every password manager asks you to trust someone. JianMi asks you to trust math and your own hardware — nothing else.

JianMi 1Password Bitwarden KeePassXC
Your vault lives on 🏠 your Mac / your server their cloud their cloud¹ a local file
macOS client ⚡️ native Swift Electron Electron Qt
Idle memory footprint ~30 MB ~300 MB ~250 MB ~90 MB
Per-entry "never sync" ✅ enforced in code ❌ ❌ n/a (no sync)
Capture-a-login hotkey ✅ < 5 seconds partial ❌ ❌
Entry-level sync merge ✅ ✅ ✅ ❌ (whole-file)
Price free · MIT subscription freemium free

¹ Bitwarden can be self-hosted via Vaultwarden, but the desktop client remains Electron.

✨ How it feels

Signing up somewhere? Press ⌥⌘N anywhere. A Spotlight-style panel appears with the site name and URL already filled in (reported live by the browser extension — zero macOS permissions, zero prompts). Type a username, roll a strong password with 🎲, hit ↩. Saved. Under 5 seconds.

Logging in? Press ⌥⌘P, type three letters:

Key Action
↩ copy password (clipboard self-destructs in 30 s)
⌥↩ copy username
⌘↩ open the site & copy password
⌃↩ auto-type straight into the focused field

In the browser? Click the extension icon — matching logins for the current site appear with Fill, Copy password and 2FA buttons. Works with React/Vue forms.

Everything else lives in a clean three-pane main window: colored type badges, Markdown notes with live rendering, TOTP with a countdown ring, custom fields, password history, pinnable always-on-top mini windows, and a menu-bar item that shows lock state at a glance.

📦 Install

1 · The app

Download JianMi-x.y.z.dmg from Releases → drag JianMi into Applications.

First launch: right-click → Open (builds are ad-hoc signed — no Apple Developer account, by design). Or: xattr -cr /Applications/JianMi.app

Prefer to build from source? (recommended for maximum trust)
brew install xcodegen
git clone https://mostafa13447.github.io && cd jianmi/apps/macos
xcodegen generate
xcodebuild -scheme JianMi -configuration Release build

2 · The browser extension

Open the app → Settings → Browser Extension → Export extension pack, then:

Browser Steps
Chrome / Edge / Arc / Brave unzip → chrome://extensions → Developer mode → Load unpacked
Firefox about:debugging → This Firefox → Load Temporary Add-on

Paste the pairing token (same settings page) into the extension. That's it — the extension only ever talks to 127.0.0.1.

3 · Sync server (optional — the app is fully functional offline)

See Self-hosting below.

🔐 Security

The chain of custody, end to end:

flowchart LR
    MP["🔑 Master password"] -->|"Argon2id<br/>64 MB · t=3"| MK["MasterKey<br/><i>RAM only, memzero on lock</i>"]
    MK -->|unwraps| VK["VaultKey"]
    VK -->|"XChaCha20-Poly1305<br/>AAD = entry UUID"| CT["Per-entry ciphertext"]
    CT --> Disk[("💾 disk")] & Sync[("☁️ server")] & Web["🌐 web vault<br/><i>decrypts in-browser</i>"]
Loading
  • Zero-knowledge everywhere. The sync server stores uuid + version + ciphertext — nothing else. So does your disk: run strings on the SQLite file, you'll find no secrets (we have a test that does exactly that).
  • local_only is physical, not cosmetic. Wallet-seed-type entries are force-flagged and filtered out before the sync engine's network layer — the code path to the server does not exist for them.
  • No recovery backdoor. Forgot the master password? Your one-time recovery code is the only way back in. We consider this a feature.
  • Cross-language proof. Swift-encrypted fixtures are decrypted by the same libsodium.js the web vault uses, in an automated test — the crypto formats can't silently drift.
  • Auto-lock on screen lock / sleep / idle · concealed-type clipboard with 30 s auto-clear · Touch ID via Keychain · conflict copies instead of silent overwrites.
Threat model
Threat Defense
Server breach ciphertext only; keys never leave your devices
Network sniffing payloads are encrypted before transport
Sync token leak token yields ciphertext only; rotate anytime
Stolen Mac (locked) field-level encryption, Argon2id-gated
Walk-away Mac auto-lock + memzero
Clipboard managers org.nspasteboard.ConcealedType + timed clear
Malicious local process bridge requires pairing token; localhost-bound
Not defended: kernel-level malware, physical coercion no software can

🏗️ Architecture

flowchart LR
    subgraph mac["🖥 Your Mac"]
        direction TB
        APP["<b>JianMi.app</b><br/>SwiftUI · SQLite + FTS5<br/>libsodium crypto core"]
        EXT["<b>Browser extension</b><br/>Chrome · Edge · Arc · Brave · Firefox"]
        EXT <-->|"127.0.0.1:48787<br/>pairing token"| APP
    end
    subgraph server["☁️ Your server (optional)"]
        direction TB
        SRV["<b>jianmi-server</b><br/>Rust · axum · single binary<br/>~10 MB RAM"]
        WEB["<b>Web vault</b><br/>static · in-browser decryption"]
        SRV --- WEB
    end
    APP <-->|"incremental sync<br/><i>ciphertext only</i>"| SRV
Loading
Component Stack Why
apps/macos Swift 6 · SwiftUI/AppKit · GRDB · swift-sodium non-activating panels, Touch ID, <100 ms hotkey wake — only native can
extension Manifest V3, vanilla JS one codebase, two builds (Chromium / Firefox)
server Rust · axum · rusqlite zero-knowledge makes the server trivially small: ~400 lines
web vanilla JS + libsodium.js no build chain, no framework, minimal attack surface

☁️ Self-hosting

cd server && cargo build --release
./target/release/jianmi-server --addr 0.0.0.0:8787 --data ./data

First run prints an access token → paste into App → Settings → Sync. The same address in any browser is your web vault.

One-command Linux deploy (static musl binary, hardened systemd unit):

./scripts/deploy_server.sh user@your-server

Even over plain HTTP your entries are ciphertext on the wire — but a reverse proxy with TLS (Caddy/nginx) is still a good idea.

🛠 Development

cd apps/macos && xcodebuild -scheme JianMi test   # 17 tests: crypto vectors, vault lifecycle,
                                                  # disk-plaintext-leak check, TCP bridge loopback
node scripts/verify_web_crypto.mjs                # Swift → JS crypto compatibility
cd server && cargo build --release                # sync server
./scripts/build_dmg.sh                            # DMG + extension zips → dist/

Design doc (zh): docs/DESIGN.md

🗺 Roadmap

  • Core vault · quick capture / search · browser extension · self-hosted sync · web vault · TOTP · auto-type
  • Encrypted attachments
  • Security audit (weak / reused password report)
  • Import / export (CSV, 1Password, Bitwarden)
  • Safari Web Extension
  • Signed Firefox add-on (AMO unlisted)

❓ FAQ

"JianMi can't be opened because it is from an unidentified developer"

Right-click the app → Open → Open. Once. Or xattr -cr /Applications/JianMi.app. This project intentionally ships without an Apple Developer subscription; build from source if you want a chain of trust you fully control.

App hangs forever on first launch (spinner / "not responding")

If you run a TUN-mode proxy (Surge, Clash, etc.), Gatekeeper's one-time online notarization lookup may be black-holed, freezing the app inside dyld. Fix: pause the proxy for one launch, or build & install from source with ./scripts/install_local.sh (registers a local execution-policy exemption — no network check at all). This is a one-time assessment; later launches are instant.

What happens if I forget my master password?

Use the 24-group recovery code shown (once!) at vault creation. There is no other way — no email reset, no support backdoor. Print it, put it somewhere safe.

Is syncing over plain HTTP actually safe?

Every payload is XChaCha20-Poly1305 ciphertext before it touches the network, and the token only gates access to ciphertext. TLS adds metadata privacy and is recommended, not required.

Why is the Firefox extension "temporary"?

Firefox release builds require extensions signed by Mozilla. Load it via about:debugging (resets on restart), or use Firefox Developer Edition with xpinstall.signatures.required = false. AMO-signed builds are on the roadmap.


MIT © JianMi contributors — built for people who read the crypto code before trusting it.

Releases

Packages

Contributors

Languages