The high level details of the encryption I'm using is:

  • AndroidKeyStore create/store RSA key
  • AES key is created and wrapped with RSA/ECB/PKCS1Padding
  • Encrypted AES is saved to disk.
  • Data is encrypted with AES/GCM/NoPadding and saved to disk.
  • Every encryption operation generates a new initialization vector from the platform secure random. Those are also saved to disk with their data.

The algorithm/transformation used are limited by the platform.

There are known issues on the AndroidKeyStore forgetting keys and I would like to save a known "lorem ipsum" data encrypted on first run. This known data would later be used during initialization to check the consistency of the keys and provide proper status for the system.

So my question: is it safe to store this known hard-coded value next to the real values, or with that I'm leaking everything and making it easy for someone to decrypt the real values?

  • $\begingroup$ As long as RSA padding creates randomness you should be fine. Do you have enough space for "magic word"? $\endgroup$
    – VovCA
    Aug 1 '18 at 18:01

Yes, it is secure to do this. Any cipher should be secure against known plaintext attacks after all.

However, if you're using RSA then the RSA decryption routine will already throw an exception during the PKCS#1 v1.5 unpadding, so storing the 'lorem ipsum" data is not necessary: the padding already acts as the "lorem ipsum" data.

If you still somehow require "lorem ipsum" for the symmetric encryption (in case Android loses track of the AES key as well) then you might as well use the "lorem ipsum" as Additional Data for the GCM algorithm. This data is included in the authentication tag but not in the ciphertext. If it is constant then you do not have to include it at all.

Note that you may want to use RSA-OAEP or RSA-KEM rather than PKCS#1 to avoid padding related attacks (RSA-OAEP should be directly available in Java / Android and is therefore recommended, but please do check with the KeyStore implementation and the targetted runtimes to be sure).

  • $\begingroup$ Thanks a lot for the answer. Unfortunately I can't directly reproduce the crashes, I only see them on the error logs. It all seems that RSA got extracted and AES unwrapped. And then on the moment of decrypting the data the crashes happen with AEADBadTagException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT. So what I'm doing is just running an actual data decryption earlier on to check if the real decryption will pass later on. $\endgroup$
    – Budius
    Aug 2 '18 at 7:28
  • $\begingroup$ This is a generic encrypted key-value pair store I'm doing, so the data sizes can vary wildly, so the RSA is being used only to wrap the AES key. Unfortunately the available KeyStore/Cipher/Transformation combinations available on Android prior to API-23 is very limited. I'll open a ticket for myself to check possible use of RSA-OAEP. $\endgroup$
    – Budius
    Aug 2 '18 at 7:28
  • $\begingroup$ Yeah, I know there are / were some issues with the KeyStore and the available algorithms from StackOverflow, hence the hint to test. Hopefully it is still a helpful answer. If you want to test the key AES key explicitly you could include a Key Check Value next to the ciphertext (a block of zero's encrypted with the AES key, then take the X leftmost bytes). However, note that this won't identify the right key if the KCV itself can be changed. AES/GCM is not affected by this because it starts the counter value at $IV \| 0^{31}1$. $\endgroup$
    – Maarten Bodewes
    Aug 2 '18 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.