Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Add feature to store keys in Java Keystore (JKS) / Android Keystore (AKS) #43
Hi, this library looks very nice (unlike the native API), but I have some trouble storing the resulting keys.
I tried to store the keys in AndroidKeyStore for its hardware-backed security, but I am getting an exception saying I cannot store secretKeys at all. Is there a way how to achieve this?
keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); AesCbcWithIntegrity.SecretKeys keys = AesCbcWithIntegrity.generateKey(); KeyStore.SecretKeyEntry entryConfidential = new KeyStore.SecretKeyEntry(keys.getConfidentialityKey()); keyStore.setEntry(confidentialAlias, entryConfidential, null); //throws exception
this ↑ throws an exception
We would like to integrate the library more completely with the Android Keystore - (AKS), as there's a lot of subtle details around the Android version, we'd like our users to have easier access to good key storage.
This should be possible today - AES CBC is available in AKS after API level 23 (6.0 / marshmallow), and so is the HMAC algorithm we use, I believe. You can even generate the key inside the AKS, which probably provides an additional level of protection.
You can also do fun things like associate the key with the user's fingerprint so they have to present that biometric to unlock the key. This can add a nice extra layer of protection. The lock screen is also a great choice.
However, some caveats are that the API level 23+ might only be half of the Android phones out there, so you probably have to handle other methods of key storage to accommodate all users. Also, note the key destruction rules (eg. the user removes the lock screen, adds fingerprints, etc) to determine if they are suitable for your application. You wouldn't want the user to lose access to e.g. their photo collection because they decided to enroll another fingerprint.
As for your particular exception, I can only say we're not quite supporting this yet, but my best guess is that you're operating on a platform where AKS doesn't have AES support. You definitely need to check API level before trying this funciton.
PRs welcome for some saveKeyToAKS function or similar :)
You're absolutely right, I didn't realize the AKS does not support AES on API 22 for which I develop. So for now I will have to store the key on my own somewhere. Sorry for that.
As for PR for this, I will consider it after familiarizing myself more with this :)
Thanks for the response.
FYI, in case it's not clear, you can already use the Java KeyStore (JKS) for this type of workflow on all or nearly all platforms.
Also, if you're encrypting a key with e.g. a passphrase in JKS, you might get similar security if you generate a key from a password and use that directly, which we already provide. AKS is much nicer because the OS protects the storage.
I want to use AKS, but it does not support AES in API < 23:
I am trying to decrypt a text; after retrieving the keys (generated with this library) from the AndroidKeyStore I get a null pointer exception: (testing it on API 27),
cipherTextIvMac = AesCbcWithIntegrity.encrypt(text, keys);
When creating the key store entries to save in AndroidKeyStore, I use the following protection params:
new KeyProtection .Builder(KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT) .setUserAuthenticationRequired(false) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .build();
Any idea what I am doing wrong?