Do’s |
Dont’s |
Classify data storage according to sensitivity and apply controls accordingly (To understand what information should be protected) |
Store any sensitive data on a mobile device where possible (Prevent data leak). |
When storing sensitive data on the device, use a file encryption API provided by the OS or other trusted source (Secure Cryptography) |
Write data to persistent memory accessible to other applications without encryption (Shared storage is untrusted) |
Use file encryption API’s which use a secret key protected by the device unlock code and deletable on remote wipe if available (Protect secret key) |
Including the keys in the same attacker-readable directory as the encrypted content (Can be used to decrypt data) |
Make use of remote wipe and kill switch APIs to remove sensitive information from the device in the event of theft or loss (Prevent data leak if the device is lost) |
Take screeenshots contain sensitive data (Avoid sensitive data is exposed through screenshots) |
Use a time based (expiry) type of control which will wipe sensitive data from the mobile device once the application has not communicated with its servers for a given period of time (Less chance to decrypt data by using brute force) |
Leak permission-protected data to other applications (Prevent other apps access sensitive data) |
Automatic application shutdown and/or lockout after X minutes of inactivity (Less chance of data leak) |
Allow third party keyboards to be used for inputs that may contain sensitive data (Prevent data leak) |
Verify that OS level storage encryption is enabled and the device is protected by a PIN or passphrase (Ensure data encryption by default) |
Backup or synchronize sensitive data (Prevent data leak) |
Restrict the data that is shared with other applications (Prevent other apps access sensitive data) |
Log sensitive information (Prevent data leak through logs) |
Nullify any variables that hold keys after use (Secure keys in memory) |
using immutable objects for sensitive keys or passwords such as in Android java.lang.String and use char array instead (Secure keys in memory) |
Restrict broadcast messages (e.g., Android Broadcast Intents) to authorized applications (Prevent other apps access sensitive data) |
|
Disable Auto Correction and Autosuggestion for inputs that contain sensitive data (Prevent data leak) |
|
Disable cut, copy and paste functionalities for inputs that may contain sensitive data or restrict the pasteboard to be accessible only from this application (Prevent data leak) |
|
Delete application caches on app termination (Prevent data leak) |
|
Clear cookies and data in Webview on app termination (Prevent data leak) |
|
Remove sesitive data from views when in background (Prevent data leak) |
We have implemented a secure storage feature in the sample mobile templates to allow users to manage secret notes. This feature is used to showcase the best practices around secure data storage.
The secret notes can be saved to either file system or database (SQLite). In both cases, the notes will be encrypted automatically when persisted, and decrypted automatically when loaded into the app.
Secret keys are being used to encrypt/decrypt the notes. To make sure the secret keys are securely persisted, in most cases, the OS’s keystore should be used to persist the secret key.
However, for Android, there is a difference between Android M and pre-Android M.
In Android M and later versions, the KeyStore API supports generating and persist secret key, so the implementation is quite straight forward:
link:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/crypto/AndroidMSecureKeyStore.java[role=include]
However, in pre-Android M, the KeyStore API only supports generating public/private key pairs, so we can’t persist the secret key using the keystore.
Instead, we will have to:
-
Generate the secret key without using the KeyStore
Generate Secretlink:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/crypto/PreAndroidMSecureKeyStore.java[role=include]
-
Generate a public/private key pair using the KeyStore
Generate Keypairlink:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/crypto/PreAndroidMSecureKeyStore.java[role=include]
-
Encrypt the generated secret key with the generated public key and persist the encrypted secret key using private SharedPreferences.
Encrypt Secretlink:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/crypto/PreAndroidMSecureKeyStore.java[role=include]
-
To load the secret key, the generated key pair needs to be loaded first, and then use the private key to decrypt the encrypted secret key.
Decrypt Secretlink:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/crypto/PreAndroidMSecureKeyStore.java[role=include]
The alternative option is to ask the user to provide a password. The password will be used to encrypt/decrypt the secret key. This does mean that the user will have to remember the password and enter it everytime when using the app.
RSA encryption/decryption is used to encrypt/decrypt the secret key. It can be used to encrypt/decrypt relatively small amount of data.
You can perform RSA encryption/decryption in Android like this:
link:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/crypto/RsaHelper.java[role=include]
link:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/crypto/RsaHelper.java[role=include]
Once we have the secret key, we can use it to encrypt/decrypt the content of the notes using AES.
You can perform data encryption/decryption in Android like this:
link:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/crypto/AesCrypto.java[role=include]
link:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/crypto/AesCrypto.java[role=include]
When a secret note is created, it can be persisted to the file system. We should encrypt the file when it is being persisted, and decrypt it when it is being loaded:
link:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/store/SecureFileNoteStore.java[role=include]
link:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/store/SecureFileNoteStore.java[role=include]
To securely persist data to the database, a library called SqlCipher is used. The library will automatically manage the encryption/decryption of the sqlite database file. It is easy to use, and requires minimum changes to the code.
To encrypt/decrypt the database, a password is required. You can ask the user to provide the password. In our sample application, we generated a random password and then protected using a public/private key pair. The password is saved to the private SharedPreferences.
link:https://raw.githubusercontent.com/aerogear/android-showcase-template/master/app/src/main/java/com/aerogear/androidshowcase/domain/store/sqlite/SqliteNoteStore.java[role=include]
The secret notes are being persisted using an encrypted Realm Mobile DB.
The Realm DB storing the notes must be initialised using the encryption key.
link:https://raw.githubusercontent.com/aerogear/ios-showcase-template/master/secure-ios-app/services/StorageService.swift[role=include]
The encryption key is stored in the iOS Keychain.
link:https://raw.githubusercontent.com/aerogear/ios-showcase-template/master/secure-ios-app/services/StorageService.swift[role=include]
When the application is initialised for the first time, a new encryption key is randomly generated.
link:https://raw.githubusercontent.com/aerogear/ios-showcase-template/master/secure-ios-app/services/StorageService.swift[role=include]
Interactions with the Realm DB are performed on background threads. Completion handlers are used to pass information to the view controllers on the Main thread.
List all the notes.
link:https://raw.githubusercontent.com/aerogear/ios-showcase-template/master/secure-ios-app/services/StorageService.swift[role=include]
Create an individual note.
link:https://raw.githubusercontent.com/aerogear/ios-showcase-template/master/secure-ios-app/services/StorageService.swift[role=include]
Read an individual note.
link:https://raw.githubusercontent.com/aerogear/ios-showcase-template/master/secure-ios-app/services/StorageService.swift[role=include]
Edit an individual note.
link:https://raw.githubusercontent.com/aerogear/ios-showcase-template/master/secure-ios-app/services/StorageService.swift[role=include]
Delete an individual note.
link:https://raw.githubusercontent.com/aerogear/ios-showcase-template/master/secure-ios-app/services/StorageService.swift[role=include]