// 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.content.SharedPreferences;
import android.support.annotation.VisibleForTesting;
import com.google.capillary.AuthModeUnavailableException;
import com.google.capillary.NoSuchKeyException;
import com.google.capillary.internal.CapillaryPublicKey;
import com.google.crypto.tink.HybridDecrypt;
import com.google.protobuf.ByteString;
import java.security.GeneralSecurityException;
import java.util.UUID;
/*
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.capillary.android;


/**
 * Encapsulates the management of Capillary keys.
 */
public abstract class KeyManager {

  private static final String AUTH_KEY_SERIAL_NUMBER_KEY = "current_auth_key_serial_number";
  private static final String NO_AUTH_KEY_SERIAL_NUMBER_KEY = "current_no_auth_key_serial_number";
  private static final String KEYCHAIN_UNIQUE_ID_KEY = "keychain_unique_id";

  final Context context;
  final String keychainId;

  private final Utils utils;
  private final SharedPreferences sharedPreferences;

  private DecrypterManager decrypterManager;

  /**
   * Creates a new {@link KeyManager} instance for managing Capillary keys.
   */
  KeyManager(Context context, Utils utils, String keychainId) {
    this.context = context;
    this.utils = utils;
    this.keychainId = keychainId;
    Context storageContext = utils.getDeviceProtectedStorageContext(context);
    String prefName = String.format("%s_%s_preferences", getClass().getCanonicalName(), keychainId);
    sharedPreferences = storageContext.getSharedPreferences(prefName, Context.MODE_PRIVATE);
  }

  /**
   * Provides a {@link DecrypterManager} backed by this {@link KeyManager}.
   *
   * @return the {@link DecrypterManager} instance.
   */
  public synchronized DecrypterManager getDecrypterManager() {
    if (decrypterManager == null) {
      CiphertextStorage ciphertextStorage = new CiphertextStorage(context, utils, keychainId);
      decrypterManager = new DecrypterManager(context, this, ciphertextStorage, utils);
    }
    return decrypterManager;
  }

  private static String toSerialNumberPrefKey(boolean isAuth) {
    return isAuth ? AUTH_KEY_SERIAL_NUMBER_KEY : NO_AUTH_KEY_SERIAL_NUMBER_KEY;
  }

  /**
   * Generates both auth and no-auth key pairs.
   *
   * @throws AuthModeUnavailableException if the user has not enabled authentication
   *     (i.e., a device with no screen lock).
   * @throws GeneralSecurityException if the key generation fails.
   */
// 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/KeyManager.java
import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.VisibleForTesting;
import com.google.capillary.AuthModeUnavailableException;
import com.google.capillary.NoSuchKeyException;
import com.google.capillary.internal.CapillaryPublicKey;
import com.google.crypto.tink.HybridDecrypt;
import com.google.protobuf.ByteString;
import java.security.GeneralSecurityException;
import java.util.UUID;

/*
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.capillary.android;


/**
 * Encapsulates the management of Capillary keys.
 */
public abstract class KeyManager {

  private static final String AUTH_KEY_SERIAL_NUMBER_KEY = "current_auth_key_serial_number";
  private static final String NO_AUTH_KEY_SERIAL_NUMBER_KEY = "current_no_auth_key_serial_number";
  private static final String KEYCHAIN_UNIQUE_ID_KEY = "keychain_unique_id";

  final Context context;
  final String keychainId;

  private final Utils utils;
  private final SharedPreferences sharedPreferences;

  private DecrypterManager decrypterManager;

  /**
   * Creates a new {@link KeyManager} instance for managing Capillary keys.
   */
  KeyManager(Context context, Utils utils, String keychainId) {
    this.context = context;
    this.utils = utils;
    this.keychainId = keychainId;
    Context storageContext = utils.getDeviceProtectedStorageContext(context);
    String prefName = String.format("%s_%s_preferences", getClass().getCanonicalName(), keychainId);
    sharedPreferences = storageContext.getSharedPreferences(prefName, Context.MODE_PRIVATE);
  }

  /**
   * Provides a {@link DecrypterManager} backed by this {@link KeyManager}.
   *
   * @return the {@link DecrypterManager} instance.
   */
  public synchronized DecrypterManager getDecrypterManager() {
    if (decrypterManager == null) {
      CiphertextStorage ciphertextStorage = new CiphertextStorage(context, utils, keychainId);
      decrypterManager = new DecrypterManager(context, this, ciphertextStorage, utils);
    }
    return decrypterManager;
  }

  private static String toSerialNumberPrefKey(boolean isAuth) {
    return isAuth ? AUTH_KEY_SERIAL_NUMBER_KEY : NO_AUTH_KEY_SERIAL_NUMBER_KEY;
  }

  /**
   * Generates both auth and no-auth key pairs.
   *
   * @throws AuthModeUnavailableException if the user has not enabled authentication
   *     (i.e., a device with no screen lock).
   * @throws GeneralSecurityException if the key generation fails.
   */
  public void generateKeyPairs() throws GeneralSecurityException, AuthModeUnavailableException {