title: Using AES with AndroidKeyStore
body: <p>Android M provides AES support via the AndroidKeyStore however I can not find any combination of generating a key that provides a method of full encryption and decryption without a user password/device locking. It appears that my current approach is appropriate for these requirements as the key store is storing my key, I can load the key and perform encryption and in the case that I hold onto the IV from the encryption process I can decrypt the data.</p>
  
  <p>Unfortunately in the real world use case I can not hold onto the IV for decryption at a later time without writing it to disk, maybe this is what I should be doing? </p>
  
  <p>I have glanced at the updated key store and related testing in the SDK but was unable to find any test cases I could use as example. The examples also seem to be devoid of actually using AndroidKeyStore generated SecretKeys without tying them to device locking/finger prints.</p>
  
  <p>I have created a repository to try and highlight what I have done along with some comments explaining where my issue is. The relevant code is also included below.</p>
  
  <p>For clarity, my question is simply how can I generate an AndroidKeyStore backed AES SecretKey that allows me to encrypt and decrypt via cipher input/output streams without writing the IV to disk or using the fingerprint/device locking approaches?</p>
  
  <p><a href="https://github.com/ToxicBakery/AES-Testing/blob/master/app/src/androidTest/java/com/toxicbakery/app/aes/AesTest.java" rel="nofollow">https://github.com/ToxicBakery/AES-Testing/blob/master/app/src/androidTest/java/com/toxicbakery/app/aes/AesTest.java</a></p>
  
  <pre><code>    final String suchAlphabet = "abcdefghijklmnopqrstuvwxyz";
  
      KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
      keyStore.load(null);
  
      /*
      KEY GENERATION
       */
  
      // Define the key spec
      KeyGenParameterSpec aesSpec = new KeyGenParameterSpec.Builder(ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
              .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
              .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
              .setKeySize(128)
              .build();
  
      // Create the secret key in the key store
      KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
      keyGenerator.init(aesSpec);
      keyGenerator.generateKey();
  
      Cipher cipher;
      SecretKey secretKey;
  
      /*
      ENCRYPTION
       */
  
      // Load the secret key and encrypt
      secretKey = ((KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null)).getSecretKey();
      cipher = Cipher.getInstance(TRANSFORMATION);
      cipher.init(Cipher.ENCRYPT_MODE, secretKey);
  
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher);
      cipherOutputStream.write(suchAlphabet.getBytes());
      cipherOutputStream.flush();
      cipherOutputStream.close();
  
      /*
      DECRYPTION
       */
  
      // Load the secret key and decrypt
      secretKey = ((KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null)).getSecretKey();
  
      // The following two lines attempt to represent real world usage in that the previous line loaded
      // the key from the store and the next two lines attempt to create the cipher and then initialize
      // the cipher such that an IV can be extracted as it does not seem that you can use the spec or the
      // parameters. Interestingly, the following two lines only 'half' such that a-p fail to decrypt and
      // q-z decrypt successfully 100% of the time. Leaving the lines commented results an in a successful
      // decryption of the alphabet but this is not a usable scenario
      //
      //        cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
      //        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
  
      IvParameterSpec ivParameterSpec = new IvParameterSpec(cipher.getIV());
      cipher = Cipher.getInstance(TRANSFORMATION);
      cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
  
      byte[] in = new byte[suchAlphabet.getBytes().length];
      ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
      CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
      IOUtils.readFully(cipherInputStream, in);
      cipherInputStream.close();
  
      /*
      VERIFY
       */
  
      String muchWow = new String(in);
      assertEquals(suchAlphabet, muchWow);
  </code></pre>