// Path: AndroidVault/vault/src/main/java/com/bottlerocketstudios/vault/EncryptionConstants.java
// public class EncryptionConstants {
//     public static final String AES_CIPHER = "AES";
//     public static final String BLOCK_MODE_CBC = "CBC";
//     public static final String ENCRYPTION_PADDING_PKCS5 = "PKCS5Padding";
//     public static final String ENCRYPTION_PADDING_PKCS7 = "PKCS7Padding";
// 
//     /**
//       * While this specifies PKCS5Padding and a 256 bit key, a historical artifact in the Sun encryption
//       * implementation interprets PKCS5 to be PKCS7 for block sizes over 8 bytes. In Android M this
//       * appears to have been corrected so that PKCS7Padding will work when instantiating a Cipher object.
//       */
//     public static final String AES_CBC_PADDED_TRANSFORM = AES_CIPHER + "/" + BLOCK_MODE_CBC + "/" + ENCRYPTION_PADDING_PKCS5;
//     public static final String AES_CBC_PADDED_TRANSFORM_ANDROID_M = AES_CIPHER + "/" + BLOCK_MODE_CBC + "/" + ENCRYPTION_PADDING_PKCS7;
//     public static final int AES_256_KEY_LENGTH_BITS = 256;
// 
//     public static final String DIGEST_SHA256 = "SHA256";
// 
//     public static final String ANDROID_KEY_STORE = "AndroidKeyStore";
// }
// 
// Path: AndroidVault/vault/src/main/java/com/bottlerocketstudios/vault/keys/generator/Aes256RandomKeyFactory.java
// public class Aes256RandomKeyFactory {
// 
//     /**
//      * Create a randomly generated AES256 key.
//      */
//     public static SecretKey createKey() {
//         RandomKeyGenerator keyGenerator = new RandomKeyGenerator(new PrngSaltGenerator(), EncryptionConstants.AES_256_KEY_LENGTH_BITS);
//         return keyGenerator.generateKey(EncryptionConstants.AES_CIPHER);
//     }
// }
// 
// Path: AndroidVault/vault/src/main/java/com/bottlerocketstudios/vault/keys/storage/KeyStorageType.java
// public enum KeyStorageType {
//     ANDROID_KEYSTORE,
//     ANDROID_KEYSTORE_AUTHENTICATED,
//     OBFUSCATED,
//     NOT_PERSISTENT
// }


import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.security.KeyPairGeneratorSpec;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import com.bottlerocketstudios.vault.EncryptionConstants;
import com.bottlerocketstudios.vault.keys.generator.Aes256RandomKeyFactory;
import com.bottlerocketstudios.vault.keys.storage.KeyStorageType;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.security.auth.x500.X500Principal;
    public synchronized SecretKey unwrap(byte[] blob, String wrappedKeyAlgorithm) throws GeneralSecurityException, IOException {

        AlgorithmParameterSpec spec = buildCipherAlgorithmParameterSpec();

        if (spec == null) {
            mCipher.init(Cipher.UNWRAP_MODE, getKeyPair().getPrivate());
        } else {
            mCipher.init(Cipher.UNWRAP_MODE, getKeyPair().getPrivate(), spec);
        }

        return (SecretKey) mCipher.unwrap(blob, wrappedKeyAlgorithm, Cipher.SECRET_KEY);
    }

    @Override
    public synchronized void clearKey(Context context) throws GeneralSecurityException, IOException {
        mKeyPair = null;
        final KeyStore keyStore = KeyStore.getInstance(EncryptionConstants.ANDROID_KEY_STORE);
        keyStore.load(null);
        keyStore.deleteEntry(mAlias);
    }

    public AlgorithmParameterSpec buildCipherAlgorithmParameterSpec() {
        return null;
    }

    public boolean testKey() throws GeneralSecurityException, IOException {
        KeyPair keyPair = getKeyPair();
        if (keyPair == null) return false;

        //Create a throwaway AES key to ensure that both wrap and unwrap operations work properly.
// Path: AndroidVault/vault/src/main/java/com/bottlerocketstudios/vault/EncryptionConstants.java
// public class EncryptionConstants {
//     public static final String AES_CIPHER = "AES";
//     public static final String BLOCK_MODE_CBC = "CBC";
//     public static final String ENCRYPTION_PADDING_PKCS5 = "PKCS5Padding";
//     public static final String ENCRYPTION_PADDING_PKCS7 = "PKCS7Padding";
// 
//     /**
//       * While this specifies PKCS5Padding and a 256 bit key, a historical artifact in the Sun encryption
//       * implementation interprets PKCS5 to be PKCS7 for block sizes over 8 bytes. In Android M this
//       * appears to have been corrected so that PKCS7Padding will work when instantiating a Cipher object.
//       */
//     public static final String AES_CBC_PADDED_TRANSFORM = AES_CIPHER + "/" + BLOCK_MODE_CBC + "/" + ENCRYPTION_PADDING_PKCS5;
//     public static final String AES_CBC_PADDED_TRANSFORM_ANDROID_M = AES_CIPHER + "/" + BLOCK_MODE_CBC + "/" + ENCRYPTION_PADDING_PKCS7;
//     public static final int AES_256_KEY_LENGTH_BITS = 256;
// 
//     public static final String DIGEST_SHA256 = "SHA256";
// 
//     public static final String ANDROID_KEY_STORE = "AndroidKeyStore";
// }
// 
// Path: AndroidVault/vault/src/main/java/com/bottlerocketstudios/vault/keys/generator/Aes256RandomKeyFactory.java
// public class Aes256RandomKeyFactory {
// 
//     /**
//      * Create a randomly generated AES256 key.
//      */
//     public static SecretKey createKey() {
//         RandomKeyGenerator keyGenerator = new RandomKeyGenerator(new PrngSaltGenerator(), EncryptionConstants.AES_256_KEY_LENGTH_BITS);
//         return keyGenerator.generateKey(EncryptionConstants.AES_CIPHER);
//     }
// }
// 
// Path: AndroidVault/vault/src/main/java/com/bottlerocketstudios/vault/keys/storage/KeyStorageType.java
// public enum KeyStorageType {
//     ANDROID_KEYSTORE,
//     ANDROID_KEYSTORE_AUTHENTICATED,
//     OBFUSCATED,
//     NOT_PERSISTENT
// }


// Path: AndroidVault/vault/src/main/java/com/bottlerocketstudios/vault/keys/wrapper/AbstractAndroidKeystoreSecretKeyWrapper.java
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.security.KeyPairGeneratorSpec;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import com.bottlerocketstudios.vault.EncryptionConstants;
import com.bottlerocketstudios.vault.keys.generator.Aes256RandomKeyFactory;
import com.bottlerocketstudios.vault.keys.storage.KeyStorageType;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.security.auth.x500.X500Principal;

    public synchronized SecretKey unwrap(byte[] blob, String wrappedKeyAlgorithm) throws GeneralSecurityException, IOException {

        AlgorithmParameterSpec spec = buildCipherAlgorithmParameterSpec();

        if (spec == null) {
            mCipher.init(Cipher.UNWRAP_MODE, getKeyPair().getPrivate());
        } else {
            mCipher.init(Cipher.UNWRAP_MODE, getKeyPair().getPrivate(), spec);
        }

        return (SecretKey) mCipher.unwrap(blob, wrappedKeyAlgorithm, Cipher.SECRET_KEY);
    }

    @Override
    public synchronized void clearKey(Context context) throws GeneralSecurityException, IOException {
        mKeyPair = null;
        final KeyStore keyStore = KeyStore.getInstance(EncryptionConstants.ANDROID_KEY_STORE);
        keyStore.load(null);
        keyStore.deleteEntry(mAlias);
    }

    public AlgorithmParameterSpec buildCipherAlgorithmParameterSpec() {
        return null;
    }

    public boolean testKey() throws GeneralSecurityException, IOException {
        KeyPair keyPair = getKeyPair();
        if (keyPair == null) return false;

        //Create a throwaway AES key to ensure that both wrap and unwrap operations work properly.
        SecretKey secretKey = Aes256RandomKeyFactory.createKey();