{"id":51306365,"url":"https://github.com/viamus/locker-it","last_synced_at":"2026-07-01T00:02:10.169Z","repository":{"id":363160983,"uuid":"1261539012","full_name":"viamus/locker-it","owner":"viamus","description":"LockerIt is a Windows-first standalone encrypted vault for passwords, Recovery Kits, and future secure files.","archived":false,"fork":false,"pushed_at":"2026-06-07T18:09:45.000Z","size":143,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T18:27:11.159Z","etag":null,"topics":["aes-gcm","dotnet","dpapi","local-first","password-manager","recovery-kit","security","sqlite","windows","wpf"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/viamus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-06T20:34:09.000Z","updated_at":"2026-06-07T17:57:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/viamus/locker-it","commit_stats":null,"previous_names":["viamus/locker-it"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/viamus/locker-it","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viamus%2Flocker-it","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viamus%2Flocker-it/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viamus%2Flocker-it/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viamus%2Flocker-it/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/viamus","download_url":"https://codeload.github.com/viamus/locker-it/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viamus%2Flocker-it/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34987611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes-gcm","dotnet","dpapi","local-first","password-manager","recovery-kit","security","sqlite","windows","wpf"],"created_at":"2026-07-01T00:02:05.602Z","updated_at":"2026-07-01T00:02:10.159Z","avatar_url":"https://github.com/viamus.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LockerIt\n\n[![Build](https://github.com/viamus/locker-it/actions/workflows/build.yml/badge.svg)](https://github.com/viamus/locker-it/actions/workflows/build.yml)\n![Platform](https://img.shields.io/badge/platform-Windows%2011%2B-D97757)\n![.NET](https://img.shields.io/badge/.NET-10-512BD4)\n![License](https://img.shields.io/badge/license-MIT-65B891)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\".docs/assets/lockerit-lockup.png\" alt=\"LockerIt orange lockup\" width=\"260\" /\u003e\n\u003c/p\u003e\n\nLockerIt is a Windows-first, standalone encrypted vault for passwords and secure file attachments. It is intentionally local-first: no WebAPI, no cloud dependency, no background sync service, and no remote account model. The vault belongs to the Windows account that unlocks it.\n\nThe project targets Windows 11+ and is built with .NET 10, WPF, SQLite, Windows DPAPI, Windows Hello/PIN/biometric consent, TOTP AuthPolicy gates, and AES-256-GCM encrypted payloads.\n\n## Why LockerIt Exists\n\nImportant credentials and private documents often live as plain files, browser exports, notes, screenshots, or spreadsheets on a local disk. LockerIt exists to put a hardened local boundary around that material without forcing the user into a cloud password manager or a network service.\n\nThe first product target is a beautiful dark desktop vault that feels modern, direct, and calm. The first security target is more important: local secrets should be encrypted before they reach storage, tied to the current Windows account for daily unlock, and recoverable across devices only through an explicit Recovery Kit.\n\n## Product Principles\n\n- Standalone desktop application.\n- Dark-only interface.\n- No runtime network dependency.\n- No WebAPI.\n- No plaintext secrets in SQLite.\n- Windows account boundary for daily unlock.\n- Explicit cross-device recovery through a passphrase-protected Recovery Kit.\n- Local AuthPolicy for optional authenticator app verification.\n- Small dependency footprint and locked package restore.\n- UI that feels like a real product, not an admin sample app.\n\n## Current Capabilities\n\n| Area | Capability | Status |\n| --- | --- | --- |\n| Desktop shell | Dark WPF app that opens maximized with sidebar navigation, account menu, tray icon and modal editor | Implemented |\n| Authentication | Windows Hello/PIN/biometric prompt with current Windows password fallback | Implemented |\n| Password vault | Create, read, update, delete, search and categorize password entries | Implemented |\n| Encryption | AES-256-GCM encrypted JSON payloads before SQLite persistence | Implemented |\n| Local keyring | 256-bit vault master key protected with Windows DPAPI CurrentUser | Implemented |\n| Recovery | Export/import Recovery Kit, optional passphrase hint and re-protect local keyring | Implemented |\n| Legacy master password | Existing master-password keyrings can still unlock and are migrated back to Windows + AuthPolicy protection | Compatibility |\n| AuthPolicy 2FA | Encrypted vault policy with TOTP QR setup, inline six-digit login check and one-time recovery codes | Implemented |\n| Secure files | Encrypted file attachments with import/export/delete, search and category filter | Implemented |\n| Documentation | Repository README, `.docs/`, contribution guide and license | Implemented |\n| Session hardening | 15-minute inactivity auto-lock and Windows verification for sensitive actions | Implemented |\n| Storage settings | Configurable vault database path | Implemented |\n| Smoke tests | End-to-end core test for CRUD, encryption, recovery and keyring loss | Implemented |\n| CI | GitHub Actions build and smoke test workflow | Implemented |\n\n## System Overview\n\n```mermaid\nflowchart LR\n    User[\"Windows user\"] --\u003e App[\"LockerIt WPF app\"]\n    App --\u003e Auth[\"Windows account verification\"]\n    Auth --\u003e Hello[\"Windows Hello / PIN / biometric\"]\n    Auth --\u003e PasswordFallback[\"Current Windows password fallback\"]\n    App --\u003e Core[\"Lockerit.Core\"]\n    Core --\u003e Cipher[\"AES-256-GCM payload cipher\"]\n    Core --\u003e Store[\"SQLite vault database\"]\n    Core --\u003e Keyring[\"DPAPI CurrentUser keyring\"]\n    Core --\u003e LegacyMaster[\"Legacy master-password migration\"]\n    Core --\u003e AuthPolicy[\"Encrypted AuthPolicy\"]\n    AuthPolicy --\u003e Totp[\"TOTP and one-time recovery codes\"]\n    Core --\u003e Recovery[\"Recovery Kit service\"]\n    Core --\u003e Files[\"Encrypted file attachments\"]\n    Recovery --\u003e Kit[\"Passphrase-protected Recovery Kit file\"]\n```\n\nLockerIt separates daily unlock from cross-device recovery. Daily unlock uses the current Windows account to unseal a local keyring. Cross-device recovery uses a Recovery Kit that wraps the same vault master key with a user-provided recovery passphrase.\n\n## Tool Map\n\nThe word \"tool\" in this repository means a concrete capability that helps the user manage or protect vault data.\n\n```mermaid\nmindmap\n  root((LockerIt tools))\n    Vault\n      Password table\n      Category filter\n      Search\n      Modal editor\n      Copy username\n      Copy password\n      Password generator\n    Files\n      Import file\n      Export file\n      Delete file\n    Security\n      Windows Hello consent\n      Password fallback\n      DPAPI keyring\n      Legacy master-password migration\n      AuthPolicy\n      TOTP authenticator\n      Recovery codes\n      AES-GCM encryption\n      Clipboard auto-clear\n      Auto-lock\n      Sensitive action verification\n    Recovery\n      Export Recovery Kit\n      Import Recovery Kit\n      Refresh local keyring\n      Missing-keyring guard\n    Desktop\n      Dark shell\n      Sidebar settings\n      Documentation workspace\n      Account menu\n      Tray icon\n    Developer\n      Locked NuGet restore\n      Smoke tests\n      GitHub metadata\n      Documentation\n```\n\n## Runtime Architecture\n\n```mermaid\nflowchart TB\n    subgraph UI[\"Lockerit.App\"]\n        MainWindow[\"MainWindow.xaml\"]\n        Dialogs[\"Windows password and recovery dialogs\"]\n        Settings[\"Settings workspace\"]\n        Documentation[\"Documentation workspace\"]\n        Tray[\"Windows tray integration\"]\n    end\n\n    subgraph Core[\"Lockerit.Core\"]\n        Vault[\"LockeritVault facade\"]\n        Repository[\"VaultRepository\"]\n        Cipher[\"AesGcmVaultCipher\"]\n        KeyStore[\"WindowsProtectedKeyStore\"]\n        RecoveryService[\"RecoveryKitService\"]\n        AuthPolicy[\"AuthPolicy + TOTP\"]\n        FileAttachments[\"Vault file attachments\"]\n    end\n\n    subgraph Disk[\"Local disk\"]\n        Database[\"lockerit.db\"]\n        KeyFile[\"keyring.bin or *.keyring.bin\"]\n        RecoveryFile[\"*.lockerit-recovery.json\"]\n        ExportedFile[\"User-selected exported file\"]\n    end\n\n    MainWindow --\u003e Vault\n    Dialogs --\u003e Vault\n    Settings --\u003e Vault\n    Documentation --\u003e MainWindow\n    Tray --\u003e MainWindow\n    Vault --\u003e Repository\n    Vault --\u003e KeyStore\n    Vault --\u003e RecoveryService\n    Vault --\u003e AuthPolicy\n    Vault --\u003e FileAttachments\n    Repository --\u003e Cipher\n    Repository --\u003e Database\n    KeyStore --\u003e KeyFile\n    RecoveryService --\u003e RecoveryFile\n    FileAttachments --\u003e Repository\n    FileAttachments --\u003e ExportedFile\n```\n\nThe WPF app owns interaction and state. The core library owns encryption, storage, recovery, and Windows account key handling. SQLite is treated as a durable encrypted payload store, not as the security boundary.\n\n## Security Model\n\nOn first unlock, LockerIt creates a random 256-bit vault master key. That key encrypts all vault items. Daily unlock stores the master key in a Windows DPAPI-protected local keyring:\n\n```text\n%APPDATA%\\Lockerit\\keyring.bin\n```\n\nThe default SQLite database is:\n\n```text\n%APPDATA%\\Lockerit\\lockerit.db\n```\n\nFor custom database paths, the keyring is stored beside the selected database using:\n\n```text\n\u003cdatabase-name\u003e.keyring.bin\n```\n\nPassword entries and file attachment payloads are serialized as JSON, encrypted with AES-256-GCM, and only then written to SQLite. The database stores item ID, item kind, and encrypted payload. The keyring is protected with `DataProtectionScope.CurrentUser`, so another Windows profile cannot unprotect it directly.\n\nOlder LockerIt builds could add a master password to the local keyring. The desktop UI no longer exposes that option because AuthPolicy 2FA is the supported second factor. Existing master-password keyrings can still be opened for compatibility and are re-saved into the Windows + AuthPolicy model after unlock.\n\nLockerIt AuthPolicy adds another local gate after the vault key is opened: an encrypted policy item inside the vault can require a TOTP authenticator code before the workspace is shown. The setup dialog renders a local QR code and also provides the manual setup key/URI as fallback. The same policy stores hashed one-time recovery codes. Because AuthPolicy lives in the encrypted database, it moves with the vault across devices and remains protected by the vault master key.\n\n## Recovery Model\n\nThe DPAPI keyring is intentionally not portable. A copied keyring from one Windows account should not unlock the vault on another account. Cross-device recovery uses a separate Recovery Kit:\n\n```mermaid\nsequenceDiagram\n    participant Source as Source PC\n    participant Vault as Vault database\n    participant Kit as Recovery Kit\n    participant Target as Target PC\n\n    Source-\u003e\u003eVault: Keep encrypted payloads unchanged\n    Source-\u003e\u003eKit: Export wrapped vault master key\n    Source-\u003e\u003eKit: Protect with recovery passphrase\n    Target-\u003e\u003eVault: Choose copied vault database\n    Target-\u003e\u003eKit: Import Recovery Kit\n    Kit-\u003e\u003eTarget: Unwrap vault master key after passphrase check\n    Target-\u003e\u003eTarget: Create new DPAPI keyring for current Windows account\n    Target-\u003e\u003eVault: Unlock encrypted payloads\n```\n\nThe Recovery Kit uses PBKDF2-HMAC-SHA256 with a 256-bit random salt, 600,000 iterations, and AES-256-GCM authenticated encryption. It can store a non-secret passphrase hint to help the user remember the recovery passphrase. If a vault database already exists but the local keyring is missing, LockerIt refuses to generate a new random key and asks the user to import a Recovery Kit instead.\n\n## Repository Layout\n\n```text\n.\n|-- .github/\n|   `-- workflows/\n|       `-- build.yml\n|-- .docs/\n|   |-- README.md\n|   |-- architecture.md\n|   |-- product-purpose.md\n|   |-- recovery.md\n|   |-- security-model.md\n|   `-- tooling.md\n|-- src/\n|   |-- Lockerit.App/\n|   `-- Lockerit.Core/\n|-- tests/\n|   `-- Lockerit.Core.SmokeTests/\n|-- Lockerit.slnx\n|-- Directory.Build.props\n|-- CONTRIBUTING.md\n|-- LICENSE\n|-- NuGet.Config\n|-- global.json\n`-- README.md\n```\n\n## Documentation\n\n- [.docs/README.md](.docs/README.md) explains the documentation map.\n- [.docs/product-purpose.md](.docs/product-purpose.md) defines the product purpose, user promise, and non-negotiables.\n- [.docs/architecture.md](.docs/architecture.md) describes the app, core, storage, and UI boundaries.\n- [.docs/security-model.md](.docs/security-model.md) documents encryption, DPAPI, threat boundaries, and limitations.\n- [.docs/recovery.md](.docs/recovery.md) explains export, import, and keyring refresh flows.\n- [.docs/tooling.md](.docs/tooling.md) lists local developer commands, GitHub CLI metadata commands, and supply-chain controls.\n\n## Platform\n\nLockerIt is a Windows 11+ desktop application. The app targets `net10.0-windows10.0.22000.0` so Windows 11 APIs such as Windows Hello/PIN/biometric consent and DPAPI CurrentUser behavior are treated as first-class runtime assumptions.\n\n## Build\n\nUse this as the canonical local build method:\n\n```powershell\ndotnet restore Lockerit.slnx --locked-mode\ndotnet build Lockerit.slnx --configuration Release --no-restore -p:ContinuousIntegrationBuild=true\n```\n\nThat matches the GitHub Actions build job before the core smoke test runs.\n\n## Run\n\n```powershell\ndotnet run --project src/Lockerit.App/Lockerit.App.csproj\n```\n\n## Test\n\n```powershell\ndotnet run --project tests/Lockerit.Core.SmokeTests/Lockerit.Core.SmokeTests.csproj\n```\n\nThe smoke test validates:\n\n- password CRUD;\n- password list summaries without decrypted password or notes;\n- encrypted file attachment import/export core behavior;\n- no plaintext password bytes in SQLite database or WAL;\n- no plaintext file bytes in SQLite database or WAL;\n- Recovery Kit export;\n- no plaintext password bytes in the Recovery Kit;\n- Recovery Kit passphrase hint metadata;\n- failed import with a wrong passphrase;\n- successful import after deleting the local keyring;\n- AuthPolicy TOTP enable, verify, recovery-code consume and persistence;\n- legacy master-password keyring unlock/migration behavior;\n- recovered vault unlock.\n\n## Supply-Chain Posture\n\nThe dependency set is intentionally small:\n\n- `Microsoft.Data.Sqlite`\n- `System.Security.Cryptography.ProtectedData`\n\n`NuGet.Config` maps package restore to `nuget.org`, and `Directory.Build.props` enables package lock files. The repository ignores local databases, keyrings, Recovery Kits, settings, environment files, certificates, private keys, and build artifacts.\n\n## Risk Posture\n\n| Previous limitation | Current correction or mitigation | Residual risk |\n| --- | --- | --- |\n| Malware already running as the same unlocked Windows user can interact with the app or user-scoped APIs. | Unlock requires Windows authorization, the app auto-locks after 15 minutes of inactivity, and AuthPolicy can require TOTP before the workspace opens. Routine copy/download actions stay frictionless after unlock. | Malware with the same user context is still outside the hard boundary of a local desktop app. |\n| Recovery passphrase cannot be recovered if forgotten. | Recovery Kits can include a non-secret hint, and an already-unlocked source device can export a new kit. | LockerIt still cannot recover a forgotten passphrase without an unlocked source or another valid Recovery Kit. That is intentional to avoid escrow. |\n| No separate master password option. | Replaced by AuthPolicy TOTP as the supported second factor. Legacy master-password keyrings remain unlockable for migration. | Losing the Recovery Kit/passphrase or all valid AuthPolicy recovery paths can still block cross-device recovery. |\n| No hardware-backed key option. | Windows Hello/PIN/biometric user presence is used for unlock and sensitive actions when available. | Direct TPM-held vault key storage is not implemented yet. |\n| Encrypted file attachments are not implemented. | Implemented encrypted file attachment import/export/delete using the same AES-GCM vault payload model. | Large-file streaming and attachment previews are not implemented yet. |\n| Decrypted strings can exist in UI memory while the app is open. | Password and file lists use summaries without decrypted passwords, notes, or file bytes; full secrets are loaded only for specific actions; modal fields are cleared on close/lock. | WPF strings and password fields can still exist in process memory during active use. |\n\n## License\n\nLockerIt is licensed under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviamus%2Flocker-it","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fviamus%2Flocker-it","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviamus%2Flocker-it/lists"}