// Path: lib/src/main/java/com/google/capillary/AuthModeUnavailableException.java
// public final class AuthModeUnavailableException extends CapillaryException {
// 
//   /**
//    * Creates a new {@link AuthModeUnavailableException} instance.
//    *
//    * @param msg the exception message.
//    */
//   public AuthModeUnavailableException(String msg) {
//     super(msg);
//   }
// }
// 
// Path: lib/src/main/java/com/google/capillary/NoSuchKeyException.java
// public final class NoSuchKeyException extends CapillaryException {
// 
//   /**
//    * Creates a new {@link NoSuchKeyException} object.
//    *
//    * @param msg the exception message.
//    */
//   public NoSuchKeyException(String msg) {
//     super(msg);
//   }
// }


import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.UserNotAuthenticatedException;
import com.google.capillary.AuthModeUnavailableException;
import com.google.capillary.NoSuchKeyException;
import com.google.capillary.internal.CapillaryCiphertext;
import com.google.crypto.tink.HybridDecrypt;
import com.google.protobuf.InvalidProtocolBufferException;
import java.security.GeneralSecurityException;
import java.security.UnrecoverableKeyException;
import java.util.List;
   * @param handler the Capillary handler instance.
   * @param extra the extra parameters to be passed back to the provided handler.
   */
  public synchronized void decrypt(byte[] ciphertext, CapillaryHandler handler, Object extra) {
    // Parse the given ciphertext bytes.
    CapillaryCiphertext capillaryCiphertext;
    try {
      capillaryCiphertext = CapillaryCiphertext.parseFrom(ciphertext);
    } catch (InvalidProtocolBufferException e) {
      handler.error(CapillaryHandlerErrorCode.MALFORMED_CIPHERTEXT, ciphertext, extra);
      return;
    }

    // Save the ciphertext for later if the decryption key is not ready.
    if (capillaryCiphertext.getIsAuthKey() && utils.isScreenLocked(context)) {
      ciphertextStorage.save(ciphertext);
      handler.authCiphertextSavedForLater(ciphertext, extra);
      return;
    }

    byte[] rawCiphertext = capillaryCiphertext.getCiphertext().toByteArray();
    byte[] data;

    // Attempt decryption.
    try {
      HybridDecrypt decrypter = keyManager.getDecrypter(
          capillaryCiphertext.getKeychainUniqueId(),
          capillaryCiphertext.getKeySerialNumber(),
          capillaryCiphertext.getIsAuthKey());
      data = decrypter.decrypt(rawCiphertext, null);
// Path: lib/src/main/java/com/google/capillary/AuthModeUnavailableException.java
// public final class AuthModeUnavailableException extends CapillaryException {
// 
//   /**
//    * Creates a new {@link AuthModeUnavailableException} instance.
//    *
//    * @param msg the exception message.
//    */
//   public AuthModeUnavailableException(String msg) {
//     super(msg);
//   }
// }
// 
// Path: lib/src/main/java/com/google/capillary/NoSuchKeyException.java
// public final class NoSuchKeyException extends CapillaryException {
// 
//   /**
//    * Creates a new {@link NoSuchKeyException} object.
//    *
//    * @param msg the exception message.
//    */
//   public NoSuchKeyException(String msg) {
//     super(msg);
//   }
// }


// Path: lib-android/src/main/java/com/google/capillary/android/DecrypterManager.java
import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.UserNotAuthenticatedException;
import com.google.capillary.AuthModeUnavailableException;
import com.google.capillary.NoSuchKeyException;
import com.google.capillary.internal.CapillaryCiphertext;
import com.google.crypto.tink.HybridDecrypt;
import com.google.protobuf.InvalidProtocolBufferException;
import java.security.GeneralSecurityException;
import java.security.UnrecoverableKeyException;
import java.util.List;

   * @param handler the Capillary handler instance.
   * @param extra the extra parameters to be passed back to the provided handler.
   */
  public synchronized void decrypt(byte[] ciphertext, CapillaryHandler handler, Object extra) {
    // Parse the given ciphertext bytes.
    CapillaryCiphertext capillaryCiphertext;
    try {
      capillaryCiphertext = CapillaryCiphertext.parseFrom(ciphertext);
    } catch (InvalidProtocolBufferException e) {
      handler.error(CapillaryHandlerErrorCode.MALFORMED_CIPHERTEXT, ciphertext, extra);
      return;
    }

    // Save the ciphertext for later if the decryption key is not ready.
    if (capillaryCiphertext.getIsAuthKey() && utils.isScreenLocked(context)) {
      ciphertextStorage.save(ciphertext);
      handler.authCiphertextSavedForLater(ciphertext, extra);
      return;
    }

    byte[] rawCiphertext = capillaryCiphertext.getCiphertext().toByteArray();
    byte[] data;

    // Attempt decryption.
    try {
      HybridDecrypt decrypter = keyManager.getDecrypter(
          capillaryCiphertext.getKeychainUniqueId(),
          capillaryCiphertext.getKeySerialNumber(),
          capillaryCiphertext.getIsAuthKey());
      data = decrypter.decrypt(rawCiphertext, null);
    } catch (AuthModeUnavailableException e) {