1. EncryptedSharedPreferences
EncryptedSharedPreferences
is an open source library forSharedPreferences
Encrypted 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
SQLCipher
is 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, useKeystoreManager
To 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
-
Generate a key pair:
- use
KeyGenParameterSpec
Define the properties of the key. - use
KeyGenerator
Generate key pairs and store them in the Keystore.
- use
-
Encrypted data:
- use
Cipher
Encrypt the data. - Returns the encrypted byte array.
- use
-
Decrypt the data:
- use
Cipher
Decrypt the encrypted data. - Returns the decrypted string.
- use
-
Store and read Tokens:
- Store the encrypted token in the application's private directory (e.g.
SharedPreferences
or file system). - When needed, the encrypted data is read and decrypted.
- Store the encrypted token in the application's private directory (e.g.
Safety advice
- Key Management: Ensure the security of the generation and use of keys and avoid key leakage.
- Store encrypted data: Store the encrypted token in the application's private directory to avoid being accessed by other applications.
- 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
SharedPreferences
It is a lightweight storage method in Android, suitable for storing a small amount of key-value pair data. You can store the encrypted tokens toSharedPreferences
middle.
//Storing encrypted tokens to SharedPreferencesSharedPreferences sharedPreferences = getSharedPreferences("MyAppPreferences", MODE_PRIVATE); editor = (); ("encryptedToken", (encryptedAccessToken, )); ();
fromSharedPreferences
When 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 useTokenDatabaseHelper
To 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
-
Encryption and storage Token
- use
KeystoreManager
Encryption Token. - Store the encrypted token (Base64 encoding) into the SQLite database.
- use
-
Read and decrypt Token
- Read the encrypted token from the database.
- Decrypt the token and print it out.
-
TokenDatabaseHelper
- Provided
saveToken
andgetToken
Methods, used to store and read Token data respectively.
- Provided
4. Things to note
- make sure
KeystoreManager
ClassicgenerateKey
、encryptData
anddecryptData
The method is implemented correctly. - Database
COLUMN_TOKEN
The 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 can
getToken
Add 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 encryption
SharedPreferences
, 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 are
MODE_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!