Popular Searches
Popular Course Categories
Popular Courses

Understanding Android Keystore and Secure Preferences

Understanding Android Keystore and Secure Preferences

App Security and Performance Optimization

Understanding Android Keystore and Secure Preferences

Course: Android App Development

Topic: Understanding Android Keystore and Secure Preferences

Course Link: Android App Development Course

Demo Link: Register for a Course Demo

Website: JustAcademy


1. Introduction to Android Keystore and Secure Preferences

Modern Android applications frequently handle sensitive information such as authentication tokens, encryption keys, account identifiers, private user settings, and session information. Storing this data without appropriate protection can expose users to privacy violations, unauthorized access, and security attacks.

Android provides security mechanisms that help developers protect sensitive information. Android Keystore helps applications generate and manage cryptographic keys, while secure preferences refer to approaches for storing small configuration values or secrets with appropriate encryption and access controls.

These two concepts serve different purposes. Android Keystore protects cryptographic keys and controls how those keys are used. Secure preferences provide a way to persist application values. When sensitive preferences require encryption, a suitable design can use Android Keystore to protect the key used to encrypt those values.

Learning Objectives

  • Understand the Android Keystore system and its architecture.
  • Differentiate between ordinary preferences and encrypted preferences.
  • Generate and retrieve cryptographic keys using Android Keystore.
  • Understand encryption and decryption using AES-GCM.
  • Store small sensitive values using an appropriate secure-storage design.
  • Protect authentication tokens and confidential application settings.
  • Understand key aliases, hardware-backed keys, and authentication requirements.
  • Recognize the limitations of secure preferences.
  • Handle key invalidation, migration, and encryption failures.
  • Apply secure storage practices in practical Android projects.

2. What Is Android Keystore?

Android Keystore is a platform system that allows applications to generate, store, and use cryptographic keys with protections designed to make key extraction more difficult. Applications can request cryptographic operations without directly accessing the underlying protected key material.

Keys can be restricted to specific operations, algorithms, or authentication conditions. Depending on the device, some keys may be protected by secure hardware such as a Trusted Execution Environment (TEE) or StrongBox.

Key Features of Android Keystore

  • Key protection: Helps prevent direct extraction of protected key material.
  • Application isolation: Normally restricts access to keys according to the application identity and platform security model.
  • Cryptographic operations: Supports operations such as encryption, decryption, signing, and verification, depending on the key type and device capabilities.
  • Usage restrictions: Allows developers to specify permitted algorithms, purposes, and other key authorizations.
  • User authentication: Certain keys can require device credential or biometric authentication before use.
  • Hardware-backed security: Supported devices can protect keys using dedicated secure hardware.

3. Why Is Android Keystore Important?

Encryption protects information only when the keys are managed securely. If an application encrypts data but stores the encryption key beside the ciphertext in plain text, an attacker who obtains both may be able to decrypt the data.

Android Keystore helps address this problem by managing cryptographic keys through the Android platform rather than requiring applications to store raw keys in ordinary preference files.

Security Challenge How Android Keystore Helps
Encryption key exposure Helps prevent direct extraction of protected key material.
Unauthorized key usage Supports restrictions on key purposes and cryptographic operations.
Device-level security Can use hardware-backed key protection when supported.
Authentication requirements Can require user authentication before a configured key can be used.
Secure application storage Provides a key-management foundation for encrypting sensitive files and preference values.

Android Keystore does not automatically encrypt every file, database, or preference. Developers must implement the appropriate encryption and storage workflow.

4. Understanding Android Keystore Architecture

Android Keystore integrates with the Android cryptographic APIs and system services. An application requests a key or cryptographic operation through supported APIs, and the platform manages access to the associated key material.

Main Components

  • Android application: Requests key creation and performs supported cryptographic operations.
  • Key alias: A name used by the application to identify a key entry.
  • AndroidKeyStore provider: Connects standard Java cryptography APIs to Android's Keystore implementation.
  • Keystore system service: Manages protected key operations and access.
  • Secure hardware: On supported devices, the key may be protected by a TEE or StrongBox.

Typical Workflow

  1. The application requests a cryptographic key.
  2. Android creates the key according to the specified parameters.
  3. The application retrieves the key using its alias when needed.
  4. The application initializes a cryptographic operation.
  5. Android performs the operation under the key's configured restrictions.
  6. The application stores the resulting ciphertext or uses the cryptographic result.

5. What Are Secure Preferences?

Preferences are used to store small key-value pairs, such as user settings, selected options, and application configuration. Ordinary SharedPreferences are not automatically encrypted, even when created with Context.MODE_PRIVATE.

Secure preferences describe a storage approach in which sensitive preference values are encrypted and the encryption keys are managed appropriately. The specific implementation depends on the APIs and libraries selected for the application.

Examples of Preference Values

Preference Example Recommended Treatment
Theme Dark mode enabled. Ordinary preferences are generally sufficient.
Language English or Hindi. Ordinary preferences are generally sufficient.
Authentication token Access or refresh token. Use an appropriate protected storage design and secure authentication lifecycle.
Encryption configuration Key alias or encryption metadata. Store only non-secret metadata; protect the actual key material.
Private user information Confidential account-related settings. Minimize collection and apply protection appropriate to the sensitivity.

6. SharedPreferences vs Secure Preferences vs Android Keystore

Feature SharedPreferences Secure Preference Design Android Keystore
Primary purpose Store key-value data. Persist sensitive values with encryption. Manage cryptographic keys.
Automatic encryption No. Depends on implementation. Protects key material, not all application data.
Suitable for theme settings Yes. Usually unnecessary. No direct need.
Suitable for encryption keys No, not as raw secrets. Only for non-key data or metadata. Yes, for supported key types.
Hardware-backed protection No built-in key protection. Possible through the key-management design. Available on supported devices and configurations.
Encryption implementation Not provided automatically. Must use an appropriate supported mechanism. Provides cryptographic key operations.

7. Understanding Key Aliases

A key alias is a name used to identify a cryptographic key stored in Android Keystore. It allows the application to retrieve the key when it needs to encrypt or decrypt information.

Aliases should be descriptive and consistent. For example, an application might use user_preferences_key for a key that protects preference values.

Example Alias

private const val PREFERENCES_KEY_ALIAS =
    "user_preferences_key"

The alias is not the secret key itself. Knowing the alias should not give an unauthorized application direct access to the protected key.

8. Generating an AES Key in Android Keystore

AES is a symmetric encryption algorithm. The same secret key is used for encryption and decryption. Android Keystore can generate and manage AES keys for supported cryptographic operations.

Example Kotlin Code

import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.security.KeyStore
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey

private const val KEY_ALIAS =
    "user_preferences_key"

fun generateEncryptionKey(): SecretKey {
    val keyStore = KeyStore.getInstance(
        "AndroidKeyStore"
    ).apply {
        load(null)
    }

    val existingKey = keyStore.getKey(
        KEY_ALIAS,
        null
    ) as? SecretKey

    if (existingKey != null) {
        return existingKey
    }

    val keyGenerator = KeyGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_AES,
        "AndroidKeyStore"
    )

    val keySpec = KeyGenParameterSpec.Builder(
        KEY_ALIAS,
        KeyProperties.PURPOSE_ENCRYPT or
            KeyProperties.PURPOSE_DECRYPT
    )
        .setBlockModes(
            KeyProperties.BLOCK_MODE_GCM
        )
        .setEncryptionPaddings(
            KeyProperties.ENCRYPTION_PADDING_NONE
        )
        .setKeySize(256)
        .build()

    keyGenerator.init(keySpec)
    return keyGenerator.generateKey()
}

This example first checks whether a key already exists. Reusing the existing key is important because generating a new key under the same alias after each application launch can make previously encrypted data unreadable.

9. Encrypting Data with AES-GCM

AES-GCM is an authenticated encryption mode that provides confidentiality and integrity. It encrypts data and generates an authentication tag that allows the application to detect unauthorized modifications during decryption.

Encryption Steps

  1. Retrieve the AES key from Android Keystore.
  2. Create a cipher using AES/GCM/NoPadding.
  3. Initialize the cipher in encryption mode.
  4. Encrypt the original preference value.
  5. Save the generated initialization vector (IV) and ciphertext.

Example Encryption Function

import javax.crypto.Cipher
import javax.crypto.SecretKey

data class EncryptedValue(
    val iv: ByteArray,
    val ciphertext: ByteArray
)

fun encryptValue(
    secretKey: SecretKey,
    value: String
): EncryptedValue {
    val cipher = Cipher.getInstance(
        "AES/GCM/NoPadding"
    )

    cipher.init(
        Cipher.ENCRYPT_MODE,
        secretKey
    )

    val ciphertext = cipher.doFinal(
        value.toByteArray(Charsets.UTF_8)
    )

    return EncryptedValue(
        iv = cipher.iv,
        ciphertext = ciphertext
    )
}

The initialization vector is not a secret, but it must be stored alongside the ciphertext because it is needed for decryption. Never reuse a nonce with the same AES-GCM key. The ciphertext output includes the authentication tag with the standard Android cryptography implementation.

10. Decrypting Stored Preference Values

When the application needs to read a protected value, it retrieves the existing key and initializes the cipher with the saved IV and ciphertext.

Example Decryption Function

import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.SecretKey

fun decryptValue(
    secretKey: SecretKey,
    encryptedValue: EncryptedValue
): String {
    val cipher = Cipher.getInstance(
        "AES/GCM/NoPadding"
    )

    cipher.init(
        Cipher.DECRYPT_MODE,
        secretKey,
        GCMParameterSpec(
            128,
            encryptedValue.iv
        )
    )

    val plaintext = cipher.doFinal(
        encryptedValue.ciphertext
    )

    return String(
        plaintext,
        Charsets.UTF_8
    )
}

If the ciphertext or authentication tag has been modified, decryption should fail with a cryptographic exception. The application should handle that failure safely instead of returning corrupted data or silently generating a replacement key.

11. Storing Encrypted Values in SharedPreferences

After encrypting a sensitive value, the application can store its ciphertext and IV in ordinary private preferences. In this design, the preferences contain encrypted bytes encoded as strings, while Android Keystore protects the encryption key.

Base64 encoding is useful for representing binary data as text, but it is not encryption. The actual confidentiality comes from the encryption step.

Example Storage Workflow

import android.content.Context
import android.util.Base64

fun saveEncryptedValue(
    context: Context,
    name: String,
    encryptedValue: EncryptedValue
) {
    val preferences = context.getSharedPreferences(
        "secure_values",
        Context.MODE_PRIVATE
    )

    preferences.edit()
        .putString(
            "${name}_iv",
            Base64.encodeToString(
                encryptedValue.iv,
                Base64.NO_WRAP
            )
        )
        .putString(
            "${name}_ciphertext",
            Base64.encodeToString(
                encryptedValue.ciphertext,
                Base64.NO_WRAP
            )
        )
        .apply()
}

This is an educational example of combining encrypted data with ordinary preferences. A production implementation should also validate keys, handle storage failures, prevent accidental key collisions, and coordinate updates so that the IV and ciphertext remain consistent.

Reading the Stored Value

fun readEncryptedValue(
    context: Context,
    name: String
): EncryptedValue? {
    val preferences = context.getSharedPreferences(
        "secure_values",
        Context.MODE_PRIVATE
    )

    val ivString = preferences.getString(
        "${name}_iv",
        null
    ) ?: return null

    val ciphertextString = preferences.getString(
        "${name}_ciphertext",
        null
    ) ?: return null

    return EncryptedValue(
        iv = Base64.decode(
            ivString,
            Base64.NO_WRAP
        ),
        ciphertext = Base64.decode(
            ciphertextString,
            Base64.NO_WRAP
        )
    )
}

After retrieving the encrypted value, call the decryption function using the existing Keystore key. Treat malformed Base64 data, missing fields, and authentication failures as storage errors that require controlled handling.

12. Secure Preferences and AndroidX Security Crypto

Android developers have historically used the AndroidX Security Crypto library, including EncryptedSharedPreferences, to encrypt preference keys and values. However, the APIs in AndroidX Security Crypto version 1.1.0 were deprecated in favor of existing platform APIs and direct use of Android Keystore. The library has no planned subsequent releases.

For new projects, evaluate the current Android platform APIs and actively maintained cryptographic libraries rather than automatically adopting older examples that use deprecated encrypted-preference APIs.

Important Considerations

  • Do not assume that a preference file is encrypted just because it is named “secure”.
  • Choose a supported storage and encryption approach for the application's requirements.
  • Use Android Keystore for suitable cryptographic key-management needs.
  • Prefer well-reviewed libraries when a complete encryption abstraction is needed.
  • Document the encryption format so that future application versions can read existing records.
  • Plan migrations before replacing an existing encrypted-storage implementation.

13. Storing Authentication Tokens Securely

Authentication tokens allow an application to access protected server resources. A leaked token may let another person impersonate the user until the token expires or is revoked.

Recommended Practices

  • Use secure HTTPS communication for authentication and API requests.
  • Store tokens only when persistence is necessary.
  • Protect stored tokens using a suitable secure-storage design.
  • Never hardcode tokens or print them in application logs.
  • Use short-lived access tokens and carefully protected refresh tokens when supported.
  • Clear tokens and relevant local session data during logout.
  • Handle token expiration and revocation correctly.
  • Enforce authorization on the server rather than trusting local application state.

14. Protecting Keys with Biometric Authentication

Android Keystore can be configured so that certain keys require user authentication before they can be used. Depending on the application's requirements, this may involve a secure device credential or an eligible biometric authenticator.

Example Configuration Concept

val keySpec = KeyGenParameterSpec.Builder(
    "biometric_protected_key",
    KeyProperties.PURPOSE_ENCRYPT or
        KeyProperties.PURPOSE_DECRYPT
)
    .setBlockModes(
        KeyProperties.BLOCK_MODE_GCM
    )
    .setEncryptionPaddings(
        KeyProperties.ENCRYPTION_PADDING_NONE
    )
    .setUserAuthenticationRequired(true)
    .setInvalidatedByBiometricEnrollment(true)
    .build()

This illustrates selected configuration options; it is not a complete biometric authentication flow. Authentication requirements and supported APIs vary by Android version. Applications must configure suitable authentication parameters and integrate the key operation with the appropriate AndroidX Biometric or platform authentication flow.

When biometric enrollment changes, certain authentication-bound keys may become invalidated. The application must define what happens to data protected by such keys before enabling this behavior.

15. Understanding Hardware-Backed Keystore

Some Android devices support hardware-backed key protection through a Trusted Execution Environment or StrongBox. In these configurations, key material can remain inside a secure hardware environment during cryptographic operations.

Benefits

  • Provides stronger resistance to key extraction on supported devices.
  • Can enforce cryptographic restrictions within a secure environment.
  • Can strengthen protection against certain operating-system or application compromise scenarios.

Hardware-backed protection is not available for every key type and configuration on every device. Applications should not assume that a key is hardware-backed without checking the available security-level information. Hardware-backed keys also do not prevent every attack: a compromised application process may still attempt to misuse a key for operations that the key is authorized to perform.

16. Key Invalidation and Error Handling

Secure-storage implementations must account for situations where a key is missing, invalidated, inaccessible, or incompatible with stored ciphertext.

Problem Possible Cause Recommended Handling
Key not found Key was deleted or the application storage state changed. Do not assume existing ciphertext can be decrypted with a newly generated key.
Decryption failure Wrong key, invalid IV, or modified ciphertext. Handle the exception and protect the user from corrupted output.
Key invalidated A configured authentication or biometric condition changed. Follow a documented recovery or re-authentication process.
Preference data missing Partial write, application reset, or data removal. Handle missing values safely.
Algorithm unavailable Unsupported configuration or device limitation. Use supported cryptographic APIs and report the failure appropriately.

17. Secure Preferences vs DataStore

Jetpack DataStore is a modern solution for storing application settings and structured preferences. However, DataStore does not automatically encrypt the values it persists.

Feature SharedPreferences DataStore Encrypted Storage Design
Storage purpose Key-value settings. Key-value or typed settings. Sensitive values requiring encryption.
Asynchronous API Traditional synchronous reads. Designed around Kotlin Flow and suspend operations. Depends on the selected storage implementation.
Automatic encryption No. No. Yes, when correctly implemented.
Best use Simple settings. Modern application preferences. Tokens and other selected confidential values.

The correct choice depends on the sensitivity of the data and the required behavior. Encryption adds complexity, so avoid encrypting every harmless preference without a clear need.

18. Security Best Practices

  • Never store raw encryption keys in SharedPreferences, DataStore, or source code.
  • Use Android Keystore for supported key-management requirements.
  • Choose modern, authenticated encryption such as AES-GCM when appropriate.
  • Never reuse a GCM nonce with the same key.
  • Store the IV and ciphertext together and validate the stored representation.
  • Do not log plaintext secrets, tokens, or key material.
  • Keep sensitive files inside the application sandbox unless sharing is explicitly required.
  • Review backup and device-transfer behavior.
  • Handle key invalidation and storage corruption deliberately.
  • Use maintained dependencies and review deprecated APIs.
  • Minimize the amount of sensitive data stored on the device.
  • Keep security-sensitive operations off the main thread when they may take significant time.

19. Common Mistakes to Avoid

Mistake Why It Is Dangerous Better Approach
Saving a password in plain text Exposes the credential if storage is accessed. Avoid retaining passwords where possible.
Storing an AES key beside ciphertext An attacker may obtain both components. Protect the key with a suitable key-management mechanism.
Assuming Base64 is encryption Base64 is reversible encoding. Use actual cryptographic encryption.
Generating a new key on every launch Previously encrypted values may become unreadable. Retrieve and reuse the existing key when appropriate.
Ignoring authentication failures May result in crashes or unsafe fallback behavior. Handle errors without exposing sensitive data.
Using deprecated APIs without review Can create maintenance and migration issues. Assess current platform APIs and supported libraries.
Assuming all devices have StrongBox Hardware capabilities differ. Check device support and implement a suitable fallback.

20. Practical Project: Secure Settings Manager

Build an Android application that stores a small sensitive value, such as a mock authentication token, using an encrypted-storage design.

Project Features

  1. Create a screen for entering a test secret.
  2. Generate an AES key using Android Keystore.
  3. Encrypt the secret using AES-GCM.
  4. Save the IV and ciphertext in private preferences.
  5. Retrieve and decrypt the stored value when needed.
  6. Handle missing keys and invalid ciphertext.
  7. Ensure that no sensitive information appears in logs.
  8. Add a delete action to remove the stored value.
  9. Test the application after process termination and restart.
  10. Document limitations and a recovery strategy.

Suggested Architecture

Component Responsibility
Settings Screen Accepts user input and displays permitted settings.
ViewModel Manages screen state and user actions.
Secure Storage Repository Coordinates encryption and preference persistence.
Encryption Manager Encrypts and decrypts sensitive values.
Keystore Manager Creates and retrieves protected cryptographic keys.

21. Testing Secure Preferences and Keystore

Testing should verify that the storage mechanism behaves correctly in both normal and failure conditions.

  • Verify that a generated key can be retrieved by its alias.
  • Encrypt and decrypt a test value and compare the result with the original.
  • Verify that modified ciphertext fails authentication.
  • Confirm that an incorrect or missing key is handled safely.
  • Check that sensitive values do not appear in plain-text logs.
  • Test behavior after application restart.
  • Test missing preference fields and corrupted encoded values.
  • Test biometric or credential requirements if they are implemented.
  • Check device capabilities before relying on hardware-backed keys.
  • Review backup, restore, and key invalidation scenarios.

22. Interview Questions and Answers

Q1. What is Android Keystore?

Android Keystore is a platform system for managing cryptographic keys and restricting how those keys can be used. It helps protect key material from direct extraction.

Q2. What is a key alias?

A key alias is a name used to identify a cryptographic key entry in Android Keystore.

Q3. Does Android Keystore automatically encrypt SharedPreferences?

No. Keystore manages cryptographic keys. The application must implement or use an appropriate storage solution to encrypt preference values.

Q4. What are secure preferences?

Secure preferences are a way of storing small values with appropriate protection, commonly by encrypting sensitive values and protecting the associated keys.

Q5. What is AES-GCM?

AES-GCM is an authenticated encryption mode that provides confidentiality and integrity when used with a suitable key and unique nonce.

Q6. Why must the IV be stored with ciphertext?

The IV is needed to decrypt the data. It is normally stored alongside the ciphertext, but it must not be reused with the same AES-GCM key.

Q7. What is hardware-backed Keystore?

It is a configuration in which supported cryptographic keys are protected by secure hardware, such as a TEE or StrongBox.

Q8. Is Base64 secure encryption?

No. Base64 is an encoding scheme that can be reversed without a key. It does not provide confidentiality.

Q9. What happens when an encryption key is lost?

Previously encrypted data may become unrecoverable. Applications should implement a deliberate recovery, reset, or data-deletion process.

Q10. Why should deprecated encrypted-preference APIs be reviewed?

Deprecated APIs may not be the recommended choice for new development. Developers should evaluate current Android platform APIs and maintained alternatives before selecting an implementation.

23. Quick Revision

  • Android Keystore manages cryptographic keys and restricts their use.
  • Secure preferences protect selected values through an appropriate encryption design.
  • Ordinary SharedPreferences and DataStore do not automatically encrypt values.
  • A key alias identifies a key; it is not the key itself.
  • AES-GCM provides authenticated encryption when used correctly.
  • The IV must be stored with the ciphertext, and GCM nonces must not be reused with the same key.
  • Hardware-backed protection depends on device capabilities.
  • Applications must handle missing keys, invalidated keys, and decryption failures.
  • Do not store raw encryption keys alongside encrypted data.
  • Review backups, logs, dependencies, and migration requirements.

Conclusion

Understanding Android Keystore and secure preferences is essential for building mobile applications that handle confidential information responsibly. Android Keystore helps protect cryptographic keys, while secure preference designs allow applications to persist selected sensitive values with encryption.

By using supported cryptographic APIs, protecting keys, handling errors carefully, and avoiding insecure storage practices, developers can improve the confidentiality and integrity of Android application data. Secure storage should always be designed as part of a broader security strategy that also considers authentication, backups, network communication, and user privacy.


Explore Android App Development with JustAcademy

Strengthen your skills in Kotlin, Android architecture, secure storage, authentication, encryption, and mobile application development.

Course Link: Explore the Android App Development Course

Demo Registration: Register for a Course Demo

Website: Visit JustAcademy

Previous Next
whatsapp