Releases: harrytmthy/safebox
SafeBox 1.3.0-alpha01
This release focuses on a slimmer crypto stack, a new helper for non-Prefs use cases, and API cleanup.
⚠️ Breaking changes ⚠️
- Removed
SafeBox.create(...)
overloads that acceptedkeyAlias
andvalueKeyStoreAlias
. Use the simplified factory without aliases. (#111, #103)
Migration note: If you previously passed a customvalueKeyStoreAlias
, re-encrypt stored data or migrate to the default; custom aliases are no longer honored.
Highlights
-
New crypto-only module (
:safebox-crypto
)
Extracts all cryptography into its own artifact so apps that don't needSharedPreferences
can still use SafeBox's cipher stack. (#110) -
SafeBoxCrypto
helper
A simple text encryption with one-liner secret and encryption/decryption. Uses the same cipher as SafeBox and keeps key management in your hands. (#121) -
API cleanup and removals
Alias-based creation removed from the public API (previously deprecated). Internal rotation/destruction hooks on key providers eliminated to avoid accidental data loss. (#111, #103) -
R8 shrink: ~9.5× smaller vs v1.2.0
Switch tobcprov-jdk15on
and targeted keep rules for ChaCha20-Poly1305 drastically reduce APK size under minify, while fixing missing-class warnings. (#115) -
Concurrency and correctness
Cross-cipher contention reduced by isolating ChaCha providers. This ensures exactly one DEK per file even when two providers are used. (#117, #119)
Dependency notes
- BouncyCastle updated to
bcprov-jdk15on:1.70
and consumer ProGuard rules narrowed to the minimal ChaCha20-Poly1305 classes, eliminating broad keeps andjavax.naming.*
warnings. (#115)
If you are evaluating or contributing to SafeBox, we would love your feedback!
SafeBox 1.2.0
SafeBox 1.2.0 focuses on a tighter core, faster writes, and stability during heavy concurrency.
What is new
-
New internal engine
SafeBoxEngine orchestrates in-memory entries, the initial-load barrier, write sequencing, and safe purging of unreadable entries. (#84, #82) -
Stable crypto under load
ChaCha20CipherProvider now uses a process-wide mutex which removes rareAEADBadTagException
. (#90) -
Faster write paths
Critical sections in the engine were reduced which lowers contention during bursty apply or commit. (#92) -
SharedPreferences parity for reads
getXxx()
calls wait for the initial load to complete which matches SharedPreferences behavior. (#71) -
Updated docs and benchmarks
The README includes new v1.2.0 charts and tables plus KDoc corrections. (#89)
Benchmark Update
See the updated performance benchmarks that compare v1.2.0
with EncryptedSharedPreferences
.
Highlights include:
- 184× faster initialization
- Up to 50× faster reads
- Up to 9.25× faster single writes (commit per entry)
- Up to 5.95× faster batched writes (put N entries then commit once)
Deprecations & Scheduled Removals (v1.3)
- CipherPool and CipherPoolExecutor (#78)
setInitialLoadStrategy(...)
which is now a no-op (#68)- AAD-taking
create(...)
overload (#72)
Gradle Setup
implementation("io.github.harrytmthy:safebox:1.2.0")
If SafeBox helped your app run faster or safer, we would love your ⭐ and your feedback!
SafeBox 1.2.0-rc01
What's new in v1.2.0-rc01
This RC focuses on stability under concurrency and faster writes, plus a docs refresh.
-
Prevent AEADBadTagException under concurrency
ChaCha20-Poly1305 is guarded by a process-wide mutex, removing cross-instance races that could cause MAC failures. (#90) -
Faster engine write paths
Reduced lock scope and shorter critical sections improve throughput on burstyapply()
/commit()
sequences. (#92) -
Benchmarks & KDoc update
v1.2.0 charts & tables refreshed in README, and KDocs updated for clarity. (#89)
If you are evaluating or contributing to SafeBox, we would love your feedback!
SafeBox 1.2.0-beta01
What's new in v1.2.0-beta01
This beta focuses on centralized runtime orchestration and a reliability fix.
-
SafeBoxEngine
New internal engine that owns in-memory entries, coordinates the initial-load barrier and write sequencing, handles AEAD dead-entry purge, and fans out change notifications. (#84, #82) -
Fixed editor cleared flag
Reusing an editor afterclear()
no longer causes unintended full clears on later commits. (#86)
If you are evaluating or contributing to SafeBox, we would love your feedback!
SafeBox 1.2.0-alpha02
What's new in v1.2.0-alpha02
This alpha focuses on read parity with SharedPreferences and safer create(...)
when aliases or AAD change.
-
Read parity
getXxx()
now waits for the initial load to finish. Matches SharedPreferences behavior. (#71) -
Guardrails for alias/AAD changes
One-time silent migration on first run keeps the key stable if a legacy alias or custom AAD was used. If anAEADBadTagException
occurs, SafeBox purges unreadable values safely. (#72) -
API cleanup
If you are evaluating or contributing to SafeBox, we would love your feedback!
SafeBox 1.1.5
This patch prevents unintentional KEK rotations (alias/AAD drift) that could surface as AEADBadTagException
and create dead entries. It also safely cleans up any unreadable values. Thanks again to @matheusmelato for the report and retests!
What's Fixed
-
Prevented KEK rotation
One-time DEK rewrap to the default Android Keystore alias when a legacy alias exists. Migration is atomic and idempotent. (#72) -
Handled dead entries on AEAD
WhenAEADBadTagException
occurs, SafeBox now purges unreadable values safely. (#72) -
Wrapped DEK path update
Redirect from$keyAlias.bin
→$fileName.key.bin
with atomic replacement to avoid partial writes. (#72)
Deprecated
AAD-taking factory: In SafeBox.create(...)
, additionalAuthenticatedData
is now ignored and this overload is planned for removal in v1.3. (#72)
Upgrade Notes
- On first run after upgrading, SafeBox will perform a one-time silent rewrap of your DEK if you previously used a non-default
keyAlias
,valueKeyStoreAlias
, and/oradditionalAuthenticatedData
. - No code changes are required. Existing values are preserved.
SafeBox 1.1.4
This patch release fixes a rare concurrency bug in SafeBox cryptography, where parallel encrypt/decrypt operations could corrupt state and trigger AEADBadTagException
. Thanks to @matheusmelato for reporting this issue!
What's Fixed
- Serialized cryptography operations
SafeBox now ensures exclusive key usage during encryption and decryption, preventing parallel race conditions. (#72)
SafeBox 1.2.0-alpha01
What's new in v1.2.0-alpha01
This alpha focuses on single-instance behavior and ergonomic access.
-
Single instance per filename
SafeBox.create(...)
is now atomic and idempotent: repeated calls return the same instance. (#58) -
New getter APIs
Retrieve without aContext
usingSafeBox.get(fileName)
orSafeBox.getOrNull(fileName)
. (#64) -
Deprecated
CLOSED
state
No longer emitted.close()
andcloseWhenIdle()
are no-ops. (#58) -
Stability roll-up
Includes the 1.1.1–1.1.3 fixes (e.g. serialized.apply()
/.commit()
writes). (#60, #51, #54)
// Initialize once
SafeBox.create(context, "prefs")
// Retrieve anywhere later
val prefs = SafeBox.get("prefs") // or SafeBox.getOrNull("prefs")
If you're evaluating or contributing to SafeBox, we would love your feedback!
SafeBox 1.1.3
This patch release improves SafeBox stability by preventing overlapping disk writes between .apply()
and .commit()
.
What's Fixed
- Serialized writes for
.apply()
and.commit()
Rapid sequences could interleave and causeAEADBadTagException
or commit deadlocks. SafeBox now enforces strict write sequencing. (#60)
SafeBox 1.1.2
This patch release improves SafeBox's responsiveness and consistency by aligning .apply()
behavior with EncryptedSharedPreferences
.
What's Fixed
- Real-time Read After Apply
getXxx()
calls now reflect the latest changes immediately after.apply()
is invoked, without waiting for persistence. This resolves unexpected defaults when reading values right after edit. (#54)
This foundational change sets the stage for smarter, more efficient persistence in v1.2.0
.