Enhance the secure messaging app with the use of keystores to protect cryptographic keys.
- [Narrator] Well, you've learned how to generate a key and use it to encrypt our activation code, but we now need to think about how we store the key. The Android Keystore system protects key material from unauthorized use by preventing extraction of the key material from application processes and from the Android device as a whole. While the coding looks fairly straightforward, keys never actually get used in the application process. When an application performs cryptographic operations, the plain text, cipher text, key identifier, and message are all fed to a system process which performs the processing.
If the app's process is compromised, the attacker may be able to extract the app's key identifier, but it won't be able to extract their key material for use outside of the device. The Android Keystore specification construct also ensures that apps specify the authorized uses of their keys and then permits only those forms of use. This helps avoid misuse and inadvertent exposure of keys. You'll also want to think further about the encryption mechanism we use. In this time, I'll use a more secure mode of operation.
I'll select the Galois/Counter Mode, a popular and highly efficient mode. The Keystore is an Android mechanism for managing sensitive key material and can be used in three ways: to store a private key from an asymmetric keypad, to store a secret key, or to store a trusted third party certificate. In all cases, the use of a Keystore provides strong protection against unauthorized access. The key is known by an alias or name which we can use to invoke it when required.
From Android and onwards, API 23 in our coding, enhancements to the Keystore enable developers to have the Keystore create a random secret key, and with hardware backed cryptographic processes, this delivers an extremely secure solution. To start with, let's look at the build.gradle file, which specifies the minimum SDK level. As you can see, I've updated this to 23. Next I'll replace the key generation code and instead generate the key within the Keystore.
I'll make this a callable function called "Setup Keystore." Know that this is the enhancement that requires API 23 as a minimum, which we've adjusted in the build.gradle file. Let's look at this. For clarity, I'm not worried about specifically catching exceptions, but for production use, you'll want to cover them with some form of coding strategy. We declare a key generator for AES keys to be stored in the Android Keystore. We'll then initialize it to make an AES key to use for Galois/Counter Mode encryption.
We'll build the Keystore and generate the key. We'll change the start of our earlier code to create an instance of the Android Keystore and check whether we can find the key we want in it, and if not, we'll set a flag for this being a new key and call the Setup Routine to create it. I'm declaring a variable called "Key_Alias," which provides the alias name for use in the Keystore. This is the same alias that we used when creating a key using the Java Key tool. For our purposes, it's the name of the key. At this point, we've either found or created the key we want.
The next section of the code, starting with "SecretKey Key=No" reads the AES secret specification from the Keystore. If the key is new, the program now continues with calls to encrypt the activation code and store it in the private file. The GCM mode of operation uses an initialization vector. We'll get that form our cipher and store it in the private file so that we can use it in the decryption process. Note we've declared the variable IV, and then used the GetIV function to recover it after encryption.
We then write out the file and also the IV. Again we use Base64 in coding for the binary IV. We'll then recover the message and decrypt it. When we read back the encoded key and the IV from our private file, it's simple to use the buffer read form of file reader. We can directly read stream. We've now got our Base64 encoded key in the S code 64 string, and the Base64 encoded IV in the SIV string. We finish by decoding the key and using it to recover the encrypted activation code.
We do Base64 decoding, and then create a parameter specification for GCM mode using the recovered IV. We introduce this into the decryption and then we output the Toast to show the activation key. Let's run that on the Virtual Nexus 5X. We see the Keystore entry being created and the activation code being displayed after decryption. When we run that again, we don't see the key entry being created in the Keystore, because it already exists.
We've now added a more sophisticated form of encryption and also used the Android Keystore to provide protection for the secret key. This is a significant improvement in security.
- Understanding Android OS, app, and hardware security components
- Using the Trusted Execution Environment
- Developing Android apps with security in mind
- Analyzing existing applications
- Understanding Android vulnerabilities
- Securing Android apps
- Developing secure enterprise apps