title: How to get key from keystore on successful fingerprint auth
body: <p>I'm creating an app where the user has two options to unlock their app, one is using a pin and the other is using a fingerprint. In order to use the fingerprint they must first set up a pin because this pin is the decryption key to get their encrypted details out of <code>SharedPreferences</code>.</p>
  
  <p>So i've followed this tutorial here: <a href="http://www.techotopia.com/index.php/An_Android_Fingerprint_Authentication_Tutorial#Accessing_the_Android_Keystore_and_KeyGenerator" rel="noreferrer">http://www.techotopia.com/index.php/An_Android_Fingerprint_Authentication_Tutorial#Accessing_the_Android_Keystore_and_KeyGenerator</a></p>
  
  <p>I've managed to get the app to read a fingerprint and say whether it is valid or not. But when the fingerprint is authorised I have no idea how to get that pin out of the Android keystore.</p>
  
  <p>Here is some code to demonstrate:</p>
  
  <pre><code>@Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
  
      keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
      fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
  
      if (!keyguardManager.isKeyguardSecure()) {
  
          Toast.makeText(this, "Lock screen security not enabled in Settings", Toast.LENGTH_LONG).show();
          return;
      }
  
      if (ActivityCompat.checkSelfPermission(this,
              Manifest.permission.USE_FINGERPRINT) !=
              PackageManager.PERMISSION_GRANTED) {
          Toast.makeText(this, "Fingerprint authentication permission not enabled", Toast.LENGTH_LONG).show();
  
          return;
      }
  
      if (!fingerprintManager.hasEnrolledFingerprints()) {
  
          // This happens when no fingerprints are registered.
          Toast.makeText(this, "Register at least one fingerprint in Settings", Toast.LENGTH_LONG).show();
          return;
      }
  
      generateKey();
  
      if (cipherInit()) {
          cryptoObject = new FingerprintManager.CryptoObject(cipher);
          FingerprintHandler helper = new FingerprintHandler(this);
  
          helper.startAuth(fingerprintManager, cryptoObject);
      }
  
  }
  
  protected void generateKey() {
      try {
          keyStore = KeyStore.getInstance("AndroidKeyStore");
      } catch (Exception e) {
          e.printStackTrace();
      }
  
      try {
          keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
      } catch (NoSuchAlgorithmException |
              NoSuchProviderException e) {
          throw new RuntimeException("Failed to get KeyGenerator instance", e);
      }
  
      try {
          keyStore.load(null);
          keyGenerator.init(new
                  KeyGenParameterSpec.Builder(KEY_NAME,
                  KeyProperties.PURPOSE_ENCRYPT |
                          KeyProperties.PURPOSE_DECRYPT)
                  .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                  .setUserAuthenticationRequired(true)
                  .setEncryptionPaddings(
                          KeyProperties.ENCRYPTION_PADDING_PKCS7)
                  .build());
          keyGenerator.generateKey();
      } catch (NoSuchAlgorithmException |
              InvalidAlgorithmParameterException
              | CertificateException | IOException e) {
          throw new RuntimeException(e);
      }
  }
  
  public boolean cipherInit() {
      try {
          cipher = Cipher.getInstance(
                  KeyProperties.KEY_ALGORITHM_AES + "/"
                          + KeyProperties.BLOCK_MODE_CBC + "/"
                          + KeyProperties.ENCRYPTION_PADDING_PKCS7);
      } catch (NoSuchAlgorithmException |
              NoSuchPaddingException e) {
          throw new RuntimeException("Failed to get Cipher", e);
      }
  
      try {
          keyStore.load(null);
          SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
                  null);
  
          cipher.init(Cipher.ENCRYPT_MODE, key);
          return true;
      } catch (KeyPermanentlyInvalidatedException e) {
          return false;
      } catch (KeyStoreException | CertificateException
              | UnrecoverableKeyException | IOException
              | NoSuchAlgorithmException | InvalidKeyException e) {
          throw new RuntimeException("Failed to init Cipher", e);
      }
  }
  </code></pre>
  
  <p>KEY_NAME is the key(pin) i'm trying to store (I think).</p>
  
  <p>Then in the <code>FingerprintHandler</code> class there is this method:</p>
  
  <pre><code>public void onAuthenticationSucceeded(
          FingerprintManager.AuthenticationResult result) {
  
      Toast.makeText(appContext,
              "Authentication succeeded.",
              Toast.LENGTH_LONG).show();
  
  }
  </code></pre>
  
  <p>But how do i get the key i want out of the <code>result</code> if at all?</p>