{"id":37019341,"url":"https://github.com/harrytmthy/safebox","last_synced_at":"2026-01-14T02:08:24.709Z","repository":{"id":292494906,"uuid":"980108327","full_name":"harrytmthy/safebox","owner":"harrytmthy","description":"A blazing-fast drop-in replacement for EncryptedSharedPreferences on Android","archived":false,"fork":false,"pushed_at":"2025-10-17T12:44:26.000Z","size":1220,"stargazers_count":24,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-18T13:49:17.170Z","etag":null,"topics":["aes-gcm","android","android-keystore","android-library","android-sdk","android-security","chacha20-poly1305","cryptography","encryptedsharedpreferences","encryption","kotlin","mmap","safebox","secure-storage","sharedpreferences"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","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/harrytmthy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","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},"funding":{"github":"harrytmthy"}},"created_at":"2025-05-08T15:17:18.000Z","updated_at":"2025-10-17T12:43:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"0ed98fff-732e-486e-beab-f5cc392263f5","html_url":"https://github.com/harrytmthy/safebox","commit_stats":null,"previous_names":["harrytmthy-dev/safebox","harrytmthy/safebox"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/harrytmthy/safebox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrytmthy%2Fsafebox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrytmthy%2Fsafebox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrytmthy%2Fsafebox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrytmthy%2Fsafebox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/harrytmthy","download_url":"https://codeload.github.com/harrytmthy/safebox/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrytmthy%2Fsafebox/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"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","android","android-keystore","android-library","android-sdk","android-security","chacha20-poly1305","cryptography","encryptedsharedpreferences","encryption","kotlin","mmap","safebox","secure-storage","sharedpreferences"],"created_at":"2026-01-14T02:08:24.090Z","updated_at":"2026-01-14T02:08:24.704Z","avatar_url":"https://github.com/harrytmthy.png","language":"Kotlin","readme":"# SafeBox\n\n[![Build](https://img.shields.io/github/actions/workflow/status/harrytmthy/safebox/ci.yml?branch=main\u0026label=build\u0026logo=githubactions\u0026logoColor=white\u0026style=flat-square)](https://github.com/harrytmthy/safebox/actions)\n[![License](https://img.shields.io/github/license/harrytmthy/safebox?label=license\u0026color=blue\u0026style=flat-square)](https://github.com/harrytmthy/safebox/blob/main/LICENSE)\n[![Release](https://img.shields.io/github/v/release/harrytmthy/safebox?include_prereleases\u0026label=release\u0026color=orange\u0026style=flat-square)](https://github.com/harrytmthy/safebox/releases)\n\nA secure, blazing-fast alternative to `EncryptedSharedPreferences`, designed for Android projects which demand both **speed** and **security**.\n\n## 🚨 EncryptedSharedPreferences is Deprecated\nAs of **Jetpack Security 1.1.0-alpha07 (April 9, 2025)**, `EncryptedSharedPreferences` has been deprecated with no official replacement. Without continued support from Google, it may fall behind in cryptography standards, leaving sensitive data exposed.\n\nSafeBox can help you [migrate](docs/MIGRATION.md) easily using the same `SharedPreferences` API. Since v1.2.0, SafeBox delivers **~184× faster init**, **~50× faster reads**, and **~9× faster writes** than EncryptedSharedPreferences.\n\n## Why SafeBox?\n\n|                | SafeBox                                              | EncryptedSharedPreferences                   |\n|----------------|------------------------------------------------------|----------------------------------------------|\n| Encryption     | **Modern ChaCha20-Poly1305 with secure key vault**   | Older AES setup tied to deprecated MasterKey |\n| Storage format | **Memory-mapped binary file with minimal headers**   | XML text file with tag/attribute overhead    |\n| I/O model      | **New data is tail-appended**                        | New data rewrites the whole XML              |\n| Concurrency    | **Stays smooth on concurrent writes**                | Gets slower on concurrent writes             |\n| Scalability    | **Stable performance on large size**                 | Keeps getting heavier as data grows          |\n| Durability     | **Low-storage failures fallback to a recovery file** | Low-storage failures = data loss             |\n| Customization  | **Cipher providers are replaceable**                 | Ciphers are not customizable                 |\n\nSafeBox uses **deterministic encryption** for reference keys (for fast lookup) and **non-deterministic encryption** for values (for strong security). Both powered by a single ChaCha20 key protected via AES-GCM and stored securely.\n\n\u003cdetails\u003e\n\n\u003csummary\u003e🔑 SafeBox Key Derivation \u0026 Encryption Flow\u003c/summary\u003e\n\n```\n [Android Keystore-backed AES-GCM Key]\n                  ↓\n       [ChaCha20-Poly1305 Key]\n              ↙       ↘\n    Reference Keys    Entry Values\n(deterministic IV)    (randomized IV)\n```\n\nCompared to EncryptedSharedPreferences:\n\n```\n[Android Keystore MasterKey (deprecated)]\n           ↙             ↘\n    [AES-SIV Key]    [AES-GCM Key]\n         ↓                 ↓\n   Reference Keys     Entry Values\n\n```\n\n\u003c/details\u003e\n\n## Installation\n\n```kotlin\ndependencies {\n    implementation(\"io.github.harrytmthy:safebox:1.3.0\")\n\n    // Optional: standalone crypto helper\n    implementation(\"io.github.harrytmthy:safebox-crypto:1.3.0\")\n}\n```\n\n## Basic Usage\n\nCreate the instance:\n\n```kotlin\nval prefs: SharedPreferences = SafeBox.create(context, PREF_FILE_NAME)\n```\n\nThen use it like any `SharedPreferences`:\n\n```kotlin\nprefs.edit()\n    .putInt(\"userId\", 123)\n    .putString(\"name\", \"Luna Moonlight\")\n    .apply()\n\nval userId = prefs.getInt(\"userId\", -1)\nval email = prefs.getString(\"email\", null)\n```\n\nOnce created, you can retrieve the same instance without a `Context`:\n\n```kotlin\nSafeBox.get(PREF_FILE_NAME) // or SafeBox.create(context, PREF_FILE_NAME)\n    .edit()\n    .clear()\n    .commit()\n```\n\n\u003e Prefer `SafeBox.getOrNull(fileName)` if you need a safe retrieval without throwing.\n\n### Understanding SafeBox Behavior\n\nSafeBox returns the same instance per filename:\n\n```kotlin\nval a1 = SafeBox.create(context, \"fileA\")\nval a2 = SafeBox.create(context, \"fileA\")\nval a3 = SafeBox.get(\"fileA\")\n\nassertTrue(a1 === a2)   // same reference\nassertTrue(a1 === a3)   // same reference\n\nval b = SafeBox.create(context, \"fileB\")\nassertTrue(a1 !== b)    // different filenames = different instances\n```\n\n\u003e Repeating `SafeBox.create(context, fileName)` returns the existing instance for that `fileName`. When an instance already exists, **all parameters are ignored** except a non-null `stateListener`, which replaces the current listener.\n\n\u003e Need lifecycle hooks for diagnostics or analytics? ➡️ [Read the Observability Guide](docs/OBSERVABILITY.md)\n\n## Migrating from EncryptedSharedPreferences\n\nSafeBox is a drop-in replacement for `EncryptedSharedPreferences`.\n\n➡️ [Read the Migration Guide](docs/MIGRATION.md)\n\n## Text Encryption Support\n\nSafeBox includes a simple text encryption helper (`SafeBoxCrypto`) you can use for things like\nencrypting values before writing to Room or sending over the network:\n\n```kotlin\n// 1. Create a secret and store it in your own vault\nval secret: String = SafeBoxCrypto.createSecret()\n\n// 2. Use it to encrypt\nval userEntity = UserEntity(\n    id = SafeBoxCrypto.encrypt(userId, secret),\n    // ...\n)\n\n// 3. Retrieve it later\nval userId: String = SafeBoxCrypto.decrypt(userEntity.id, secret)\n```\n\nIf you only need the helper, use the standalone `:safebox-crypto` module.\n\n## Performance Benchmarks\n\nAverage times measured over **100 samples** on an emulator:\n\n\u003cdetails open\u003e\n\n\u003csummary\u003e📊 v1.3.0 Benchmark\u003c/summary\u003e\n\n![Get Performance](docs/charts/v1_3_get_performance_chart.png)\n\n![Put Performance](docs/charts/v1_3_put_performance_chart.png)\n\n![Put then Commit Performance](docs/charts/v1_3_put_and_commit_performance_chart.png)\n\n| Operation                   | SafeBox v1.3.0               | EncryptedSharedPreferences |\n|-----------------------------|------------------------------|----------------------------|\n| Initialization              | **0.19ms** (*201.1× faster*) | 38.7ms                     |\n| Get 1 entry                 | **0.01ms** (*76.9× faster*)  | 0.50ms                     |\n| Get 3 entries               | **0.02ms** (*68.5× faster*)  | 1.27ms                     |\n| Get 5 entries               | **0.03ms** (*76.8× faster*)  | 2.25ms                     |\n| Get 10 entries              | **0.06ms** (*66.4× faster*)  | 4.07ms                     |\n| Put 1 entry, then commit    | **0.17ms** (*7.8× faster*)   | 1.31ms                     |\n| Put 3 entries, then commit  | **0.46ms** (*4.7× faster*)   | 2.16ms                     |\n| Put 5 entries, then commit  | **0.73ms** (*4.5× faster*)   | 3.32ms                     |\n| Put 10 entries, then commit | **1.46ms** (*4.3× faster*)   | 6.28ms                     |\n\nEven on **multiple single commits**, SafeBox remains faster:\n\n| Operation                 | SafeBox v1.3.0              | EncryptedSharedPreferences |\n|---------------------------|-----------------------------|----------------------------|\n| Commit 3 single entries   | **0.52ms** (*9.5× faster*)  | 4.90ms                     |\n| Commit 5 single entries   | **0.85ms** (*8.2× faster*)  | 6.91ms                     |\n| Commit 10 single entries  | **1.71ms** (*6.6× faster*)  | 11.27ms                    |\n| Commit 100 single entries | **16.51ms** (*4.3× faster*) | 71.34ms                    |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e📊 v1.2.0 Benchmark\u003c/summary\u003e\n\n![Get Performance](docs/charts/v1_2_get_performance_chart.png)\n\n![Put Performance](docs/charts/v1_2_put_performance_chart.png)\n\n![Put then Commit Performance](docs/charts/v1_2_put_and_commit_performance_chart.png)\n\n| Operation                   | SafeBox v1.2.0               | EncryptedSharedPreferences |\n|-----------------------------|------------------------------|----------------------------|\n| Initialization              | **0.21ms** (*184.3× faster*) | 38.7ms                     |\n| Get 1 entry                 | **0.01ms** (*50.0× faster*)  | 0.50ms                     |\n| Get 3 entries               | **0.04ms** (*31.8× faster*)  | 1.27ms                     |\n| Get 5 entries               | **0.07ms** (*32.1× faster*)  | 2.25ms                     |\n| Get 10 entries              | **0.15ms** (*27.1× faster*)  | 4.07ms                     |\n| Put 1 entry, then commit    | **0.22ms** (*5.95× faster*)  | 1.31ms                     |\n| Put 3 entries, then commit  | **0.52ms** (*4.15× faster*)  | 2.16ms                     |\n| Put 5 entries, then commit  | **0.98ms** (*3.39× faster*)  | 3.32ms                     |\n| Put 10 entries, then commit | **1.64ms** (*3.83× faster*)  | 6.28ms                     |\n\nEven on **multiple single commits**, SafeBox remains faster:\n\n| Operation                 | SafeBox v1.2.0               | EncryptedSharedPreferences |\n|---------------------------|------------------------------|----------------------------|\n| Commit 3 single entries   | **0.53ms** (*9.25× faster*)  | 4.90ms                     |\n| Commit 5 single entries   | **0.95ms** (*7.27× faster*)  | 6.91ms                     |\n| Commit 10 single entries  | **1.96ms** (*5.75× faster*)  | 11.27ms                    |\n| Commit 100 single entries | **17.41ms** (*4.10× faster*) | 71.34ms                    |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e📊 v1.1.0 Benchmark\u003c/summary\u003e\n\n![Get Performance](docs/charts/v1_1_get_performance_chart.png)\n\n![Put Performance](docs/charts/v1_1_put_performance_chart.png)\n\n![Put then Commit Performance](docs/charts/v1_1_put_and_commit_performance_chart.png)\n\n| Operation                   | SafeBox v1.1.0 | EncryptedSharedPreferences |\n|-----------------------------|----------------|----------------------------|\n| Initialization              | **0.38ms**     | 38.7ms (*10,079% slower*)  |\n| Get 1 entry                 | **0.33ms**     | 0.50ms (*52% slower*)      |\n| Get 3 entries               | **0.94ms**     | 1.27ms (*35% slower*)      |\n| Get 5 entries               | **1.56ms**     | 2.25ms (*44% slower*)      |\n| Get 10 entries              | **3.06ms**     | 4.07ms (*33% slower*)      |\n| Put 1 entry, then commit    | **0.49ms**     | 1.31ms (*167% slower*)     |\n| Put 3 entries, then commit  | **1.34ms**     | 2.16ms (*61% slower*)      |\n| Put 5 entries, then commit  | **2.36ms**     | 3.32ms (*41% slower*)      |\n| Put 10 entries, then commit | **4.20ms**     | 6.28ms (*50% slower*)      |\n\nEven on **multiple single commits**, SafeBox remains faster:\n\n| Operation                    | SafeBox v1.1.0 | EncryptedSharedPreferences |\n|------------------------------|----------------|----------------------------|\n| Commit 3 single entries      | **1.50ms**     | 4.90ms (*227% slower*)     |\n| Commit 5 single entries      | **2.39ms**     | 6.91ms (*189% slower*)     |\n| Commit 10 single entries     | **5.07ms**     | 11.27ms (*122% slower*)    |\n| Commit 100 single entries    | **38.12ms**    | 71.34ms (*87% slower*)     |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e📊 v1.0.0 Benchmark\u003c/summary\u003e\n\n![Get Performance](docs/charts/read_performance_chart.png)\n\n![Put Performance](docs/charts/write_performance_chart.png)\n\n![Put then Commit Performance](docs/charts/write_commit_performance_chart.png)\n\n| Operation                   | SafeBox v1.0.0 | EncryptedSharedPreferences |\n|-----------------------------|----------------|----------------------------|\n| Get 1 entry                 | **0.39ms**     | 0.50ms (*28% slower*)      |\n| Get 3 entries               | **0.94ms**     | 1.27ms (*35% slower*)      |\n| Get 5 entries               | **1.37ms**     | 2.25ms (*64% slower*)      |\n| Get 10 entries              | **3.29ms**     | 4.07ms (*24% slower*)      |\n| Put 1 entry, then commit    | **0.55ms**     | 1.31ms (*138% slower*)     |\n| Put 3 entries, then commit  | **1.25ms**     | 2.16ms (*73% slower*)      |\n| Put 5 entries, then commit  | **2.33ms**     | 3.32ms (*42% slower*)      |\n| Put 10 entries, then commit | **4.73ms**     | 6.28ms (*33% slower*)      |\n\nEven on **multiple single commits**, SafeBox remains faster:\n\n| Operation                    | SafeBox v1.0.0 | EncryptedSharedPreferences |\n|------------------------------|----------------|----------------------------|\n| Commit 3 single entries      | **1.94ms**     | 4.90ms (*152% slower*)     |\n| Commit 5 single entries      | **2.84ms**     | 6.91ms (*143% slower*)     |\n| Commit 10 single entries     | **5.47ms**     | 11.27ms (*106% slower*)    |\n| Commit 100 single entries    | **33.19ms**    | 71.34ms (*115% slower*)    |\n\n\u003c/details\u003e\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for setup, formatting, testing, and PR guidelines.\n\n## 💖 Support SafeBox\n\nIf SafeBox helped secure your app or saved your time, consider sponsoring to support future improvements and maintenance!\n\n[![Sponsor](https://img.shields.io/badge/sponsor-%F0%9F%92%96-blueviolet?style=flat-square)](https://github.com/sponsors/harrytmthy)\n\n## License\n\n```\nMIT License\nCopyright (c) 2025 Harry Timothy Tumalewa\n```","funding_links":["https://github.com/sponsors/harrytmthy"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharrytmthy%2Fsafebox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fharrytmthy%2Fsafebox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharrytmthy%2Fsafebox/lists"}