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

package org.bouncycastle.openssl;

import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import java.util.Iterator;
import org.bouncycastle.util.encoders.Hex;
import java.util.StringTokenizer;
import org.bouncycastle.util.io.pem.PemHeader;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
import org.bouncycastle.asn1.ASN1BitString;
import org.bouncycastle.asn1.sec.ECPrivateKey;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Sequence;
import java.util.Collections;
import java.util.Set;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemObjectParser;
import java.io.IOException;
import java.util.HashMap;
import java.io.Reader;
import java.util.Map;
import org.bouncycastle.util.io.pem.PemReader;

public class PEMParser extends PemReader
{
    public static final String TYPE_CERTIFICATE_REQUEST = "CERTIFICATE REQUEST";
    public static final String TYPE_NEW_CERTIFICATE_REQUEST = "NEW CERTIFICATE REQUEST";
    public static final String TYPE_CERTIFICATE = "CERTIFICATE";
    public static final String TYPE_TRUSTED_CERTIFICATE = "TRUSTED CERTIFICATE";
    public static final String TYPE_X509_CERTIFICATE = "X509 CERTIFICATE";
    public static final String TYPE_X509_CRL = "X509 CRL";
    public static final String TYPE_PKCS7 = "PKCS7";
    public static final String TYPE_CMS = "CMS";
    public static final String TYPE_ATTRIBUTE_CERTIFICATE = "ATTRIBUTE CERTIFICATE";
    public static final String TYPE_EC_PARAMETERS = "EC PARAMETERS";
    public static final String TYPE_PUBLIC_KEY = "PUBLIC KEY";
    public static final String TYPE_RSA_PUBLIC_KEY = "RSA PUBLIC KEY";
    public static final String TYPE_RSA_PRIVATE_KEY = "RSA PRIVATE KEY";
    public static final String TYPE_DSA_PRIVATE_KEY = "DSA PRIVATE KEY";
    public static final String TYPE_EC_PRIVATE_KEY = "EC PRIVATE KEY";
    public static final String TYPE_ENCRYPTED_PRIVATE_KEY = "ENCRYPTED PRIVATE KEY";
    public static final String TYPE_PRIVATE_KEY = "PRIVATE KEY";
    protected final Map parsers;
    
    public PEMParser(final Reader reader) {
        super(reader);
        (this.parsers = new HashMap()).put("CERTIFICATE REQUEST", new PKCS10CertificationRequestParser());
        this.parsers.put("NEW CERTIFICATE REQUEST", new PKCS10CertificationRequestParser());
        this.parsers.put("CERTIFICATE", new X509CertificateParser());
        this.parsers.put("TRUSTED CERTIFICATE", new X509TrustedCertificateParser());
        this.parsers.put("X509 CERTIFICATE", new X509CertificateParser());
        this.parsers.put("X509 CRL", new X509CRLParser());
        this.parsers.put("PKCS7", new PKCS7Parser());
        this.parsers.put("CMS", new PKCS7Parser());
        this.parsers.put("ATTRIBUTE CERTIFICATE", new X509AttributeCertificateParser());
        this.parsers.put("EC PARAMETERS", new ECCurveParamsParser());
        this.parsers.put("PUBLIC KEY", new PublicKeyParser());
        this.parsers.put("RSA PUBLIC KEY", new RSAPublicKeyParser());
        this.parsers.put("RSA PRIVATE KEY", new KeyPairParser(new RSAKeyPairParser()));
        this.parsers.put("DSA PRIVATE KEY", new KeyPairParser(new DSAKeyPairParser()));
        this.parsers.put("EC PRIVATE KEY", new KeyPairParser(new ECDSAKeyPairParser()));
        this.parsers.put("ENCRYPTED PRIVATE KEY", new EncryptedPrivateKeyParser());
        this.parsers.put("PRIVATE KEY", new PrivateKeyParser());
    }
    
    public Object readObject() throws IOException {
        final PemObject pemObject = this.readPemObject();
        if (pemObject == null) {
            return null;
        }
        final String type = pemObject.getType();
        final Object value = this.parsers.get(type);
        if (value == null) {
            throw new IOException("unrecognised object: " + type);
        }
        return ((PemObjectParser)value).parseObject(pemObject);
    }
    
    public Set<String> getSupportedTypes() {
        return Collections.unmodifiableSet(this.parsers.keySet());
    }
    
    private static class DSAKeyPairParser implements PEMKeyPairParser
    {
        @Override
        public PEMKeyPair parse(final byte[] array) throws IOException {
            try {
                final ASN1Sequence instance = ASN1Sequence.getInstance(array);
                if (instance.size() != 6) {
                    throw new PEMException("malformed sequence in DSA private key");
                }
                final ASN1Integer instance2 = ASN1Integer.getInstance(instance.getObjectAt(1));
                final ASN1Integer instance3 = ASN1Integer.getInstance(instance.getObjectAt(2));
                final ASN1Integer instance4 = ASN1Integer.getInstance(instance.getObjectAt(3));
                return new PEMKeyPair(new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(instance2.getValue(), instance3.getValue(), instance4.getValue())), ASN1Integer.getInstance(instance.getObjectAt(4))), new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(instance2.getValue(), instance3.getValue(), instance4.getValue())), ASN1Integer.getInstance(instance.getObjectAt(5))));
            }
            catch (final IOException ex) {
                throw ex;
            }
            catch (final Exception ex2) {
                throw new PEMException("problem creating DSA private key: " + ex2.toString(), ex2);
            }
        }
    }
    
    private static class ECCurveParamsParser implements PemObjectParser
    {
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            try {
                final ASN1Primitive fromByteArray = ASN1Primitive.fromByteArray(pemObject.getContent());
                if (fromByteArray instanceof ASN1ObjectIdentifier) {
                    return fromByteArray;
                }
                if (fromByteArray instanceof ASN1Sequence) {
                    return X9ECParameters.getInstance(fromByteArray);
                }
                return null;
            }
            catch (final IOException ex) {
                throw ex;
            }
            catch (final Exception ex2) {
                throw new PEMException("exception extracting EC named curve: " + ex2.toString());
            }
        }
    }
    
    private static class ECDSAKeyPairParser implements PEMKeyPairParser
    {
        @Override
        public PEMKeyPair parse(final byte[] array) throws IOException {
            try {
                final ECPrivateKey instance = ECPrivateKey.getInstance(ASN1Sequence.getInstance(array));
                final AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, instance.getParametersObject());
                final PrivateKeyInfo privateKeyInfo = new PrivateKeyInfo(algorithmIdentifier, instance);
                final ASN1BitString publicKey = instance.getPublicKey();
                SubjectPublicKeyInfo subjectPublicKeyInfo = null;
                if (publicKey != null) {
                    subjectPublicKeyInfo = new SubjectPublicKeyInfo(algorithmIdentifier, publicKey.getBytes());
                }
                return new PEMKeyPair(subjectPublicKeyInfo, privateKeyInfo);
            }
            catch (final IOException ex) {
                throw ex;
            }
            catch (final Exception ex2) {
                throw new PEMException("problem creating EC private key: " + ex2.toString(), ex2);
            }
        }
    }
    
    private static class EncryptedPrivateKeyParser implements PemObjectParser
    {
        public EncryptedPrivateKeyParser() {
        }
        
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            try {
                return new PKCS8EncryptedPrivateKeyInfo(EncryptedPrivateKeyInfo.getInstance(pemObject.getContent()));
            }
            catch (final Exception ex) {
                throw new PEMException("problem parsing ENCRYPTED PRIVATE KEY: " + ex.toString(), ex);
            }
        }
    }
    
    private static class KeyPairParser implements PemObjectParser
    {
        private final PEMKeyPairParser pemKeyPairParser;
        
        public KeyPairParser(final PEMKeyPairParser pemKeyPairParser) {
            this.pemKeyPairParser = pemKeyPairParser;
        }
        
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            boolean b = false;
            String value = null;
            for (final PemHeader pemHeader : pemObject.getHeaders()) {
                if (pemHeader.getName().equals("Proc-Type") && pemHeader.getValue().equals("4,ENCRYPTED")) {
                    b = true;
                }
                else {
                    if (!pemHeader.getName().equals("DEK-Info")) {
                        continue;
                    }
                    value = pemHeader.getValue();
                }
            }
            final byte[] content = pemObject.getContent();
            try {
                if (b) {
                    final StringTokenizer stringTokenizer = new StringTokenizer(value, ",");
                    return new PEMEncryptedKeyPair(stringTokenizer.nextToken(), Hex.decode(stringTokenizer.nextToken()), content, this.pemKeyPairParser);
                }
                return this.pemKeyPairParser.parse(content);
            }
            catch (final IOException ex) {
                if (b) {
                    throw new PEMException("exception decoding - please check password and data.", ex);
                }
                throw new PEMException(ex.getMessage(), ex);
            }
            catch (final IllegalArgumentException ex2) {
                if (b) {
                    throw new PEMException("exception decoding - please check password and data.", ex2);
                }
                throw new PEMException(ex2.getMessage(), ex2);
            }
        }
    }
    
    private static class PKCS10CertificationRequestParser implements PemObjectParser
    {
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            try {
                return new PKCS10CertificationRequest(pemObject.getContent());
            }
            catch (final Exception ex) {
                throw new PEMException("problem parsing certrequest: " + ex.toString(), ex);
            }
        }
    }
    
    private static class PKCS7Parser implements PemObjectParser
    {
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            try {
                return ContentInfo.getInstance(pemObject.getContent());
            }
            catch (final Exception ex) {
                throw new PEMException("problem parsing PKCS7 object: " + ex.toString(), ex);
            }
        }
    }
    
    private static class PrivateKeyParser implements PemObjectParser
    {
        public PrivateKeyParser() {
        }
        
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            try {
                return PrivateKeyInfo.getInstance(pemObject.getContent());
            }
            catch (final Exception ex) {
                throw new PEMException("problem parsing PRIVATE KEY: " + ex.toString(), ex);
            }
        }
    }
    
    private static class PublicKeyParser implements PemObjectParser
    {
        public PublicKeyParser() {
        }
        
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            return SubjectPublicKeyInfo.getInstance(pemObject.getContent());
        }
    }
    
    private static class RSAKeyPairParser implements PEMKeyPairParser
    {
        @Override
        public PEMKeyPair parse(final byte[] array) throws IOException {
            try {
                final ASN1Sequence instance = ASN1Sequence.getInstance(array);
                if (instance.size() != 9) {
                    throw new PEMException("malformed sequence in RSA private key");
                }
                final RSAPrivateKey instance2 = RSAPrivateKey.getInstance(instance);
                final RSAPublicKey rsaPublicKey = new RSAPublicKey(instance2.getModulus(), instance2.getPublicExponent());
                final AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);
                return new PEMKeyPair(new SubjectPublicKeyInfo(algorithmIdentifier, rsaPublicKey), new PrivateKeyInfo(algorithmIdentifier, instance2));
            }
            catch (final IOException ex) {
                throw ex;
            }
            catch (final Exception ex2) {
                throw new PEMException("problem creating RSA private key: " + ex2.toString(), ex2);
            }
        }
    }
    
    private static class RSAPublicKeyParser implements PemObjectParser
    {
        public RSAPublicKeyParser() {
        }
        
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            try {
                return new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), RSAPublicKey.getInstance(pemObject.getContent()));
            }
            catch (final IOException ex) {
                throw ex;
            }
            catch (final Exception ex2) {
                throw new PEMException("problem extracting key: " + ex2.toString(), ex2);
            }
        }
    }
    
    private static class X509AttributeCertificateParser implements PemObjectParser
    {
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            return new X509AttributeCertificateHolder(pemObject.getContent());
        }
    }
    
    private static class X509CRLParser implements PemObjectParser
    {
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            try {
                return new X509CRLHolder(pemObject.getContent());
            }
            catch (final Exception ex) {
                throw new PEMException("problem parsing cert: " + ex.toString(), ex);
            }
        }
    }
    
    private static class X509CertificateParser implements PemObjectParser
    {
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            try {
                return new X509CertificateHolder(pemObject.getContent());
            }
            catch (final Exception ex) {
                throw new PEMException("problem parsing cert: " + ex.toString(), ex);
            }
        }
    }
    
    private static class X509TrustedCertificateParser implements PemObjectParser
    {
        @Override
        public Object parseObject(final PemObject pemObject) throws IOException {
            try {
                return new X509TrustedCertificateBlock(pemObject.getContent());
            }
            catch (final Exception ex) {
                throw new PEMException("problem parsing cert: " + ex.toString(), ex);
            }
        }
    }
}
