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.

Why SafeBox?

Feature SafeBox v1.2.0 EncryptedSharedPreferences
Initialization Time 0.21ms (184.3Γ— faster) 38.7ms
Storage Format Memory-mapped binary file XML-based per-entry
Encryption Method ChaCha20-Poly1305 (keys & values) AES-SIV for keys, AES-GCM for values
Key Security Android Keystore-backed AES-GCM Android Keystore MasterKey (deprecated)
Customization Pluggable cipher providers Tightly coupled

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-alpha01")

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

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