MiscPemGenerator
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.IO.Pem;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.IO;
namespace Org.BouncyCastle.OpenSsl
{
    public class MiscPemGenerator : PemObjectGenerator
    {
        private readonly object obj;
        private readonly string algorithm;
        private readonly char[] password;
        private readonly SecureRandom random;
        public MiscPemGenerator(object obj)
            : this(obj, null, null, null)
        {
        }
        public MiscPemGenerator(object obj, string algorithm, char[] password, SecureRandom random)
        {
            this.obj = obj;
            this.algorithm = algorithm;
            this.password = password;
            this.random = random;
        }
        private static PemObject CreatePemObject(object obj)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");
            AsymmetricCipherKeyPair asymmetricCipherKeyPair = obj as AsymmetricCipherKeyPair;
            if (asymmetricCipherKeyPair != null)
                return CreatePemObject(asymmetricCipherKeyPair.Private);
            PemObject pemObject = obj as PemObject;
            if (pemObject != null)
                return pemObject;
            PemObjectGenerator pemObjectGenerator = obj as PemObjectGenerator;
            if (pemObjectGenerator != null)
                return pemObjectGenerator.Generate();
            X509Certificate x509Certificate = obj as X509Certificate;
            string keyType;
            byte[] content;
            if (x509Certificate != null) {
                keyType = "CERTIFICATE";
                try {
                    content = x509Certificate.GetEncoded();
                } catch (CertificateEncodingException ex) {
                    throw new IOException("Cannot Encode object: " + ex.ToString());
                }
            } else {
                X509Crl x509Crl = obj as X509Crl;
                if (x509Crl != null) {
                    keyType = "X509 CRL";
                    try {
                        content = x509Crl.GetEncoded();
                    } catch (CrlException ex2) {
                        throw new IOException("Cannot Encode object: " + ex2.ToString());
                    }
                } else {
                    AsymmetricKeyParameter asymmetricKeyParameter = obj as AsymmetricKeyParameter;
                    if (asymmetricKeyParameter != null)
                        content = ((!asymmetricKeyParameter.IsPrivate) ? EncodePublicKey(asymmetricKeyParameter, out keyType) : EncodePrivateKey(asymmetricKeyParameter, out keyType));
                    else {
                        PrivateKeyInfo privateKeyInfo = obj as PrivateKeyInfo;
                        if (privateKeyInfo != null)
                            content = EncodePrivateKeyInfo(privateKeyInfo, out keyType);
                        else {
                            SubjectPublicKeyInfo subjectPublicKeyInfo = obj as SubjectPublicKeyInfo;
                            if (subjectPublicKeyInfo != null)
                                content = EncodePublicKeyInfo(subjectPublicKeyInfo, out keyType);
                            else {
                                X509V2AttributeCertificate x509V2AttributeCertificate = obj as X509V2AttributeCertificate;
                                if (x509V2AttributeCertificate != null) {
                                    keyType = "ATTRIBUTE CERTIFICATE";
                                    content = x509V2AttributeCertificate.GetEncoded();
                                } else {
                                    Pkcs8EncryptedPrivateKeyInfo pkcs8EncryptedPrivateKeyInfo = obj as Pkcs8EncryptedPrivateKeyInfo;
                                    if (pkcs8EncryptedPrivateKeyInfo != null) {
                                        keyType = "ENCRYPTED PRIVATE KEY";
                                        content = pkcs8EncryptedPrivateKeyInfo.GetEncoded();
                                    } else {
                                        Pkcs10CertificationRequest pkcs10CertificationRequest = obj as Pkcs10CertificationRequest;
                                        if (pkcs10CertificationRequest != null) {
                                            keyType = "CERTIFICATE REQUEST";
                                            content = pkcs10CertificationRequest.GetEncoded();
                                        } else {
                                            Org.BouncyCastle.Asn1.Cms.ContentInfo contentInfo = obj as Org.BouncyCastle.Asn1.Cms.ContentInfo;
                                            if (contentInfo != null) {
                                                keyType = "PKCS7";
                                                content = contentInfo.GetEncoded();
                                            } else {
                                                Org.BouncyCastle.Asn1.Pkcs.ContentInfo contentInfo2 = obj as Org.BouncyCastle.Asn1.Pkcs.ContentInfo;
                                                if (contentInfo2 == null)
                                                    throw new PemGenerationException("Object type not supported: " + Platform.GetTypeName(obj));
                                                keyType = "PKCS7";
                                                content = contentInfo2.GetEncoded();
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return new PemObject(keyType, content);
        }
        private static PemObject CreatePemObject(object obj, string algorithm, ReadOnlySpan<char> password, SecureRandom random)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");
            if (algorithm == null)
                throw new ArgumentNullException("algorithm");
            if (random == null)
                throw new ArgumentNullException("random");
            AsymmetricCipherKeyPair asymmetricCipherKeyPair = obj as AsymmetricCipherKeyPair;
            if (asymmetricCipherKeyPair != null)
                return CreatePemObject(asymmetricCipherKeyPair.Private, algorithm, password, random);
            string keyType = null;
            byte[] array = null;
            AsymmetricKeyParameter asymmetricKeyParameter = obj as AsymmetricKeyParameter;
            if (asymmetricKeyParameter != null && asymmetricKeyParameter.IsPrivate)
                array = EncodePrivateKey(asymmetricKeyParameter, out keyType);
            if (keyType == null || array == null)
                throw new PemGenerationException("Object type not supported: " + Platform.GetTypeName(obj));
            string text = algorithm.ToUpperInvariant();
            if (text == "DESEDE")
                text = "DES-EDE3-CBC";
            byte[] array2 = new byte[Platform.StartsWith(text, "AES-") ? 16 : 8];
            random.NextBytes(array2);
            byte[] content = PemUtilities.Crypt(true, array, password, text, array2);
            List<PemHeader> list = new List<PemHeader>(2);
            list.Add(new PemHeader("Proc-Type", "4,ENCRYPTED"));
            list.Add(new PemHeader("DEK-Info", text + "," + Hex.ToHexString(array2, true)));
            return new PemObject(keyType, list, content);
        }
        public PemObject Generate()
        {
            try {
                if (algorithm == null)
                    return CreatePemObject(obj);
                return CreatePemObject(obj, algorithm, password, random);
            } catch (IOException innerException) {
                throw new PemGenerationException("encoding exception", innerException);
            }
        }
        private static byte[] EncodePrivateKey(AsymmetricKeyParameter akp, out string keyType)
        {
            return EncodePrivateKeyInfo(PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp), out keyType);
        }
        private static byte[] EncodePrivateKeyInfo(PrivateKeyInfo info, out string keyType)
        {
            AlgorithmIdentifier privateKeyAlgorithm = info.PrivateKeyAlgorithm;
            DerObjectIdentifier derObjectIdentifier = privateKeyAlgorithm.Algorithm;
            if (derObjectIdentifier.Equals(PkcsObjectIdentifiers.RsaEncryption)) {
                keyType = "RSA PRIVATE KEY";
                return info.ParsePrivateKey().GetEncoded();
            }
            if (derObjectIdentifier.Equals(X9ObjectIdentifiers.IdECPublicKey) || derObjectIdentifier.Equals(CryptoProObjectIdentifiers.GostR3410x2001)) {
                keyType = "EC PRIVATE KEY";
                return info.ParsePrivateKey().GetEncoded();
            }
            if (derObjectIdentifier.Equals(X9ObjectIdentifiers.IdDsa) || derObjectIdentifier.Equals(OiwObjectIdentifiers.DsaWithSha1)) {
                keyType = "DSA PRIVATE KEY";
                DsaParameter instance = DsaParameter.GetInstance(privateKeyAlgorithm.Parameters);
                BigInteger value = DerInteger.GetInstance(info.ParsePrivateKey()).Value;
                BigInteger value2 = instance.G.ModPow(value, instance.P);
                return new DerSequence(DerInteger.Zero, new DerInteger(instance.P), new DerInteger(instance.Q), new DerInteger(instance.G), new DerInteger(value2), new DerInteger(value)).GetEncoded();
            }
            keyType = "PRIVATE KEY";
            return info.GetEncoded();
        }
        private static byte[] EncodePublicKey(AsymmetricKeyParameter akp, out string keyType)
        {
            return EncodePublicKeyInfo(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(akp), out keyType);
        }
        private static byte[] EncodePublicKeyInfo(SubjectPublicKeyInfo info, out string keyType)
        {
            keyType = "PUBLIC KEY";
            return info.GetEncoded();
        }
    }
}