// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.jcajce.provider.keystore.bcfks;

import org.bouncycastle.jcajce.util.BCJcaJceHelper;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.jcajce.provider.keystore.util.AdaptingKeyStoreSpi;
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
import org.bouncycastle.internal.asn1.nsri.NSRIObjectIdentifiers;
import org.bouncycastle.internal.asn1.ntt.NTTObjectIdentifiers;
import org.bouncycastle.internal.asn1.kisa.KISAObjectIdentifiers;
import org.bouncycastle.internal.asn1.oiw.OIWObjectIdentifiers;
import java.security.interfaces.RSAKey;
import java.security.interfaces.DSAKey;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jce.interfaces.ECKey;
import java.security.AlgorithmParameters;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.crypto.util.PBKDF2Config;
import org.bouncycastle.crypto.util.ScryptConfig;
import org.bouncycastle.crypto.util.PBKDFConfig;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.BadPaddingException;
import org.bouncycastle.asn1.bc.ObjectStoreData;
import org.bouncycastle.asn1.bc.ObjectDataSequence;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import org.bouncycastle.asn1.bc.EncryptedObjectStoreData;
import org.bouncycastle.jcajce.BCLoadStoreParameter;
import org.bouncycastle.asn1.bc.ObjectStore;
import org.bouncycastle.asn1.bc.ObjectStoreIntegrityCheck;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.jcajce.provider.keystore.util.ParameterUtil;
import org.bouncycastle.jcajce.BCFKSStoreParameter;
import java.security.KeyStore;
import javax.crypto.Mac;
import org.bouncycastle.asn1.bc.PbkdMacIntegrityCheck;
import java.security.GeneralSecurityException;
import java.security.Signature;
import org.bouncycastle.asn1.bc.SignatureCheck;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.crypto.generators.SCrypt;
import org.bouncycastle.internal.asn1.misc.ScryptParams;
import org.bouncycastle.internal.asn1.misc.MiscObjectIdentifiers;
import org.bouncycastle.crypto.PBEParametersGenerator;
import java.io.IOException;
import org.bouncycastle.util.Arrays;
import java.util.Iterator;
import java.util.Collection;
import java.util.HashSet;
import java.util.Enumeration;
import java.security.cert.CertificateEncodingException;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import java.security.SecureRandom;
import java.security.NoSuchProviderException;
import java.security.InvalidKeyException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.Cipher;
import org.bouncycastle.util.Strings;
import javax.crypto.SecretKey;
import org.bouncycastle.asn1.pkcs.PBES2Parameters;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.pkcs.EncryptionScheme;
import org.bouncycastle.internal.asn1.cms.CCMParameters;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import java.security.KeyStoreException;
import java.text.ParseException;
import java.security.cert.CertificateFactory;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.security.cert.X509Certificate;
import java.security.cert.Certificate;
import java.security.NoSuchAlgorithmException;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.bc.SecretKeyData;
import org.bouncycastle.asn1.bc.EncryptedSecretKeyData;
import java.security.UnrecoverableKeyException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
import org.bouncycastle.asn1.bc.EncryptedPrivateKeyData;
import java.security.Key;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import java.util.HashMap;
import java.util.Date;
import org.bouncycastle.asn1.pkcs.KeyDerivationFunc;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import java.security.PrivateKey;
import org.bouncycastle.asn1.bc.ObjectData;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import java.math.BigInteger;
import org.bouncycastle.jcajce.BCFKSLoadStoreParameter;
import java.security.PublicKey;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import java.util.Map;
import java.security.KeyStoreSpi;

class BcFKSKeyStoreSpi extends KeyStoreSpi
{
    private static final Map<String, ASN1ObjectIdentifier> oidMap;
    private static final Map<ASN1ObjectIdentifier, String> publicAlgMap;
    private PublicKey verificationKey;
    private BCFKSLoadStoreParameter.CertChainValidator validator;
    private static final BigInteger CERTIFICATE;
    private static final BigInteger PRIVATE_KEY;
    private static final BigInteger SECRET_KEY;
    private static final BigInteger PROTECTED_PRIVATE_KEY;
    private static final BigInteger PROTECTED_SECRET_KEY;
    private final JcaJceHelper helper;
    private final Map<String, ObjectData> entries;
    private final Map<String, PrivateKey> privateKeyCache;
    private AlgorithmIdentifier hmacAlgorithm;
    private KeyDerivationFunc hmacPkbdAlgorithm;
    private AlgorithmIdentifier signatureAlgorithm;
    private Date creationDate;
    private Date lastModifiedDate;
    private ASN1ObjectIdentifier storeEncryptionAlgorithm;
    
    private static String getPublicKeyAlg(final ASN1ObjectIdentifier asn1ObjectIdentifier) {
        final String s = BcFKSKeyStoreSpi.publicAlgMap.get(asn1ObjectIdentifier);
        if (s != null) {
            return s;
        }
        return asn1ObjectIdentifier.getId();
    }
    
    BcFKSKeyStoreSpi(final JcaJceHelper helper) {
        this.entries = new HashMap<String, ObjectData>();
        this.privateKeyCache = new HashMap<String, PrivateKey>();
        this.storeEncryptionAlgorithm = NISTObjectIdentifiers.id_aes256_CCM;
        this.helper = helper;
    }
    
    @Override
    public Key engineGetKey(final String str, final char[] array) throws NoSuchAlgorithmException, UnrecoverableKeyException {
        final ObjectData objectData = this.entries.get(str);
        if (objectData != null) {
            if (objectData.getType().equals(BcFKSKeyStoreSpi.PRIVATE_KEY) || objectData.getType().equals(BcFKSKeyStoreSpi.PROTECTED_PRIVATE_KEY)) {
                final PrivateKey privateKey = this.privateKeyCache.get(str);
                if (privateKey != null) {
                    return privateKey;
                }
                final EncryptedPrivateKeyInfo instance = EncryptedPrivateKeyInfo.getInstance(EncryptedPrivateKeyData.getInstance(objectData.getData()).getEncryptedPrivateKeyInfo());
                try {
                    final PrivateKeyInfo instance2 = PrivateKeyInfo.getInstance(this.decryptData("PRIVATE_KEY_ENCRYPTION", instance.getEncryptionAlgorithm(), array, instance.getEncryptedData()));
                    final PrivateKey generatePrivate = this.helper.createKeyFactory(getPublicKeyAlg(instance2.getPrivateKeyAlgorithm().getAlgorithm())).generatePrivate(new PKCS8EncodedKeySpec(instance2.getEncoded()));
                    this.privateKeyCache.put(str, generatePrivate);
                    return generatePrivate;
                }
                catch (final Exception ex) {
                    throw new UnrecoverableKeyException("BCFKS KeyStore unable to recover private key (" + str + "): " + ex.getMessage());
                }
            }
            if (objectData.getType().equals(BcFKSKeyStoreSpi.SECRET_KEY) || objectData.getType().equals(BcFKSKeyStoreSpi.PROTECTED_SECRET_KEY)) {
                final EncryptedSecretKeyData instance3 = EncryptedSecretKeyData.getInstance(objectData.getData());
                try {
                    final SecretKeyData instance4 = SecretKeyData.getInstance(this.decryptData("SECRET_KEY_ENCRYPTION", instance3.getKeyEncryptionAlgorithm(), array, instance3.getEncryptedKeyData()));
                    return this.helper.createSecretKeyFactory(instance4.getKeyAlgorithm().getId()).generateSecret(new SecretKeySpec(instance4.getKeyBytes(), instance4.getKeyAlgorithm().getId()));
                }
                catch (final Exception ex2) {
                    throw new UnrecoverableKeyException("BCFKS KeyStore unable to recover secret key (" + str + "): " + ex2.getMessage());
                }
            }
            throw new UnrecoverableKeyException("BCFKS KeyStore unable to recover secret key (" + str + "): type not recognized");
        }
        return null;
    }
    
    @Override
    public Certificate[] engineGetCertificateChain(final String s) {
        final ObjectData objectData = this.entries.get(s);
        if (objectData != null && (objectData.getType().equals(BcFKSKeyStoreSpi.PRIVATE_KEY) || objectData.getType().equals(BcFKSKeyStoreSpi.PROTECTED_PRIVATE_KEY))) {
            final org.bouncycastle.asn1.x509.Certificate[] certificateChain = EncryptedPrivateKeyData.getInstance(objectData.getData()).getCertificateChain();
            final X509Certificate[] array = new X509Certificate[certificateChain.length];
            for (int i = 0; i != array.length; ++i) {
                array[i] = (X509Certificate)this.decodeCertificate(certificateChain[i]);
            }
            return array;
        }
        return null;
    }
    
    @Override
    public Certificate engineGetCertificate(final String s) {
        final ObjectData objectData = this.entries.get(s);
        if (objectData != null) {
            if (objectData.getType().equals(BcFKSKeyStoreSpi.PRIVATE_KEY) || objectData.getType().equals(BcFKSKeyStoreSpi.PROTECTED_PRIVATE_KEY)) {
                return this.decodeCertificate(EncryptedPrivateKeyData.getInstance(objectData.getData()).getCertificateChain()[0]);
            }
            if (objectData.getType().equals(BcFKSKeyStoreSpi.CERTIFICATE)) {
                return this.decodeCertificate(objectData.getData());
            }
        }
        return null;
    }
    
    private Certificate decodeCertificate(final Object o) {
        if (this.helper != null) {
            try {
                return this.helper.createCertificateFactory("X.509").generateCertificate(new ByteArrayInputStream(org.bouncycastle.asn1.x509.Certificate.getInstance(o).getEncoded()));
            }
            catch (final Exception ex) {
                return null;
            }
        }
        try {
            return CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(org.bouncycastle.asn1.x509.Certificate.getInstance(o).getEncoded()));
        }
        catch (final Exception ex2) {
            return null;
        }
    }
    
    @Override
    public Date engineGetCreationDate(final String s) {
        final ObjectData objectData = this.entries.get(s);
        if (objectData != null) {
            try {
                return objectData.getLastModifiedDate().getDate();
            }
            catch (final ParseException ex) {
                return new Date();
            }
        }
        return null;
    }
    
    @Override
    public void engineSetKeyEntry(final String s, final Key key, final char[] array, final Certificate[] array2) throws KeyStoreException {
        final Date lastModifiedDate;
        Date creationDate = lastModifiedDate = new Date();
        final ObjectData objectData = this.entries.get(s);
        if (objectData != null) {
            creationDate = this.extractCreationDate(objectData, creationDate);
        }
        this.privateKeyCache.remove(s);
        Label_0846: {
            if (key instanceof PrivateKey) {
                if (array2 == null) {
                    throw new KeyStoreException("BCFKS KeyStore requires a certificate chain for private key storage.");
                }
                try {
                    final byte[] encoded = key.getEncoded();
                    final KeyDerivationFunc generatePkbdAlgorithmIdentifier = this.generatePkbdAlgorithmIdentifier(PKCSObjectIdentifiers.id_PBKDF2, 32);
                    final byte[] generateKey = this.generateKey(generatePkbdAlgorithmIdentifier, "PRIVATE_KEY_ENCRYPTION", (array != null) ? array : new char[0], 32);
                    EncryptedPrivateKeyInfo encryptedPrivateKeyInfo;
                    if (this.storeEncryptionAlgorithm.equals(NISTObjectIdentifiers.id_aes256_CCM)) {
                        final Cipher cipher = this.createCipher("AES/CCM/NoPadding", generateKey);
                        encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBES2, new PBES2Parameters(generatePkbdAlgorithmIdentifier, new EncryptionScheme(NISTObjectIdentifiers.id_aes256_CCM, CCMParameters.getInstance(cipher.getParameters().getEncoded())))), cipher.doFinal(encoded));
                    }
                    else {
                        encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBES2, new PBES2Parameters(generatePkbdAlgorithmIdentifier, new EncryptionScheme(NISTObjectIdentifiers.id_aes256_wrap_pad))), this.createCipher("AESKWP", generateKey).doFinal(encoded));
                    }
                    this.entries.put(s, new ObjectData(BcFKSKeyStoreSpi.PRIVATE_KEY, s, creationDate, lastModifiedDate, this.createPrivateKeySequence(encryptedPrivateKeyInfo, array2).getEncoded(), null));
                    break Label_0846;
                }
                catch (final Exception ex) {
                    throw new ExtKeyStoreException("BCFKS KeyStore exception storing private key: " + ex.toString(), ex);
                }
            }
            if (key instanceof SecretKey) {
                if (array2 != null) {
                    throw new KeyStoreException("BCFKS KeyStore cannot store certificate chain with secret key.");
                }
                try {
                    final byte[] encoded2 = key.getEncoded();
                    final KeyDerivationFunc generatePkbdAlgorithmIdentifier2 = this.generatePkbdAlgorithmIdentifier(PKCSObjectIdentifiers.id_PBKDF2, 32);
                    final byte[] generateKey2 = this.generateKey(generatePkbdAlgorithmIdentifier2, "SECRET_KEY_ENCRYPTION", (array != null) ? array : new char[0], 32);
                    final String upperCase = Strings.toUpperCase(key.getAlgorithm());
                    SecretKeyData secretKeyData;
                    if (upperCase.indexOf("AES") > -1) {
                        secretKeyData = new SecretKeyData(NISTObjectIdentifiers.aes, encoded2);
                    }
                    else {
                        final ASN1ObjectIdentifier asn1ObjectIdentifier = BcFKSKeyStoreSpi.oidMap.get(upperCase);
                        if (asn1ObjectIdentifier != null) {
                            secretKeyData = new SecretKeyData(asn1ObjectIdentifier, encoded2);
                        }
                        else {
                            final ASN1ObjectIdentifier asn1ObjectIdentifier2 = BcFKSKeyStoreSpi.oidMap.get(upperCase + "." + encoded2.length * 8);
                            if (asn1ObjectIdentifier2 == null) {
                                throw new KeyStoreException("BCFKS KeyStore cannot recognize secret key (" + upperCase + ") for storage.");
                            }
                            secretKeyData = new SecretKeyData(asn1ObjectIdentifier2, encoded2);
                        }
                    }
                    EncryptedSecretKeyData encryptedSecretKeyData;
                    if (this.storeEncryptionAlgorithm.equals(NISTObjectIdentifiers.id_aes256_CCM)) {
                        final Cipher cipher2 = this.createCipher("AES/CCM/NoPadding", generateKey2);
                        encryptedSecretKeyData = new EncryptedSecretKeyData(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBES2, new PBES2Parameters(generatePkbdAlgorithmIdentifier2, new EncryptionScheme(NISTObjectIdentifiers.id_aes256_CCM, CCMParameters.getInstance(cipher2.getParameters().getEncoded())))), cipher2.doFinal(secretKeyData.getEncoded()));
                    }
                    else {
                        encryptedSecretKeyData = new EncryptedSecretKeyData(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBES2, new PBES2Parameters(generatePkbdAlgorithmIdentifier2, new EncryptionScheme(NISTObjectIdentifiers.id_aes256_wrap_pad))), this.createCipher("AESKWP", generateKey2).doFinal(secretKeyData.getEncoded()));
                    }
                    this.entries.put(s, new ObjectData(BcFKSKeyStoreSpi.SECRET_KEY, s, creationDate, lastModifiedDate, encryptedSecretKeyData.getEncoded(), null));
                    break Label_0846;
                }
                catch (final Exception ex2) {
                    throw new ExtKeyStoreException("BCFKS KeyStore exception storing private key: " + ex2.toString(), ex2);
                }
            }
            throw new KeyStoreException("BCFKS KeyStore unable to recognize key.");
        }
        this.lastModifiedDate = lastModifiedDate;
    }
    
    private Cipher createCipher(final String s, final byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, NoSuchProviderException {
        final Cipher cipher = this.helper.createCipher(s);
        cipher.init(1, new SecretKeySpec(key, "AES"));
        return cipher;
    }
    
    private SecureRandom getDefaultSecureRandom() {
        return CryptoServicesRegistrar.getSecureRandom();
    }
    
    private EncryptedPrivateKeyData createPrivateKeySequence(final EncryptedPrivateKeyInfo encryptedPrivateKeyInfo, final Certificate[] array) throws CertificateEncodingException {
        final org.bouncycastle.asn1.x509.Certificate[] array2 = new org.bouncycastle.asn1.x509.Certificate[array.length];
        for (int i = 0; i != array.length; ++i) {
            array2[i] = org.bouncycastle.asn1.x509.Certificate.getInstance(array[i].getEncoded());
        }
        return new EncryptedPrivateKeyData(encryptedPrivateKeyInfo, array2);
    }
    
    @Override
    public void engineSetKeyEntry(final String s, final byte[] array, final Certificate[] array2) throws KeyStoreException {
        final Date lastModifiedDate;
        Date creationDate = lastModifiedDate = new Date();
        final ObjectData objectData = this.entries.get(s);
        if (objectData != null) {
            creationDate = this.extractCreationDate(objectData, creationDate);
        }
        if (array2 != null) {
            EncryptedPrivateKeyInfo instance;
            try {
                instance = EncryptedPrivateKeyInfo.getInstance(array);
            }
            catch (final Exception ex) {
                throw new ExtKeyStoreException("BCFKS KeyStore private key encoding must be an EncryptedPrivateKeyInfo.", ex);
            }
            try {
                this.privateKeyCache.remove(s);
                this.entries.put(s, new ObjectData(BcFKSKeyStoreSpi.PROTECTED_PRIVATE_KEY, s, creationDate, lastModifiedDate, this.createPrivateKeySequence(instance, array2).getEncoded(), null));
            }
            catch (final Exception ex2) {
                throw new ExtKeyStoreException("BCFKS KeyStore exception storing protected private key: " + ex2.toString(), ex2);
            }
        }
        else {
            try {
                this.entries.put(s, new ObjectData(BcFKSKeyStoreSpi.PROTECTED_SECRET_KEY, s, creationDate, lastModifiedDate, array, null));
            }
            catch (final Exception ex3) {
                throw new ExtKeyStoreException("BCFKS KeyStore exception storing protected private key: " + ex3.toString(), ex3);
            }
        }
        this.lastModifiedDate = lastModifiedDate;
    }
    
    @Override
    public void engineSetCertificateEntry(final String str, final Certificate certificate) throws KeyStoreException {
        final ObjectData objectData = this.entries.get(str);
        final Date lastModifiedDate;
        Date creationDate = lastModifiedDate = new Date();
        if (objectData != null) {
            if (!objectData.getType().equals(BcFKSKeyStoreSpi.CERTIFICATE)) {
                throw new KeyStoreException("BCFKS KeyStore already has a key entry with alias " + str);
            }
            creationDate = this.extractCreationDate(objectData, creationDate);
        }
        try {
            this.entries.put(str, new ObjectData(BcFKSKeyStoreSpi.CERTIFICATE, str, creationDate, lastModifiedDate, certificate.getEncoded(), null));
        }
        catch (final CertificateEncodingException ex) {
            throw new ExtKeyStoreException("BCFKS KeyStore unable to handle certificate: " + ex.getMessage(), ex);
        }
        this.lastModifiedDate = lastModifiedDate;
    }
    
    private Date extractCreationDate(final ObjectData objectData, Date date) {
        try {
            date = objectData.getCreationDate().getDate();
        }
        catch (final ParseException ex) {}
        return date;
    }
    
    @Override
    public void engineDeleteEntry(final String s) throws KeyStoreException {
        if (this.entries.get(s) == null) {
            return;
        }
        this.privateKeyCache.remove(s);
        this.entries.remove(s);
        this.lastModifiedDate = new Date();
    }
    
    @Override
    public Enumeration<String> engineAliases() {
        return new Enumeration() {
            final /* synthetic */ Iterator val$it = new HashSet(BcFKSKeyStoreSpi.this.entries.keySet()).iterator();
            
            @Override
            public boolean hasMoreElements() {
                return this.val$it.hasNext();
            }
            
            @Override
            public Object nextElement() {
                return this.val$it.next();
            }
        };
    }
    
    @Override
    public boolean engineContainsAlias(final String s) {
        if (s == null) {
            throw new NullPointerException("alias value is null");
        }
        return this.entries.containsKey(s);
    }
    
    @Override
    public int engineSize() {
        return this.entries.size();
    }
    
    @Override
    public boolean engineIsKeyEntry(final String s) {
        final ObjectData objectData = this.entries.get(s);
        if (objectData != null) {
            final BigInteger type = objectData.getType();
            return type.equals(BcFKSKeyStoreSpi.PRIVATE_KEY) || type.equals(BcFKSKeyStoreSpi.SECRET_KEY) || type.equals(BcFKSKeyStoreSpi.PROTECTED_PRIVATE_KEY) || type.equals(BcFKSKeyStoreSpi.PROTECTED_SECRET_KEY);
        }
        return false;
    }
    
    @Override
    public boolean engineIsCertificateEntry(final String s) {
        final ObjectData objectData = this.entries.get(s);
        return objectData != null && objectData.getType().equals(BcFKSKeyStoreSpi.CERTIFICATE);
    }
    
    @Override
    public String engineGetCertificateAlias(final Certificate certificate) {
        if (certificate == null) {
            return null;
        }
        byte[] encoded;
        try {
            encoded = certificate.getEncoded();
        }
        catch (final CertificateEncodingException ex) {
            return null;
        }
        for (final String s : this.entries.keySet()) {
            final ObjectData objectData = this.entries.get(s);
            if (objectData.getType().equals(BcFKSKeyStoreSpi.CERTIFICATE)) {
                if (Arrays.areEqual(objectData.getData(), encoded)) {
                    return s;
                }
                continue;
            }
            else {
                if (!objectData.getType().equals(BcFKSKeyStoreSpi.PRIVATE_KEY)) {
                    if (!objectData.getType().equals(BcFKSKeyStoreSpi.PROTECTED_PRIVATE_KEY)) {
                        continue;
                    }
                }
                try {
                    if (Arrays.areEqual(EncryptedPrivateKeyData.getInstance(objectData.getData()).getCertificateChain()[0].toASN1Primitive().getEncoded(), encoded)) {
                        return s;
                    }
                    continue;
                }
                catch (final IOException ex2) {}
            }
        }
        return null;
    }
    
    private byte[] generateKey(final KeyDerivationFunc keyDerivationFunc, final String s, final char[] array, final int n) throws IOException {
        final byte[] pkcs12PasswordToBytes = PBEParametersGenerator.PKCS12PasswordToBytes(array);
        final byte[] pkcs12PasswordToBytes2 = PBEParametersGenerator.PKCS12PasswordToBytes(s.toCharArray());
        int n2 = n;
        if (MiscObjectIdentifiers.id_scrypt.equals(keyDerivationFunc.getAlgorithm())) {
            final ScryptParams instance = ScryptParams.getInstance(keyDerivationFunc.getParameters());
            if (instance.getKeyLength() != null) {
                n2 = instance.getKeyLength().intValue();
            }
            else if (n2 == -1) {
                throw new IOException("no keyLength found in ScryptParams");
            }
            return SCrypt.generate(Arrays.concatenate(pkcs12PasswordToBytes, pkcs12PasswordToBytes2), instance.getSalt(), instance.getCostParameter().intValue(), instance.getBlockSize().intValue(), instance.getBlockSize().intValue(), n2);
        }
        if (!keyDerivationFunc.getAlgorithm().equals(PKCSObjectIdentifiers.id_PBKDF2)) {
            throw new IOException("BCFKS KeyStore: unrecognized MAC PBKD.");
        }
        final PBKDF2Params instance2 = PBKDF2Params.getInstance(keyDerivationFunc.getParameters());
        if (instance2.getKeyLength() != null) {
            n2 = instance2.getKeyLength().intValue();
        }
        else if (n2 == -1) {
            throw new IOException("no keyLength found in PBKDF2Params");
        }
        if (instance2.getPrf().getAlgorithm().equals(PKCSObjectIdentifiers.id_hmacWithSHA512)) {
            final PKCS5S2ParametersGenerator pkcs5S2ParametersGenerator = new PKCS5S2ParametersGenerator(new SHA512Digest());
            pkcs5S2ParametersGenerator.init(Arrays.concatenate(pkcs12PasswordToBytes, pkcs12PasswordToBytes2), instance2.getSalt(), instance2.getIterationCount().intValue());
            return ((KeyParameter)pkcs5S2ParametersGenerator.generateDerivedParameters(n2 * 8)).getKey();
        }
        if (instance2.getPrf().getAlgorithm().equals(NISTObjectIdentifiers.id_hmacWithSHA3_512)) {
            final PKCS5S2ParametersGenerator pkcs5S2ParametersGenerator2 = new PKCS5S2ParametersGenerator(new SHA3Digest(512));
            pkcs5S2ParametersGenerator2.init(Arrays.concatenate(pkcs12PasswordToBytes, pkcs12PasswordToBytes2), instance2.getSalt(), instance2.getIterationCount().intValue());
            return ((KeyParameter)pkcs5S2ParametersGenerator2.generateDerivedParameters(n2 * 8)).getKey();
        }
        throw new IOException("BCFKS KeyStore: unrecognized MAC PBKD PRF: " + instance2.getPrf().getAlgorithm());
    }
    
    private void verifySig(final ASN1Encodable asn1Encodable, final SignatureCheck signatureCheck, final PublicKey publicKey) throws GeneralSecurityException, IOException {
        final Signature signature = this.helper.createSignature(signatureCheck.getSignatureAlgorithm().getAlgorithm().getId());
        signature.initVerify(publicKey);
        signature.update(asn1Encodable.toASN1Primitive().getEncoded("DER"));
        if (!signature.verify(signatureCheck.getSignature().getOctets())) {
            throw new IOException("BCFKS KeyStore corrupted: signature calculation failed");
        }
    }
    
    private void verifyMac(final byte[] array, final PbkdMacIntegrityCheck pbkdMacIntegrityCheck, final char[] array2) throws NoSuchAlgorithmException, IOException, NoSuchProviderException {
        if (!Arrays.constantTimeAreEqual(this.calculateMac(array, pbkdMacIntegrityCheck.getMacAlgorithm(), pbkdMacIntegrityCheck.getPbkdAlgorithm(), array2), pbkdMacIntegrityCheck.getMac())) {
            throw new IOException("BCFKS KeyStore corrupted: MAC calculation failed");
        }
    }
    
    private byte[] calculateMac(final byte[] input, final AlgorithmIdentifier algorithmIdentifier, final KeyDerivationFunc keyDerivationFunc, final char[] array) throws NoSuchAlgorithmException, IOException, NoSuchProviderException {
        final String id = algorithmIdentifier.getAlgorithm().getId();
        final Mac mac = this.helper.createMac(id);
        try {
            mac.init(new SecretKeySpec(this.generateKey(keyDerivationFunc, "INTEGRITY_CHECK", (array != null) ? array : new char[0], -1), id));
        }
        catch (final InvalidKeyException ex) {
            throw new IOException("Cannot set up MAC calculation: " + ex.getMessage());
        }
        return mac.doFinal(input);
    }
    
    @Override
    public void engineStore(final KeyStore.LoadStoreParameter loadStoreParameter) throws CertificateException, NoSuchAlgorithmException, IOException {
        if (loadStoreParameter == null) {
            throw new IllegalArgumentException("'parameter' arg cannot be null");
        }
        if (loadStoreParameter instanceof BCFKSStoreParameter) {
            final BCFKSStoreParameter bcfksStoreParameter = (BCFKSStoreParameter)loadStoreParameter;
            final char[] password = ParameterUtil.extractPassword(loadStoreParameter);
            this.hmacPkbdAlgorithm = this.generatePkbdAlgorithmIdentifier(bcfksStoreParameter.getStorePBKDFConfig(), 64);
            this.engineStore(bcfksStoreParameter.getOutputStream(), password);
        }
        else if (loadStoreParameter instanceof BCFKSLoadStoreParameter) {
            final BCFKSLoadStoreParameter bcfksLoadStoreParameter = (BCFKSLoadStoreParameter)loadStoreParameter;
            if (bcfksLoadStoreParameter.getStoreSignatureKey() != null) {
                this.signatureAlgorithm = this.generateSignatureAlgId(bcfksLoadStoreParameter.getStoreSignatureKey(), bcfksLoadStoreParameter.getStoreSignatureAlgorithm());
                this.hmacPkbdAlgorithm = this.generatePkbdAlgorithmIdentifier(bcfksLoadStoreParameter.getStorePBKDFConfig(), 64);
                if (bcfksLoadStoreParameter.getStoreEncryptionAlgorithm() == BCFKSLoadStoreParameter.EncryptionAlgorithm.AES256_CCM) {
                    this.storeEncryptionAlgorithm = NISTObjectIdentifiers.id_aes256_CCM;
                }
                else {
                    this.storeEncryptionAlgorithm = NISTObjectIdentifiers.id_aes256_wrap_pad;
                }
                if (bcfksLoadStoreParameter.getStoreMacAlgorithm() == BCFKSLoadStoreParameter.MacAlgorithm.HmacSHA512) {
                    this.hmacAlgorithm = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA512, DERNull.INSTANCE);
                }
                else {
                    this.hmacAlgorithm = new AlgorithmIdentifier(NISTObjectIdentifiers.id_hmacWithSHA3_512, DERNull.INSTANCE);
                }
                final EncryptedObjectStoreData encryptedObjectStoreData = this.getEncryptedObjectStoreData(this.signatureAlgorithm, ParameterUtil.extractPassword(bcfksLoadStoreParameter));
                try {
                    final Signature signature = this.helper.createSignature(this.signatureAlgorithm.getAlgorithm().getId());
                    signature.initSign((PrivateKey)bcfksLoadStoreParameter.getStoreSignatureKey());
                    signature.update(encryptedObjectStoreData.getEncoded());
                    final X509Certificate[] storeCertificates = bcfksLoadStoreParameter.getStoreCertificates();
                    SignatureCheck signatureCheck;
                    if (storeCertificates != null) {
                        final org.bouncycastle.asn1.x509.Certificate[] array = new org.bouncycastle.asn1.x509.Certificate[storeCertificates.length];
                        for (int i = 0; i != array.length; ++i) {
                            array[i] = org.bouncycastle.asn1.x509.Certificate.getInstance(storeCertificates[i].getEncoded());
                        }
                        signatureCheck = new SignatureCheck(this.signatureAlgorithm, array, signature.sign());
                    }
                    else {
                        signatureCheck = new SignatureCheck(this.signatureAlgorithm, signature.sign());
                    }
                    bcfksLoadStoreParameter.getOutputStream().write(new ObjectStore(encryptedObjectStoreData, new ObjectStoreIntegrityCheck(signatureCheck)).getEncoded());
                    bcfksLoadStoreParameter.getOutputStream().flush();
                }
                catch (final GeneralSecurityException cause) {
                    throw new IOException("error creating signature: " + cause.getMessage(), cause);
                }
            }
            else {
                final char[] password2 = ParameterUtil.extractPassword(bcfksLoadStoreParameter);
                this.hmacPkbdAlgorithm = this.generatePkbdAlgorithmIdentifier(bcfksLoadStoreParameter.getStorePBKDFConfig(), 64);
                if (bcfksLoadStoreParameter.getStoreEncryptionAlgorithm() == BCFKSLoadStoreParameter.EncryptionAlgorithm.AES256_CCM) {
                    this.storeEncryptionAlgorithm = NISTObjectIdentifiers.id_aes256_CCM;
                }
                else {
                    this.storeEncryptionAlgorithm = NISTObjectIdentifiers.id_aes256_wrap_pad;
                }
                if (bcfksLoadStoreParameter.getStoreMacAlgorithm() == BCFKSLoadStoreParameter.MacAlgorithm.HmacSHA512) {
                    this.hmacAlgorithm = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA512, DERNull.INSTANCE);
                }
                else {
                    this.hmacAlgorithm = new AlgorithmIdentifier(NISTObjectIdentifiers.id_hmacWithSHA3_512, DERNull.INSTANCE);
                }
                this.engineStore(bcfksLoadStoreParameter.getOutputStream(), password2);
            }
        }
        else {
            if (!(loadStoreParameter instanceof BCLoadStoreParameter)) {
                throw new IllegalArgumentException("no support for 'parameter' of type " + loadStoreParameter.getClass().getName());
            }
            this.engineStore(((BCLoadStoreParameter)loadStoreParameter).getOutputStream(), ParameterUtil.extractPassword(loadStoreParameter));
        }
    }
    
    @Override
    public void engineStore(final OutputStream outputStream, final char[] array) throws IOException, NoSuchAlgorithmException, CertificateException {
        if (this.creationDate == null) {
            throw new IOException("KeyStore not initialized");
        }
        final EncryptedObjectStoreData encryptedObjectStoreData = this.getEncryptedObjectStoreData(this.hmacAlgorithm, array);
        if (MiscObjectIdentifiers.id_scrypt.equals(this.hmacPkbdAlgorithm.getAlgorithm())) {
            this.hmacPkbdAlgorithm = this.generatePkbdAlgorithmIdentifier(this.hmacPkbdAlgorithm, ScryptParams.getInstance(this.hmacPkbdAlgorithm.getParameters()).getKeyLength().intValue());
        }
        else {
            this.hmacPkbdAlgorithm = this.generatePkbdAlgorithmIdentifier(this.hmacPkbdAlgorithm, PBKDF2Params.getInstance(this.hmacPkbdAlgorithm.getParameters()).getKeyLength().intValue());
        }
        byte[] calculateMac;
        try {
            calculateMac = this.calculateMac(encryptedObjectStoreData.getEncoded(), this.hmacAlgorithm, this.hmacPkbdAlgorithm, array);
        }
        catch (final NoSuchProviderException ex) {
            throw new IOException("cannot calculate mac: " + ex.getMessage());
        }
        outputStream.write(new ObjectStore(encryptedObjectStoreData, new ObjectStoreIntegrityCheck(new PbkdMacIntegrityCheck(this.hmacAlgorithm, this.hmacPkbdAlgorithm, calculateMac))).getEncoded());
        outputStream.flush();
    }
    
    private EncryptedObjectStoreData getEncryptedObjectStoreData(final AlgorithmIdentifier algorithmIdentifier, final char[] array) throws IOException, NoSuchAlgorithmException {
        final ObjectData[] array2 = this.entries.values().toArray(new ObjectData[this.entries.size()]);
        final KeyDerivationFunc generatePkbdAlgorithmIdentifier = this.generatePkbdAlgorithmIdentifier(this.hmacPkbdAlgorithm, 32);
        final byte[] generateKey = this.generateKey(generatePkbdAlgorithmIdentifier, "STORE_ENCRYPTION", (array != null) ? array : new char[0], 32);
        final ObjectStoreData objectStoreData = new ObjectStoreData(algorithmIdentifier, this.creationDate, this.lastModifiedDate, new ObjectDataSequence(array2), null);
        EncryptedObjectStoreData encryptedObjectStoreData;
        try {
            if (this.storeEncryptionAlgorithm.equals(NISTObjectIdentifiers.id_aes256_CCM)) {
                final Cipher cipher = this.createCipher("AES/CCM/NoPadding", generateKey);
                encryptedObjectStoreData = new EncryptedObjectStoreData(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBES2, new PBES2Parameters(generatePkbdAlgorithmIdentifier, new EncryptionScheme(NISTObjectIdentifiers.id_aes256_CCM, CCMParameters.getInstance(cipher.getParameters().getEncoded())))), cipher.doFinal(objectStoreData.getEncoded()));
            }
            else {
                encryptedObjectStoreData = new EncryptedObjectStoreData(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBES2, new PBES2Parameters(generatePkbdAlgorithmIdentifier, new EncryptionScheme(NISTObjectIdentifiers.id_aes256_wrap_pad))), this.createCipher("AESKWP", generateKey).doFinal(objectStoreData.getEncoded()));
            }
        }
        catch (final NoSuchPaddingException ex) {
            throw new NoSuchAlgorithmException(ex.toString());
        }
        catch (final BadPaddingException ex2) {
            throw new IOException(ex2.toString());
        }
        catch (final IllegalBlockSizeException ex3) {
            throw new IOException(ex3.toString());
        }
        catch (final InvalidKeyException ex4) {
            throw new IOException(ex4.toString());
        }
        catch (final NoSuchProviderException ex5) {
            throw new IOException(ex5.toString());
        }
        return encryptedObjectStoreData;
    }
    
    @Override
    public void engineLoad(final KeyStore.LoadStoreParameter loadStoreParameter) throws CertificateException, NoSuchAlgorithmException, IOException {
        if (loadStoreParameter == null) {
            this.engineLoad(null, (char[])null);
        }
        else if (loadStoreParameter instanceof BCFKSLoadStoreParameter) {
            final BCFKSLoadStoreParameter bcfksLoadStoreParameter = (BCFKSLoadStoreParameter)loadStoreParameter;
            final char[] password = ParameterUtil.extractPassword(bcfksLoadStoreParameter);
            this.hmacPkbdAlgorithm = this.generatePkbdAlgorithmIdentifier(bcfksLoadStoreParameter.getStorePBKDFConfig(), 64);
            if (bcfksLoadStoreParameter.getStoreEncryptionAlgorithm() == BCFKSLoadStoreParameter.EncryptionAlgorithm.AES256_CCM) {
                this.storeEncryptionAlgorithm = NISTObjectIdentifiers.id_aes256_CCM;
            }
            else {
                this.storeEncryptionAlgorithm = NISTObjectIdentifiers.id_aes256_wrap_pad;
            }
            if (bcfksLoadStoreParameter.getStoreMacAlgorithm() == BCFKSLoadStoreParameter.MacAlgorithm.HmacSHA512) {
                this.hmacAlgorithm = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA512, DERNull.INSTANCE);
            }
            else {
                this.hmacAlgorithm = new AlgorithmIdentifier(NISTObjectIdentifiers.id_hmacWithSHA3_512, DERNull.INSTANCE);
            }
            this.verificationKey = (PublicKey)bcfksLoadStoreParameter.getStoreSignatureKey();
            this.validator = bcfksLoadStoreParameter.getCertChainValidator();
            this.signatureAlgorithm = this.generateSignatureAlgId(this.verificationKey, bcfksLoadStoreParameter.getStoreSignatureAlgorithm());
            final AlgorithmIdentifier hmacAlgorithm = this.hmacAlgorithm;
            final ASN1ObjectIdentifier storeEncryptionAlgorithm = this.storeEncryptionAlgorithm;
            final InputStream inputStream = bcfksLoadStoreParameter.getInputStream();
            this.engineLoad(inputStream, password);
            if (inputStream != null && (!this.isSimilarHmacPbkd(bcfksLoadStoreParameter.getStorePBKDFConfig(), this.hmacPkbdAlgorithm) || !storeEncryptionAlgorithm.equals(this.storeEncryptionAlgorithm))) {
                throw new IOException("configuration parameters do not match existing store");
            }
        }
        else {
            if (!(loadStoreParameter instanceof BCLoadStoreParameter)) {
                throw new IllegalArgumentException("no support for 'parameter' of type " + loadStoreParameter.getClass().getName());
            }
            this.engineLoad(((BCLoadStoreParameter)loadStoreParameter).getInputStream(), ParameterUtil.extractPassword(loadStoreParameter));
        }
    }
    
    private boolean isSimilarHmacPbkd(final PBKDFConfig pbkdfConfig, final KeyDerivationFunc keyDerivationFunc) {
        if (!pbkdfConfig.getAlgorithm().equals(keyDerivationFunc.getAlgorithm())) {
            return false;
        }
        if (MiscObjectIdentifiers.id_scrypt.equals(keyDerivationFunc.getAlgorithm())) {
            if (!(pbkdfConfig instanceof ScryptConfig)) {
                return false;
            }
            final ScryptConfig scryptConfig = (ScryptConfig)pbkdfConfig;
            final ScryptParams instance = ScryptParams.getInstance(keyDerivationFunc.getParameters());
            if (scryptConfig.getSaltLength() != instance.getSalt().length || scryptConfig.getBlockSize() != instance.getBlockSize().intValue() || scryptConfig.getCostParameter() != instance.getCostParameter().intValue() || scryptConfig.getParallelizationParameter() != instance.getParallelizationParameter().intValue()) {
                return false;
            }
        }
        else {
            if (!(pbkdfConfig instanceof PBKDF2Config)) {
                return false;
            }
            final PBKDF2Config pbkdf2Config = (PBKDF2Config)pbkdfConfig;
            final PBKDF2Params instance2 = PBKDF2Params.getInstance(keyDerivationFunc.getParameters());
            if (pbkdf2Config.getSaltLength() != instance2.getSalt().length || pbkdf2Config.getIterationCount() != instance2.getIterationCount().intValue()) {
                return false;
            }
        }
        return true;
    }
    
    @Override
    public void engineLoad(final InputStream inputStream, final char[] array) throws IOException, NoSuchAlgorithmException, CertificateException {
        this.entries.clear();
        this.privateKeyCache.clear();
        final Date date = null;
        this.creationDate = date;
        this.lastModifiedDate = date;
        this.hmacAlgorithm = null;
        if (inputStream == null) {
            final Date date2 = new Date();
            this.creationDate = date2;
            this.lastModifiedDate = date2;
            this.verificationKey = null;
            this.validator = null;
            this.hmacAlgorithm = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA512, DERNull.INSTANCE);
            this.hmacPkbdAlgorithm = this.generatePkbdAlgorithmIdentifier(PKCSObjectIdentifiers.id_PBKDF2, 64);
            return;
        }
        final ASN1InputStream asn1InputStream = new ASN1InputStream(inputStream);
        ObjectStore instance;
        try {
            instance = ObjectStore.getInstance(asn1InputStream.readObject());
        }
        catch (final Exception ex) {
            throw new IOException(ex.getMessage());
        }
        final ObjectStoreIntegrityCheck integrityCheck = instance.getIntegrityCheck();
        AlgorithmIdentifier algorithmIdentifier;
        if (integrityCheck.getType() == 0) {
            final PbkdMacIntegrityCheck instance2 = PbkdMacIntegrityCheck.getInstance(integrityCheck.getIntegrityCheck());
            this.hmacAlgorithm = instance2.getMacAlgorithm();
            this.hmacPkbdAlgorithm = instance2.getPbkdAlgorithm();
            algorithmIdentifier = this.hmacAlgorithm;
            try {
                this.verifyMac(instance.getStoreData().toASN1Primitive().getEncoded(), instance2, array);
            }
            catch (final NoSuchProviderException ex2) {
                throw new IOException(ex2.getMessage());
            }
        }
        else {
            if (integrityCheck.getType() != 1) {
                throw new IOException("BCFKS KeyStore unable to recognize integrity check.");
            }
            final SignatureCheck instance3 = SignatureCheck.getInstance(integrityCheck.getIntegrityCheck());
            algorithmIdentifier = instance3.getSignatureAlgorithm();
            try {
                final org.bouncycastle.asn1.x509.Certificate[] certificates = instance3.getCertificates();
                if (this.validator != null) {
                    if (certificates == null) {
                        throw new IOException("validator specified but no certifcates in store");
                    }
                    final CertificateFactory certificateFactory = this.helper.createCertificateFactory("X.509");
                    final X509Certificate[] array2 = new X509Certificate[certificates.length];
                    for (int i = 0; i != array2.length; ++i) {
                        array2[i] = (X509Certificate)certificateFactory.generateCertificate(new ByteArrayInputStream(certificates[i].getEncoded()));
                    }
                    if (!this.validator.isValid(array2)) {
                        throw new IOException("certificate chain in key store signature not valid");
                    }
                    this.verifySig(instance.getStoreData(), instance3, array2[0].getPublicKey());
                }
                else {
                    this.verifySig(instance.getStoreData(), instance3, this.verificationKey);
                }
            }
            catch (final GeneralSecurityException cause) {
                throw new IOException("error verifying signature: " + cause.getMessage(), cause);
            }
        }
        final ASN1Encodable storeData = instance.getStoreData();
        ObjectStoreData objectStoreData;
        if (storeData instanceof EncryptedObjectStoreData) {
            final EncryptedObjectStoreData encryptedObjectStoreData = (EncryptedObjectStoreData)storeData;
            objectStoreData = ObjectStoreData.getInstance(this.decryptData("STORE_ENCRYPTION", encryptedObjectStoreData.getEncryptionAlgorithm(), array, encryptedObjectStoreData.getEncryptedContent().getOctets()));
        }
        else {
            objectStoreData = ObjectStoreData.getInstance(storeData);
        }
        try {
            this.creationDate = objectStoreData.getCreationDate().getDate();
            this.lastModifiedDate = objectStoreData.getLastModifiedDate().getDate();
        }
        catch (final ParseException ex3) {
            throw new IOException("BCFKS KeyStore unable to parse store data information.");
        }
        if (!objectStoreData.getIntegrityAlgorithm().equals(algorithmIdentifier)) {
            throw new IOException("BCFKS KeyStore storeData integrity algorithm does not match store integrity algorithm.");
        }
        final Iterator<ASN1Encodable> iterator = objectStoreData.getObjectDataSequence().iterator();
        while (iterator.hasNext()) {
            final ObjectData instance4 = ObjectData.getInstance(iterator.next());
            this.entries.put(instance4.getIdentifier(), instance4);
        }
    }
    
    private byte[] decryptData(final String s, final AlgorithmIdentifier algorithmIdentifier, final char[] array, final byte[] input) throws IOException {
        if (!algorithmIdentifier.getAlgorithm().equals(PKCSObjectIdentifiers.id_PBES2)) {
            throw new IOException("BCFKS KeyStore cannot recognize protection algorithm.");
        }
        final PBES2Parameters instance = PBES2Parameters.getInstance(algorithmIdentifier.getParameters());
        final EncryptionScheme encryptionScheme = instance.getEncryptionScheme();
        try {
            Cipher cipher;
            AlgorithmParameters algorithmParameters;
            if (encryptionScheme.getAlgorithm().equals(NISTObjectIdentifiers.id_aes256_CCM)) {
                cipher = this.helper.createCipher("AES/CCM/NoPadding");
                algorithmParameters = this.helper.createAlgorithmParameters("CCM");
                algorithmParameters.init(CCMParameters.getInstance(encryptionScheme.getParameters()).getEncoded());
            }
            else {
                if (!encryptionScheme.getAlgorithm().equals(NISTObjectIdentifiers.id_aes256_wrap_pad)) {
                    throw new IOException("BCFKS KeyStore cannot recognize protection encryption algorithm.");
                }
                cipher = this.helper.createCipher("AESKWP");
                algorithmParameters = null;
            }
            cipher.init(2, new SecretKeySpec(this.generateKey(instance.getKeyDerivationFunc(), s, (array != null) ? array : new char[0], 32), "AES"), algorithmParameters);
            return cipher.doFinal(input);
        }
        catch (final IOException ex) {
            throw ex;
        }
        catch (final Exception ex2) {
            throw new IOException(ex2.toString());
        }
    }
    
    private AlgorithmIdentifier generateSignatureAlgId(final Key key, final BCFKSLoadStoreParameter.SignatureAlgorithm signatureAlgorithm) throws IOException {
        if (key == null) {
            return null;
        }
        if (key instanceof ECKey) {
            if (signatureAlgorithm == BCFKSLoadStoreParameter.SignatureAlgorithm.SHA512withECDSA) {
                return new AlgorithmIdentifier(X9ObjectIdentifiers.ecdsa_with_SHA512);
            }
            if (signatureAlgorithm == BCFKSLoadStoreParameter.SignatureAlgorithm.SHA3_512withECDSA) {
                return new AlgorithmIdentifier(NISTObjectIdentifiers.id_ecdsa_with_sha3_512);
            }
        }
        if (key instanceof DSAKey) {
            if (signatureAlgorithm == BCFKSLoadStoreParameter.SignatureAlgorithm.SHA512withDSA) {
                return new AlgorithmIdentifier(NISTObjectIdentifiers.dsa_with_sha512);
            }
            if (signatureAlgorithm == BCFKSLoadStoreParameter.SignatureAlgorithm.SHA3_512withDSA) {
                return new AlgorithmIdentifier(NISTObjectIdentifiers.id_dsa_with_sha3_512);
            }
        }
        if (key instanceof RSAKey) {
            if (signatureAlgorithm == BCFKSLoadStoreParameter.SignatureAlgorithm.SHA512withRSA) {
                return new AlgorithmIdentifier(PKCSObjectIdentifiers.sha512WithRSAEncryption, DERNull.INSTANCE);
            }
            if (signatureAlgorithm == BCFKSLoadStoreParameter.SignatureAlgorithm.SHA3_512withRSA) {
                return new AlgorithmIdentifier(NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_512, DERNull.INSTANCE);
            }
        }
        throw new IOException("unknown signature algorithm");
    }
    
    private KeyDerivationFunc generatePkbdAlgorithmIdentifier(final PBKDFConfig pbkdfConfig, final int n) {
        if (MiscObjectIdentifiers.id_scrypt.equals(pbkdfConfig.getAlgorithm())) {
            final ScryptConfig scryptConfig = (ScryptConfig)pbkdfConfig;
            final byte[] bytes = new byte[scryptConfig.getSaltLength()];
            this.getDefaultSecureRandom().nextBytes(bytes);
            return new KeyDerivationFunc(MiscObjectIdentifiers.id_scrypt, new ScryptParams(bytes, scryptConfig.getCostParameter(), scryptConfig.getBlockSize(), scryptConfig.getParallelizationParameter(), n));
        }
        final PBKDF2Config pbkdf2Config = (PBKDF2Config)pbkdfConfig;
        final byte[] bytes2 = new byte[pbkdf2Config.getSaltLength()];
        this.getDefaultSecureRandom().nextBytes(bytes2);
        return new KeyDerivationFunc(PKCSObjectIdentifiers.id_PBKDF2, new PBKDF2Params(bytes2, pbkdf2Config.getIterationCount(), n, pbkdf2Config.getPRF()));
    }
    
    private KeyDerivationFunc generatePkbdAlgorithmIdentifier(final KeyDerivationFunc keyDerivationFunc, final int n) {
        if (MiscObjectIdentifiers.id_scrypt.equals(keyDerivationFunc.getAlgorithm())) {
            final ScryptParams instance = ScryptParams.getInstance(keyDerivationFunc.getParameters());
            final byte[] bytes = new byte[instance.getSalt().length];
            this.getDefaultSecureRandom().nextBytes(bytes);
            return new KeyDerivationFunc(MiscObjectIdentifiers.id_scrypt, new ScryptParams(bytes, instance.getCostParameter(), instance.getBlockSize(), instance.getParallelizationParameter(), BigInteger.valueOf(n)));
        }
        final PBKDF2Params instance2 = PBKDF2Params.getInstance(keyDerivationFunc.getParameters());
        final byte[] bytes2 = new byte[instance2.getSalt().length];
        this.getDefaultSecureRandom().nextBytes(bytes2);
        return new KeyDerivationFunc(PKCSObjectIdentifiers.id_PBKDF2, new PBKDF2Params(bytes2, instance2.getIterationCount().intValue(), n, instance2.getPrf()));
    }
    
    private KeyDerivationFunc generatePkbdAlgorithmIdentifier(final ASN1ObjectIdentifier obj, final int n) {
        final byte[] bytes = new byte[64];
        this.getDefaultSecureRandom().nextBytes(bytes);
        if (PKCSObjectIdentifiers.id_PBKDF2.equals(obj)) {
            return new KeyDerivationFunc(PKCSObjectIdentifiers.id_PBKDF2, new PBKDF2Params(bytes, 51200, n, new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA512, DERNull.INSTANCE)));
        }
        throw new IllegalStateException("unknown derivation algorithm: " + obj);
    }
    
    static {
        oidMap = new HashMap<String, ASN1ObjectIdentifier>();
        publicAlgMap = new HashMap<ASN1ObjectIdentifier, String>();
        BcFKSKeyStoreSpi.oidMap.put("DESEDE", OIWObjectIdentifiers.desEDE);
        BcFKSKeyStoreSpi.oidMap.put("TRIPLEDES", OIWObjectIdentifiers.desEDE);
        BcFKSKeyStoreSpi.oidMap.put("TDEA", OIWObjectIdentifiers.desEDE);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA1", PKCSObjectIdentifiers.id_hmacWithSHA1);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA224", PKCSObjectIdentifiers.id_hmacWithSHA224);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA256", PKCSObjectIdentifiers.id_hmacWithSHA256);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA384", PKCSObjectIdentifiers.id_hmacWithSHA384);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA512", PKCSObjectIdentifiers.id_hmacWithSHA512);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA512/224", PKCSObjectIdentifiers.id_hmacWithSHA512_224);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA512/256", PKCSObjectIdentifiers.id_hmacWithSHA512_256);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA512(224)", PKCSObjectIdentifiers.id_hmacWithSHA512_224);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA512(256)", PKCSObjectIdentifiers.id_hmacWithSHA512_256);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA3-224", NISTObjectIdentifiers.id_hmacWithSHA3_224);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA3-256", NISTObjectIdentifiers.id_hmacWithSHA3_256);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA3-384", NISTObjectIdentifiers.id_hmacWithSHA3_384);
        BcFKSKeyStoreSpi.oidMap.put("HMACSHA3-512", NISTObjectIdentifiers.id_hmacWithSHA3_512);
        BcFKSKeyStoreSpi.oidMap.put("KMAC128", NISTObjectIdentifiers.id_Kmac128);
        BcFKSKeyStoreSpi.oidMap.put("KMAC256", NISTObjectIdentifiers.id_Kmac256);
        BcFKSKeyStoreSpi.oidMap.put("SEED", KISAObjectIdentifiers.id_seedCBC);
        BcFKSKeyStoreSpi.oidMap.put("CAMELLIA.128", NTTObjectIdentifiers.id_camellia128_cbc);
        BcFKSKeyStoreSpi.oidMap.put("CAMELLIA.192", NTTObjectIdentifiers.id_camellia192_cbc);
        BcFKSKeyStoreSpi.oidMap.put("CAMELLIA.256", NTTObjectIdentifiers.id_camellia256_cbc);
        BcFKSKeyStoreSpi.oidMap.put("ARIA.128", NSRIObjectIdentifiers.id_aria128_cbc);
        BcFKSKeyStoreSpi.oidMap.put("ARIA.192", NSRIObjectIdentifiers.id_aria192_cbc);
        BcFKSKeyStoreSpi.oidMap.put("ARIA.256", NSRIObjectIdentifiers.id_aria256_cbc);
        BcFKSKeyStoreSpi.publicAlgMap.put(PKCSObjectIdentifiers.rsaEncryption, "RSA");
        BcFKSKeyStoreSpi.publicAlgMap.put(X9ObjectIdentifiers.id_ecPublicKey, "EC");
        BcFKSKeyStoreSpi.publicAlgMap.put(OIWObjectIdentifiers.elGamalAlgorithm, "DH");
        BcFKSKeyStoreSpi.publicAlgMap.put(PKCSObjectIdentifiers.dhKeyAgreement, "DH");
        BcFKSKeyStoreSpi.publicAlgMap.put(X9ObjectIdentifiers.id_dsa, "DSA");
        CERTIFICATE = BigInteger.valueOf(0L);
        PRIVATE_KEY = BigInteger.valueOf(1L);
        SECRET_KEY = BigInteger.valueOf(2L);
        PROTECTED_PRIVATE_KEY = BigInteger.valueOf(3L);
        PROTECTED_SECRET_KEY = BigInteger.valueOf(4L);
    }
    
    public static class Def extends BcFKSKeyStoreSpi
    {
        public Def() {
            super(new DefaultJcaJceHelper());
        }
    }
    
    public static class DefCompat extends AdaptingKeyStoreSpi
    {
        public DefCompat() {
            super(new DefaultJcaJceHelper(), new BcFKSKeyStoreSpi(new DefaultJcaJceHelper()));
        }
    }
    
    public static class DefShared extends SharedKeyStoreSpi
    {
        public DefShared() {
            super(new DefaultJcaJceHelper());
        }
    }
    
    private static class SharedKeyStoreSpi extends BcFKSKeyStoreSpi implements PKCSObjectIdentifiers, X509ObjectIdentifiers
    {
        private final Map<String, byte[]> cache;
        private final byte[] seedKey;
        
        public SharedKeyStoreSpi(final JcaJceHelper jcaJceHelper) {
            super(jcaJceHelper);
            try {
                this.seedKey = new byte[32];
                jcaJceHelper.createSecureRandom("DEFAULT").nextBytes(this.seedKey);
            }
            catch (final GeneralSecurityException ex) {
                throw new IllegalArgumentException("can't create random - " + ex.toString());
            }
            this.cache = new HashMap<String, byte[]>();
        }
        
        @Override
        public void engineDeleteEntry(final String s) throws KeyStoreException {
            throw new KeyStoreException("delete operation not supported in shared mode");
        }
        
        @Override
        public void engineSetKeyEntry(final String s, final Key key, final char[] array, final Certificate[] array2) throws KeyStoreException {
            throw new KeyStoreException("set operation not supported in shared mode");
        }
        
        @Override
        public void engineSetKeyEntry(final String s, final byte[] array, final Certificate[] array2) throws KeyStoreException {
            throw new KeyStoreException("set operation not supported in shared mode");
        }
        
        @Override
        public void engineSetCertificateEntry(final String s, final Certificate certificate) throws KeyStoreException {
            throw new KeyStoreException("set operation not supported in shared mode");
        }
        
        @Override
        public Key engineGetKey(final String s, final char[] array) throws NoSuchAlgorithmException, UnrecoverableKeyException {
            byte[] calculateMac;
            try {
                calculateMac = this.calculateMac(s, array);
            }
            catch (final InvalidKeyException ex) {
                throw new UnrecoverableKeyException("unable to recover key (" + s + "): " + ex.getMessage());
            }
            if (this.cache.containsKey(s) && !Arrays.constantTimeAreEqual(this.cache.get(s), calculateMac)) {
                throw new UnrecoverableKeyException("unable to recover key (" + s + ")");
            }
            final Key engineGetKey = super.engineGetKey(s, array);
            if (engineGetKey != null && !this.cache.containsKey(s)) {
                this.cache.put(s, calculateMac);
            }
            return engineGetKey;
        }
        
        private byte[] calculateMac(final String s, final char[] array) throws NoSuchAlgorithmException, InvalidKeyException {
            byte[] array2;
            if (array != null) {
                array2 = Arrays.concatenate(Strings.toUTF8ByteArray(array), Strings.toUTF8ByteArray(s));
            }
            else {
                array2 = Arrays.concatenate(this.seedKey, Strings.toUTF8ByteArray(s));
            }
            return SCrypt.generate(array2, this.seedKey, 16384, 8, 1, 32);
        }
    }
    
    public static class DefSharedCompat extends AdaptingKeyStoreSpi
    {
        public DefSharedCompat() {
            super(new DefaultJcaJceHelper(), new BcFKSKeyStoreSpi(new DefaultJcaJceHelper()));
        }
    }
    
    private static class ExtKeyStoreException extends KeyStoreException
    {
        private final Throwable cause;
        
        ExtKeyStoreException(final String msg, final Throwable cause) {
            super(msg);
            this.cause = cause;
        }
        
        @Override
        public Throwable getCause() {
            return this.cause;
        }
    }
    
    public static class Std extends BcFKSKeyStoreSpi
    {
        public Std() {
            super(new BCJcaJceHelper());
        }
    }
    
    public static class StdCompat extends AdaptingKeyStoreSpi
    {
        public StdCompat() {
            super(new DefaultJcaJceHelper(), new BcFKSKeyStoreSpi(new BCJcaJceHelper()));
        }
    }
    
    public static class StdShared extends SharedKeyStoreSpi
    {
        public StdShared() {
            super(new BCJcaJceHelper());
        }
    }
    
    public static class StdSharedCompat extends AdaptingKeyStoreSpi
    {
        public StdSharedCompat() {
            super(new BCJcaJceHelper(), new BcFKSKeyStoreSpi(new BCJcaJceHelper()));
        }
    }
}
