SoFunction
Updated on 2025-04-18

Summary of several ways to safe storage of Tokens

1. EncryptedSharedPreferences

EncryptedSharedPreferencesis an open source library forSharedPreferencesEncrypted storage provides higher security.

Sample code

// Create EncryptedSharedPreferences keyPair = (context, MasterKeys.AES256_GCM_SPEC);
String keyAlias = ();

EncryptedSharedPreferences encryptedSharedPreferences = (
        context,
        "encrypted_prefs",
        keyAlias,
        .AES256_SIV,
        .AES256_GCM
);

//Storage Token editor = ();
("token", token);
();

// Get TokenString token = ("token", null);

2. SQLCipher

SQLCipheris an open source library for encrypting storage of SQLite databases and is suitable for scenarios where higher security is required.

Sample code

// Initialize the SQLCipher databaseSQLiteDatabase db = (
        new File((), ""),
        "password", // Database Password        null
);

// Create table and store tokens("CREATE TABLE IF NOT EXISTS tokens (token TEXT)");
("INSERT INTO tokens (token) VALUES (?)", new Object[]{token});
();

3. Encrypt and store using Android Keystore

Keystore provides hardware-level encryption protection, making it difficult to obtain the keys stored in the Keystore even if the device is rooted.
Very suitable for storing sensitive information such as tokens and passwords.

However, using Keystore is more complicated, requiring operations such as generating key pairs, encrypting and decrypting data. Encryption and decryption operations will bring certain performance overhead.

Sample code

1. Generate a key pair

When the application is first launched, a key pair is generated and stored in the Keystore.

import ;
import ;
import .Base64;

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

import ;
import ;
import ;
import ;

public class KeystoreManager {
    private static final String KEYSTORE_PROVIDER = "AndroidKeyStore";
    private static final String KEY_ALIAS = "myAppKeyAlias";
    private static final String ENCRYPTION_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
    private static final String ENCRYPTION_BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM;
    private static final String ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_NONE;
    private static final String ENCRYPTION_TRANSFORMATION = ENCRYPTION_ALGORITHM + "/"
            + ENCRYPTION_BLOCK_MODE + "/" + ENCRYPTION_PADDING;

    private KeyStore keyStore;

    public KeystoreManager() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
        keyStore = (KEYSTORE_PROVIDER);
        (null);
    }

    public void generateKey() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        KeyGenerator keyGenerator = (KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_PROVIDER);
        (new (KEY_ALIAS,
                KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(ENCRYPTION_BLOCK_MODE)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                .build());
        ();
    }

    public byte[] encryptData(String data) throws Exception {
        Cipher cipher = (ENCRYPTION_TRANSFORMATION);
        (Cipher.ENCRYPT_MODE, getSecretKey());
        return (());
    }

    public String decryptData(byte[] encryptedData) throws Exception {
        Cipher cipher = (ENCRYPTION_TRANSFORMATION);
        (Cipher.DECRYPT_MODE, getSecretKey());
        return new String((encryptedData));
    }

    private SecretKey getSecretKey() throws UnrecoverableEntryException, KeyStoreException {
        return (SecretKey) (KEY_ALIAS, null);
    }
}

2. Use KeystoreManager

In your application, useKeystoreManagerTo store and read the token.

import ;
import ;

import ;

import ;
import ;
import ;
import ;
import ;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        (savedInstanceState);
        setContentView(.activity_main);

        try {
            KeystoreManager keystoreManager = new KeystoreManager();
            // Generate key pairs (only call once on first startup)            ();

            // Encryption Token            String accessToken = "your_access_token_here";
            byte[] encryptedAccessToken = (accessToken);
            
			// Please refer to the following methods for storage			
            // Decrypt Token            String decryptedAccessToken = (encryptedAccessToken);

            (TAG, "Encrypted Token: " + (encryptedAccessToken, ));
            (TAG, "Decrypted Token: " + decryptedAccessToken);
        } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | UnrecoverableEntryException | InvalidAlgorithmParameterException e) {
            ();
        }
    }
}

Code description

  1. Generate a key pair

    • useKeyGenParameterSpecDefine the properties of the key.
    • useKeyGeneratorGenerate key pairs and store them in the Keystore.
  2. Encrypted data

    • useCipherEncrypt the data.
    • Returns the encrypted byte array.
  3. Decrypt the data

    • useCipherDecrypt the encrypted data.
    • Returns the decrypted string.
  4. Store and read Tokens

    • Store the encrypted token in the application's private directory (e.g.SharedPreferencesor file system).
    • When needed, the encrypted data is read and decrypted.

Safety advice

  1. Key Management: Ensure the security of the generation and use of keys and avoid key leakage.
  2. Store encrypted data: Store the encrypted token in the application's private directory to avoid being accessed by other applications.
  3. Error handling: In practical applications, various abnormal situations need to be handled to ensure the stability and security of the application.

Several storage methods after encryption

1. Encrypted and use SharedPreferences storage

SharedPreferencesIt is a lightweight storage method in Android, suitable for storing a small amount of key-value pair data. You can store the encrypted tokens toSharedPreferencesmiddle.

//Storing encrypted tokens to SharedPreferencesSharedPreferences sharedPreferences = getSharedPreferences("MyAppPreferences", MODE_PRIVATE);
 editor = ();
("encryptedToken", (encryptedAccessToken, ));
();

fromSharedPreferencesWhen reading:

SharedPreferences sharedPreferences = getSharedPreferences("MyAppPreferences", MODE_PRIVATE);
String encryptedToken = ("encryptedToken", null);
if (encryptedToken != null) {
    byte[] encryptedAccessToken = (encryptedToken, );
    // Then you can decrypt the encryptedAccessToken and other operations}

2. After encryption, use SQLite database storage

If there is a database in the application (such as SQLite), the encrypted token can also be stored in the database. This method is suitable for scenarios where structured storage is required.

1. TokenDatabaseHelper class

Here is the complete code of the TokenDatabaseHelper class to create and manage SQLite databases:

import ;
import ;
import ;
import ;
import ;

public class TokenDatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "";
    private static final int DATABASE_VERSION = 1;
    private static final String TABLE_TOKENS = "tokens";
    private static final String COLUMN_ID = "id";
    private static final String COLUMN_TOKEN = "token";

    public TokenDatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String createTable = "CREATE TABLE " + TABLE_TOKENS + "("
                + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + COLUMN_TOKEN + " TEXT" + ")";
        (createTable);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        ("DROP TABLE IF EXISTS " + TABLE_TOKENS);
        onCreate(db);
    }

    public void saveToken(String token) {
        SQLiteDatabase db = ();
        ContentValues values = new ContentValues();
        (COLUMN_TOKEN, token);
        (TABLE_TOKENS, null, values);
        ();
    }

    public String getToken() {
        String token = null;
        SQLiteDatabase db = ();
        Cursor cursor = (TABLE_TOKENS, new String[]{COLUMN_TOKEN}, null, null, null, null, null);
        if (cursor != null && ()) {
            token = ((COLUMN_TOKEN));
        }
        ();
        ();
        return token;
    }
}

2. Implementation in MainActivity

existMainActivity, we will useTokenDatabaseHelperTo store and read encrypted tokens.

Here is the complete code:

import ;
import .Base64;
import ;

import ;

import ;
import ;
import ;
import ;
import ;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private TokenDatabaseHelper dbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        (savedInstanceState);
        setContentView(.activity_main);

        // Initialize the database help class        dbHelper = new TokenDatabaseHelper(this);

        try {
            KeystoreManager keystoreManager = new KeystoreManager();
            // Generate key pairs (only call once on first startup)            ();

            // Encryption Token            String accessToken = "your_access_token_here";
            byte[] encryptedAccessToken = (accessToken);

            //Storage the encrypted token to the database            String encodedToken = (encryptedAccessToken, );
            (encodedToken);

            // Read Token from the database            String retrievedToken = ();
            if (retrievedToken != null) {
                byte[] retrievedEncryptedToken = (retrievedToken, );
                // Decrypt Token                String decryptedAccessToken = (retrievedEncryptedToken);
                (TAG, "Decrypted Token: " + decryptedAccessToken);
            }
        } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | UnrecoverableEntryException | InvalidAlgorithmParameterException e) {
            ();
        }
    }
}

3. Code description

  1. Encryption and storage Token

    • useKeystoreManagerEncryption Token.
    • Store the encrypted token (Base64 encoding) into the SQLite database.
  2. Read and decrypt Token

    • Read the encrypted token from the database.
    • Decrypt the token and print it out.
  3. TokenDatabaseHelper

    • ProvidedsaveTokenandgetTokenMethods, used to store and read Token data respectively.

4. Things to note

  • make sureKeystoreManagerClassicgenerateKeyencryptDataanddecryptDataThe method is implemented correctly.
  • DatabaseCOLUMN_TOKENThe field stores encrypted data encoded by Base64 to ensure that encoding and decoding are handled correctly during storage and reading.
  • If you need to support multiple token data, you cangetTokenAdd logic to the method, such as sorting by timestamp or specifying a specific token.

3. Encrypted and use internal file storage

If the token data is large or a more secure storage method is needed, it can be stored in internal storage. The internal storage is private and cannot be accessed by other applications.

//Storage to internal storageFile file = new File(getFilesDir(), "");
FileOutputStream fos = new FileOutputStream(file);
(encryptedAccessToken);
();

When reading from internal storage:

File file = new File(getFilesDir(), "");
FileInputStream fis = new FileInputStream(file);
byte[] encryptedAccessToken = new byte[(int) ()];
(encryptedAccessToken);
();

4. Cloud storage service

If you need to synchronize tokens across devices, you can consider using cloud storage services, such as Firebase, Dropbox, etc.

Sample code (using Firebase)

// Initialize the Firebase databaseFirebaseDatabase database = ();
DatabaseReference tokensRef = ("tokens");

//Storage Token("userToken").setValue(token);

// Get Token("userToken").addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        String token = ();
        // Use Token    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // Handle errors    }
});

Summarize

  • EncryptedSharedPreferences: Provide encryptionSharedPreferences, suitable for storing a small amount of sensitive data.
  • SQLCipher: Provides an encrypted SQLite database, suitable for scenarios where higher security is required.
  • SQLite database: Suitable for storing structured data and supports complex queries. It is recommended to encrypt it first in storage.
  • File storage: Suitable for storing simple text data, ensuring file permissions areMODE_PRIVATE. It is recommended to encrypt it first in storage.
  • SharedPreferences: Suitable for storing a small amount of data. It is recommended to encrypt it first in storage.
  • Cloud storage services: Suitable for synchronizing data across devices, but requires relying on third-party services.

The above is the detailed content of several methods of Token secure storage. For more information about Token secure storage, please pay attention to my other related articles!