Skip to content

A blazing-fast drop-in replacement for EncryptedSharedPreferences on Android

License

Notifications You must be signed in to change notification settings

harrytmthy/safebox

Repository files navigation

SafeBox

Build License Release

A secure, blazing-fast alternative to EncryptedSharedPreferences, designed for Android projects which demand both speed and security.

🚨 EncryptedSharedPreferences is Deprecated

As 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.

SafeBox can help you migrate easily using the same SharedPreferences API. Since v1.2.0, SafeBox delivers ~184Γ— faster init, ~50Γ— faster reads, and ~9Γ— faster writes than EncryptedSharedPreferences.

Why SafeBox?

SafeBox EncryptedSharedPreferences
Encryption Modern ChaCha20-Poly1305 with secure key vault Older AES setup tied to deprecated MasterKey
Storage format Memory-mapped binary file with minimal headers XML text file with tag/attribute overhead
I/O model New data is tail-appended New data rewrites the whole XML
Concurrency Stays smooth on concurrent writes Gets slower on concurrent writes
Scalability Stable performance on large size Keeps getting heavier as data grows
Durability Low-storage failures fallback to a recovery file Low-storage failures = data loss
Customization Cipher providers are replaceable Ciphers are not customizable

SafeBox 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.

πŸ”‘ SafeBox Key Derivation & Encryption Flow
 [Android Keystore-backed AES-GCM Key]
                  ↓
       [ChaCha20-Poly1305 Key]
              ↙       β†˜
    Reference Keys    Entry Values
(deterministic IV)    (randomized IV)

Compared to EncryptedSharedPreferences:

[Android Keystore MasterKey (deprecated)]
           ↙             β†˜
    [AES-SIV Key]    [AES-GCM Key]
         ↓                 ↓
   Reference Keys     Entry Values

Installation

dependencies {
    implementation("io.github.harrytmthy:safebox:1.3.0")

    // Optional: standalone crypto helper
    implementation("io.github.harrytmthy:safebox-crypto:1.3.0")
}

Basic Usage

Create the instance:

val prefs: SharedPreferences = SafeBox.create(context, PREF_FILE_NAME)

Then use it like any SharedPreferences:

prefs.edit()
    .putInt("userId", 123)
    .putString("name", "Luna Moonlight")
    .apply()

val userId = prefs.getInt("userId", -1)
val email = prefs.getString("email", null)

Once created, you can retrieve the same instance without a Context:

SafeBox.get(PREF_FILE_NAME) // or SafeBox.create(context, PREF_FILE_NAME)
    .edit()
    .clear()
    .commit()

Prefer SafeBox.getOrNull(fileName) if you need a safe retrieval without throwing.

Understanding SafeBox Behavior

SafeBox returns the same instance per filename:

val a1 = SafeBox.create(context, "fileA")
val a2 = SafeBox.create(context, "fileA")
val a3 = SafeBox.get("fileA")

assertTrue(a1 === a2)   // same reference
assertTrue(a1 === a3)   // same reference

val b = SafeBox.create(context, "fileB")
assertTrue(a1 !== b)    // different filenames = different instances

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.

Need lifecycle hooks for diagnostics or analytics? ➑️ Read the Observability Guide

Migrating from EncryptedSharedPreferences

SafeBox is a drop-in replacement for EncryptedSharedPreferences.

➑️ Read the Migration Guide

Text Encryption Support

SafeBox includes a simple text encryption helper (SafeBoxCrypto) you can use for things like encrypting values before writing to Room or sending over the network:

// 1. Create a secret and store it in your own vault
val secret: String = SafeBoxCrypto.createSecret()

// 2. Use it to encrypt
val userEntity = UserEntity(
    id = SafeBoxCrypto.encrypt(userId, secret),
    // ...
)

// 3. Retrieve it later
val userId: String = SafeBoxCrypto.decrypt(userEntity.id, secret)

If you only need the helper, use the standalone :safebox-crypto module.

Performance Benchmarks

Average times measured over 100 samples on an emulator:

πŸ“Š v1.3.0 Benchmark

Get Performance

Put Performance

Put then Commit Performance

Operation SafeBox v1.3.0 EncryptedSharedPreferences
Initialization 0.19ms (201.1Γ— faster) 38.7ms
Get 1 entry 0.01ms (76.9Γ— faster) 0.50ms
Get 3 entries 0.02ms (68.5Γ— faster) 1.27ms
Get 5 entries 0.03ms (76.8Γ— faster) 2.25ms
Get 10 entries 0.06ms (66.4Γ— faster) 4.07ms
Put 1 entry, then commit 0.17ms (7.8Γ— faster) 1.31ms
Put 3 entries, then commit 0.46ms (4.7Γ— faster) 2.16ms
Put 5 entries, then commit 0.73ms (4.5Γ— faster) 3.32ms
Put 10 entries, then commit 1.46ms (4.3Γ— faster) 6.28ms

Even on multiple single commits, SafeBox remains faster:

Operation SafeBox v1.3.0 EncryptedSharedPreferences
Commit 3 single entries 0.52ms (9.5Γ— faster) 4.90ms
Commit 5 single entries 0.85ms (8.2Γ— faster) 6.91ms
Commit 10 single entries 1.71ms (6.6Γ— faster) 11.27ms
Commit 100 single entries 16.51ms (4.3Γ— faster) 71.34ms
πŸ“Š v1.2.0 Benchmark

Get Performance

Put Performance

Put then Commit Performance

Operation SafeBox v1.2.0 EncryptedSharedPreferences
Initialization 0.21ms (184.3Γ— faster) 38.7ms
Get 1 entry 0.01ms (50.0Γ— faster) 0.50ms
Get 3 entries 0.04ms (31.8Γ— faster) 1.27ms
Get 5 entries 0.07ms (32.1Γ— faster) 2.25ms
Get 10 entries 0.15ms (27.1Γ— faster) 4.07ms
Put 1 entry, then commit 0.22ms (5.95Γ— faster) 1.31ms
Put 3 entries, then commit 0.52ms (4.15Γ— faster) 2.16ms
Put 5 entries, then commit 0.98ms (3.39Γ— faster) 3.32ms
Put 10 entries, then commit 1.64ms (3.83Γ— faster) 6.28ms

Even on multiple single commits, SafeBox remains faster:

Operation SafeBox v1.2.0 EncryptedSharedPreferences
Commit 3 single entries 0.53ms (9.25Γ— faster) 4.90ms
Commit 5 single entries 0.95ms (7.27Γ— faster) 6.91ms
Commit 10 single entries 1.96ms (5.75Γ— faster) 11.27ms
Commit 100 single entries 17.41ms (4.10Γ— faster) 71.34ms
πŸ“Š v1.1.0 Benchmark

Get Performance

Put Performance

Put then Commit Performance

Operation SafeBox v1.1.0 EncryptedSharedPreferences
Initialization 0.38ms 38.7ms (10,079% slower)
Get 1 entry 0.33ms 0.50ms (52% slower)
Get 3 entries 0.94ms 1.27ms (35% slower)
Get 5 entries 1.56ms 2.25ms (44% slower)
Get 10 entries 3.06ms 4.07ms (33% slower)
Put 1 entry, then commit 0.49ms 1.31ms (167% slower)
Put 3 entries, then commit 1.34ms 2.16ms (61% slower)
Put 5 entries, then commit 2.36ms 3.32ms (41% slower)
Put 10 entries, then commit 4.20ms 6.28ms (50% slower)

Even on multiple single commits, SafeBox remains faster:

Operation SafeBox v1.1.0 EncryptedSharedPreferences
Commit 3 single entries 1.50ms 4.90ms (227% slower)
Commit 5 single entries 2.39ms 6.91ms (189% slower)
Commit 10 single entries 5.07ms 11.27ms (122% slower)
Commit 100 single entries 38.12ms 71.34ms (87% slower)
πŸ“Š v1.0.0 Benchmark

Get Performance

Put Performance

Put then Commit Performance

Operation SafeBox v1.0.0 EncryptedSharedPreferences
Get 1 entry 0.39ms 0.50ms (28% slower)
Get 3 entries 0.94ms 1.27ms (35% slower)
Get 5 entries 1.37ms 2.25ms (64% slower)
Get 10 entries 3.29ms 4.07ms (24% slower)
Put 1 entry, then commit 0.55ms 1.31ms (138% slower)
Put 3 entries, then commit 1.25ms 2.16ms (73% slower)
Put 5 entries, then commit 2.33ms 3.32ms (42% slower)
Put 10 entries, then commit 4.73ms 6.28ms (33% slower)

Even on multiple single commits, SafeBox remains faster:

Operation SafeBox v1.0.0 EncryptedSharedPreferences
Commit 3 single entries 1.94ms 4.90ms (152% slower)
Commit 5 single entries 2.84ms 6.91ms (143% slower)
Commit 10 single entries 5.47ms 11.27ms (106% slower)
Commit 100 single entries 33.19ms 71.34ms (115% slower)

Contributing

See CONTRIBUTING.md for setup, formatting, testing, and PR guidelines.

πŸ’– Support SafeBox

If SafeBox helped secure your app or saved your time, consider sponsoring to support future improvements and maintenance!

Sponsor

License

MIT License
Copyright (c) 2025 Harry Timothy Tumalewa

Sponsor this project

 

Packages

No packages published

Contributors 2

  •  
  •