Esempio n. 1
0
        /**
         * generate a signature for the message we've been loaded with using
         * the key we were initialised with.
         */
        public byte[] generateSignature()
        {
            if (forSigning)
            {
                MemoryStream        bOut = new MemoryStream();
                DEROutputStream     dOut = new DEROutputStream(bOut);
                ASN1EncodableVector v    = new ASN1EncodableVector();

                byte[] dig = new byte[digest.getDigestSize()];
                digest.doFinal(dig, 0);

                BigInteger[] sig = dsaSigner.generateSignature(dig);

                v.add(new DERInteger(sig[0]));
                v.add(new DERInteger(sig[1]));

                dOut.writeObject(new DERSequence(v));
                dOut.Flush();

                byte[] output = bOut.ToArray();
                dOut.Close();
                return(output);
            }
            throw new Exception("DSADigestSigner initialised for verification..");
        }
Esempio n. 2
0
        /// <summary>
        /// Return the DER encoded TBSCertificate data.
        /// This is the certificate component less the signature.
        /// To get the whole certificate call the getEncoded() member.
        /// </summary>
        /// <returns>A byte array containing the DER encoded Certificate component.</returns>

        public byte[] getTBSCertificate()
        {
            MemoryStream    bOut = new MemoryStream();
            DEROutputStream dOut = new DEROutputStream(bOut);

            dOut.writeObject(xStruct.getTBSCertificate());
            return(bOut.ToArray());
        }
Esempio n. 3
0
        /// <summary>
        /// Get the DER Encoded PKCS10 Certification Request.
        /// </summary>
        /// <returns>A byte array.</returns>
        public byte[] getEncoded()
        {
            MemoryStream    mStr   = new MemoryStream();
            DEROutputStream derOut = new DEROutputStream(mStr);

            derOut.writeObject(new CertificationRequest(reqInfo, sigAlgId, sigBits));
            derOut.Flush();
            byte[] _out = mStr.ToArray();
            mStr.Close();
            return(_out);
        }
Esempio n. 4
0
        /// <summary>
        /// Instanciate a PKCS10CertificationRequest object with the necessary credentials.
        /// </summary>
        ///<param name="signatureAlgorithm">Name of Sig Alg.</param>
        /// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
        /// <param name="key">Public Key to be included in cert reqest.</param>
        /// <param name="attributes">ASN1Set of Attributes.</param>
        /// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
        public PKCS10CertificationRequest(String signatureAlgorithm,
                                          X509Name subject,
                                          AsymmetricKeyParameter key,
                                          ASN1Set attributes,
                                          AsymmetricKeyParameter signingKey)

        {
            DERObjectIdentifier sigOID = SignerUtil.getObjectIdentifier(signatureAlgorithm.ToUpper());

            if (sigOID == null)
            {
                throw new ArgumentException("Unknown signature type requested");
            }

            if (subject == null)
            {
                throw new ArgumentException("subject must not be null");
            }

            if (key == null)
            {
                throw new ArgumentException("public key must not be null");
            }



            this.sigAlgId = new AlgorithmIdentifier(sigOID, null);

            SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key);


            this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes);

            Signer sig = null;

            // Create appropriate Signature.
            sig = SignerUtil.getSigner(sigAlgId.getObjectId());

            sig.init(true, signingKey);

            // Encode.

            MemoryStream    mStr   = new MemoryStream();
            DEROutputStream derOut = new DEROutputStream(mStr);

            derOut.writeObject(reqInfo);

            // Sign
            byte[] b = mStr.ToArray();
            sig.update(b, 0, b.Length);

            // Generate Signature.
            sigBits = new DERBitString(sig.generateSignature());
        }
Esempio n. 5
0
        private byte[] derEncode(
            byte[]  hash)
        {
            MemoryStream    bOut  = new MemoryStream();
            DEROutputStream dOut  = new DEROutputStream(bOut);
            DigestInfo      dInfo = new DigestInfo(algId, hash);

            dOut.writeObject(dInfo);
            dOut.Flush();

            return(bOut.ToArray());
        }
Esempio n. 6
0
 internal override void encode(
     DEROutputStream derOut)
 {
     if (derOut is ASN1OutputStream || derOut is BEROutputStream)
     {
         derOut.WriteByte((byte)ASN1Tags.NULL);
     }
     else
     {
         base.encode(derOut);
     }
 }
Esempio n. 7
0
        /// <summary>
        /// Return a DER encoded version of this certificate.
        /// </summary>
        /// <returns>A byte array.</returns>
        public byte[] getEncoded()
        {
            MemoryStream    bOut = new MemoryStream();
            DEROutputStream dOut = new DEROutputStream(bOut);

            try
            {
                dOut.writeObject(xStruct);
                return(bOut.ToArray());
            }
            catch (IOException e)
            {
                throw new Exception(e.Message);
            }
        }
Esempio n. 8
0
        private byte[] derEncode(
            BigInteger r,
            BigInteger s)
        {
            MemoryStream        bOut = new MemoryStream();
            DEROutputStream     dOut = new DEROutputStream(bOut);
            ASN1EncodableVector v    = new ASN1EncodableVector();

            v.add(new DERInteger(r));
            v.add(new DERInteger(s));

            dOut.writeObject(new DERSequence(v));

            return(bOut.ToArray());
        }
Esempio n. 9
0
        /// <summary>
        /// Generate a new X509Certificate specifying a SecureRandom instance that you would like to use.
        /// </summary>
        /// <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
        /// <param name="random">The Secure Random you want to use.</param>
        /// <returns></returns>
        public X509CertificateStructure generateX509Certificate(
            AsymmetricKeyParameter privateKey,
            SecureRandom random)

        {
            Signer sig = null;

            try {
                sig = SignerUtil.getSigner(sigOID);
            }
            catch (Exception ex)
            {
                throw new Exception("exception creating signature: " + ex.Message);
            }

            if (random != null)
            {
                sig.init(true, privateKey);
            }
            else
            {
                sig.init(true, new ParametersWithRandom(privateKey, random));
            }

            TBSCertificateStructure tbsCert = tbsGen.generateTBSCertificate();

            try
            {
                MemoryStream    mStr = new MemoryStream();
                DEROutputStream dOut = new DEROutputStream(mStr);
                dOut.writeObject(tbsCert);
                mStr.Flush();
                byte[] b = mStr.ToArray();
                sig.update(b, 0, b.Length);
            }
            catch (Exception e)
            {
                throw new Exception("exception encoding TBS cert - " + e);
            }

            ASN1EncodableVector v = new ASN1EncodableVector();

            v.add(tbsCert);
            v.add(sigAlgId);
            v.add(new DERBitString(sig.generateSignature()));

            return(new X509CertificateStructure(new DERSequence(v)));
        }
Esempio n. 10
0
        /// <summary>
        /// Add an extension to this certificate.
        /// </summary>
        /// <param name="OID">Its Object identifier.</param>
        /// <param name="critical">Is it crtical.</param>
        /// <param name="value">The value.</param>
        public void addExtension(DERObjectIdentifier OID, bool critical, ASN1Encodable value)
        {
            MemoryStream    mStr = new MemoryStream();
            DEROutputStream dOut = new DEROutputStream(mStr);

            try
            {
                dOut.writeObject(value);
            }
            catch (IOException e)
            {
                throw new Exception("error encoding value: " + e);
            }

            this.addExtension(OID, critical, mStr.ToArray());
        }
Esempio n. 11
0
        /// <summary>
        /// Verify PKCS10 Cert Reqest is valid.
        /// </summary>
        /// <returns>true = valid.</returns>
        public bool verify()
        {
            Signer sig = null;

            sig = SignerUtil.getSigner(sigAlgId.getObjectId());

            sig.init(false, getPublicKey());

            MemoryStream    mStr   = new MemoryStream();
            DEROutputStream derOut = new DEROutputStream(mStr);

            derOut.writeObject(reqInfo);
            derOut.Flush();
            byte[] b = mStr.ToArray();
            sig.update(b, 0, b.Length);
            mStr.Close();

            return(sig.verifySignature(sigBits.getBytes()));
        }
Esempio n. 12
0
        /// <summary>
        /// Get the signature algorithms parameters. (EG DSA Parameters)
        /// </summary>
        /// <returns>A byte array containing the DER encoded version of the parameters or null if there are none.</returns>
        public byte[] getSigAlgParams()
        {
            MemoryStream bOut = new MemoryStream();

            if (xStruct.getSignatureAlgorithm().getParameters() != null)
            {
                try
                {
                    DEROutputStream dOut = new DEROutputStream(bOut);
                    dOut.writeObject(xStruct.getSignatureAlgorithm().getParameters());
                }
                catch (Exception e)
                {
                    throw new Exception("exception getting sig parameters " + e);
                }

                return(bOut.ToArray());
            }
            else
            {
                return(null);
            }
        }
Esempio n. 13
0
        public void addCRLEntry(DERInteger userCertificate, Time revocationDate, int reason)
        {
            ASN1EncodableVector v = new ASN1EncodableVector();

            v.add(userCertificate);
            v.add(revocationDate);

            if (reason != 0)
            {
                CRLReason       rf   = new CRLReason(reason);
                MemoryStream    bOut = new MemoryStream();
                DEROutputStream dOut = new DEROutputStream(bOut);
                try
                {
                    dOut.writeObject(rf);
                }
                catch (IOException e)
                {
                    throw new ArgumentException("error encoding value: " + e);
                }
                byte[] value           = bOut.ToArray();
                ASN1EncodableVector v1 = new ASN1EncodableVector();
                v1.add(X509Extensions.ReasonCode);
                v1.add(new DEROctetString(value));
                X509Extensions ex = new X509Extensions(new DERSequence(
                                                           new DERSequence(v1)));
                v.add(ex);
            }

            if (crlentries == null)
            {
                crlentries = new ArrayList();
            }

            crlentries.Add(new DERSequence(v));
        }
Esempio n. 14
0
 internal override void encode(
     DEROutputStream derOut)
 {
     derOut.writeEncoded(ASN1Tags.OCTET_STRING, str);
 }
Esempio n. 15
0
        public void save(Stream stream, char[] password, SecureRandom random)
        {
            if (password == null)
            {
                throw new ArgumentException("No password supplied for PKCS12Store.");
            }

            ContentInfo[] c = new ContentInfo[2];


            //
            // handle the key
            //
            ASN1EncodableVector keyS = new ASN1EncodableVector();


            IEnumerator ks = keys.Keys.GetEnumerator();

            while (ks.MoveNext())
            {
                byte[] kSalt = new byte[saltSize];

                random.nextBytes(kSalt);

                String                  name    = (String)ks.Current;
                AsymmetricKeyEntry      privKey = (AsymmetricKeyEntry)keys[name];
                EncryptedPrivateKeyInfo kInfo   = EncryptedPrivateKeyInfoFactory.createEncryptedPrivateKeyInfo(keyAlgorithm, password, kSalt, minIterations, privKey.getKey());
                ASN1EncodableVector     kName   = new ASN1EncodableVector();

                IEnumerator e = privKey.getBagAttributeKeys();

                while (e.MoveNext())
                {
                    String oid = (String)e.Current;
                    ASN1EncodableVector kSeq = new ASN1EncodableVector();

                    kSeq.add(new DERObjectIdentifier(oid));
                    kSeq.add(new DERSet(privKey.getBagAttribute(new DERObjectIdentifier(oid))));

                    kName.add(new DERSequence(kSeq));
                }

                //
                // make sure we have a local key-id
                //
                if (privKey.getBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId) == null)
                {
                    ASN1EncodableVector  kSeq = new ASN1EncodableVector();
                    X509CertificateEntry ct   = getCertificate(name);

                    kSeq.add(PKCSObjectIdentifiers.pkcs_9_at_localKeyId);
                    kSeq.add(new DERSet(new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(ct.getCertificate().getPublicKey()))));

                    kName.add(new DERSequence(kSeq));
                }

                //
                // make sure we are using the local alias on store
                //
                DERBMPString nm = (DERBMPString)privKey.getBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName);
                if (nm == null || !nm.getString().Equals(name))
                {
                    ASN1EncodableVector kSeq = new ASN1EncodableVector();

                    kSeq.add(PKCSObjectIdentifiers.pkcs_9_at_friendlyName);
                    kSeq.add(new DERSet(new DERBMPString(name)));

                    kName.add(new DERSequence(kSeq));
                }

                SafeBag kBag = new SafeBag(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag, kInfo.toASN1Object(), new DERSet(kName));
                keyS.add(kBag);
            }

            MemoryStream    bOut = new MemoryStream();
            DEROutputStream dOut = new DEROutputStream(bOut);

            dOut.writeObject(new DERSequence(keyS));

            BEROctetString keyString = new BEROctetString(bOut.ToArray());

            //
            // certficate processing
            //
            byte[] cSalt = new byte[saltSize];

            random.nextBytes(cSalt);

            ASN1EncodableVector certSeq   = new ASN1EncodableVector();
            PKCS12PBEParams     cParams   = new PKCS12PBEParams(cSalt, minIterations);
            AlgorithmIdentifier cAlgId    = new AlgorithmIdentifier(certAlgorithm, cParams.toASN1Object());
            Hashtable           doneCerts = new Hashtable();

            IEnumerator cs = keys.Keys.GetEnumerator();

            while (cs.MoveNext())
            {
                try
                {
                    String name = (String)cs.Current;
                    X509CertificateEntry cert = getCertificate(name);
                    CertBag cBag = new CertBag(
                        PKCSObjectIdentifiers.x509certType,
                        new DEROctetString(cert.getCertificate().getEncoded()));
                    ASN1EncodableVector fName = new ASN1EncodableVector();

                    IEnumerator e = cert.getBagAttributeKeys();

                    while (e.MoveNext())
                    {
                        String oid = (String)e.Current;
                        ASN1EncodableVector fSeq = new ASN1EncodableVector();

                        fSeq.add(new DERObjectIdentifier(oid));
                        fSeq.add(new DERSet(cert.getBagAttribute(new DERObjectIdentifier(oid))));
                        fName.add(new DERSequence(fSeq));
                    }

                    //
                    // make sure we are using the local alias on store
                    //
                    DERBMPString nm = (DERBMPString)cert.getBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName);
                    if (nm == null || !nm.getString().Equals(name))
                    {
                        ASN1EncodableVector fSeq = new ASN1EncodableVector();

                        fSeq.add(PKCSObjectIdentifiers.pkcs_9_at_friendlyName);
                        fSeq.add(new DERSet(new DERBMPString(name)));

                        fName.add(new DERSequence(fSeq));
                    }

                    //
                    // make sure we have a local key-id
                    //
                    if (cert.getBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId) == null)
                    {
                        ASN1EncodableVector fSeq = new ASN1EncodableVector();

                        fSeq.add(PKCSObjectIdentifiers.pkcs_9_at_localKeyId);
                        fSeq.add(new DERSet(new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(cert.getCertificate().getPublicKey()))));
                        fName.add(new DERSequence(fSeq));
                    }

                    SafeBag sBag = new SafeBag(PKCSObjectIdentifiers.certBag, cBag.toASN1Object(), new DERSet(fName));

                    certSeq.add(sBag);

                    doneCerts.Add(cert, cert);
                }
                catch (Exception e)
                {
                    throw new Exception("Error encoding certificate: " + e.Message);
                }
            }

            cs = certs.Keys.GetEnumerator();
            while (cs.MoveNext())
            {
                try
                {
                    String certId             = (String)cs.Current;
                    X509CertificateEntry cert = (X509CertificateEntry)certs[certId];

                    if (keys[certId] != null)
                    {
                        continue;
                    }

                    CertBag cBag = new CertBag(
                        PKCSObjectIdentifiers.x509certType,
                        new DEROctetString(cert.getCertificate().getEncoded()));
                    ASN1EncodableVector fName = new ASN1EncodableVector();
                    IEnumerator         e     = cert.getBagAttributeKeys();

                    while (e.MoveNext())
                    {
                        String oid = (String)e.Current;
                        ASN1EncodableVector fSeq = new ASN1EncodableVector();

                        fSeq.add(new DERObjectIdentifier(oid));
                        fSeq.add(new DERSet(cert.getBagAttribute(new DERObjectIdentifier(oid))));
                        fName.add(new DERSequence(fSeq));
                    }

                    //
                    // make sure we are using the local alias on store
                    //
                    DERBMPString nm = (DERBMPString)cert.getBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName);
                    if (nm == null || !nm.getString().Equals(certId))
                    {
                        ASN1EncodableVector fSeq = new ASN1EncodableVector();

                        fSeq.add(PKCSObjectIdentifiers.pkcs_9_at_friendlyName);
                        fSeq.add(new DERSet(new DERBMPString(certId)));

                        fName.add(new DERSequence(fSeq));
                    }

                    SafeBag sBag = new SafeBag(PKCSObjectIdentifiers.certBag, cBag.toASN1Object(), new DERSet(fName));

                    certSeq.add(sBag);

                    doneCerts.Add(cert, cert);
                }
                catch (Exception e)
                {
                    throw new Exception("Error encoding certificate: " + e.Message);
                }
            }

            cs = chainCerts.Keys.GetEnumerator();
            while (cs.MoveNext())
            {
                try
                {
                    CertId certId             = (CertId)cs.Current;
                    X509CertificateEntry cert = (X509CertificateEntry)chainCerts[certId];

                    if (doneCerts[cert] != null)
                    {
                        continue;
                    }

                    CertBag cBag = new CertBag(
                        PKCSObjectIdentifiers.x509certType,
                        new DEROctetString(cert.getCertificate().getEncoded()));
                    ASN1EncodableVector fName = new ASN1EncodableVector();

                    IEnumerator e = cert.getBagAttributeKeys();

                    while (e.MoveNext())
                    {
                        DERObjectIdentifier oid  = (DERObjectIdentifier)e.Current;
                        ASN1EncodableVector fSeq = new ASN1EncodableVector();

                        fSeq.add(oid);
                        fSeq.add(new DERSet(cert.getBagAttribute(oid)));
                        fName.add(new DERSequence(fSeq));
                    }

                    SafeBag sBag = new SafeBag(PKCSObjectIdentifiers.certBag, cBag.toASN1Object(), new DERSet(fName));

                    certSeq.add(sBag);
                }
                catch (Exception e)
                {
                    throw new Exception("Error encoding certificate: " + e.Message);
                }
            }

            bOut = new MemoryStream();

            dOut = new DEROutputStream(bOut);

            dOut.writeObject(new DERSequence(certSeq));

            dOut.Close();

            byte[]        certBytes = encryptData(new AlgorithmIdentifier(certAlgorithm, cParams), bOut.ToArray(), password);
            EncryptedData cInfo     = new EncryptedData(PKCSObjectIdentifiers.data, cAlgId, new BEROctetString(certBytes));

            c[0] = new ContentInfo(PKCSObjectIdentifiers.data, keyString);

            c[1] = new ContentInfo(PKCSObjectIdentifiers.encryptedData, cInfo.toASN1Object());

            AuthenticatedSafe auth = new AuthenticatedSafe(c);

            bOut = new MemoryStream();

            BEROutputStream berOut = new BEROutputStream(bOut);

            berOut.writeObject(auth);

            byte[] pkg = bOut.ToArray();

            ContentInfo mainInfo = new ContentInfo(PKCSObjectIdentifiers.data, new BEROctetString(pkg));

            //
            // create the mac
            //
            byte[] mSalt   = new byte[20];
            int    itCount = minIterations;

            random.nextBytes(mSalt);

            byte[] data = ((ASN1OctetString)mainInfo.getContent()).getOctets();

            MacData mData = null;

            try
            {
                ASN1Encodable    parameters    = PBEUtil.generateAlgorithmParameters(OIWObjectIdentifiers.id_SHA1, mSalt, itCount);
                CipherParameters keyParameters = PBEUtil.generateCipherParameters(OIWObjectIdentifiers.id_SHA1, password, parameters);
                Mac mac = (Mac)PBEUtil.createEngine(OIWObjectIdentifiers.id_SHA1);

                mac.init(keyParameters);

                mac.update(data, 0, data.Length);

                byte[] res = new byte[mac.getMacSize()];

                mac.doFinal(res, 0);

                AlgorithmIdentifier algId = new AlgorithmIdentifier(OIWObjectIdentifiers.id_SHA1, new DERNull());
                DigestInfo          dInfo = new DigestInfo(algId, res);

                mData = new MacData(dInfo, mSalt, itCount);
            }
            catch (Exception e)
            {
                throw new Exception("error constructing MAC: " + e.Message);
            }

            //
            // output the Pfx
            //
            Pfx pfx = new Pfx(mainInfo, mData);

            berOut = new BEROutputStream(stream);

            berOut.writeObject(pfx);
        }
Esempio n. 16
0
/// <summary>
///
/// </summary>
/// <param name="signingAlgorithm">The OID of the signing algorithm.</param>
/// <param name="privkey">The signing private key.</param>
/// <param name="chain">An array containing X509Certificate objects, can be null.</param>
/// <param name="producedAt">The time this response is produced at.</param>
/// <param name="random">A SecureRandom instance.</param>
/// <returns></returns>
        public BasicOCSPResp generateResponse(
            DERObjectIdentifier signingAlgorithm,
            AsymmetricKeyParameter privkey,
            X509Certificate[]   chain,
            DateTime producedAt,
            SecureRandom random)
        {
            IEnumerator         it        = list.GetEnumerator();
            ASN1EncodableVector responses = new ASN1EncodableVector();

            while (it.MoveNext())
            {
                try
                {
                    responses.add(((ResponseObject)it.Current).toResponse());
                }
                catch (Exception e)
                {
                    throw new OCSPException("exception creating Request", e);
                }
            }

            ResponseData tbsResp = new ResponseData(new DERInteger(0), responderID.toASN1Object(), new DERGeneralizedTime(producedAt), new DERSequence(responses), responseExtensions);

            Signer sig = null;

            try
            {
                sig = SignerUtil.getSigner(signingAlgorithm);
                if (random != null)
                {
                    sig.init(true, new ParametersWithRandom(privkey, random));
                }
                else
                {
                    sig.init(true, privkey);
                }
            }
            catch (Exception e)
            {
                throw new OCSPException("exception creating signature: " + e, e);
            }

            DERBitString bitSig = null;

            try
            {
                MemoryStream    bOut = new MemoryStream();
                DEROutputStream dOut = new DEROutputStream(bOut);

                dOut.writeObject(tbsResp);
                byte[] b = bOut.ToArray();

                sig.update(b, 0, b.Length);
                bitSig = new DERBitString(sig.generateSignature());
            }
            catch (Exception e)
            {
                throw new OCSPException("exception processing TBSRequest: " + e, e);
            }

            AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(signingAlgorithm, new DERNull());

            if (chain != null && chain.Length > 0)
            {
                ASN1EncodableVector v = new ASN1EncodableVector();
                try
                {
                    for (int i = 0; i != chain.Length; i++)
                    {
                        v.add(new X509CertificateStructure(
                                  (ASN1Sequence)makeObj(chain[i].getEncoded())));
                    }
                }
                catch (IOException e)
                {
                    throw new OCSPException("error processing certs", e);
                }


                return(new BasicOCSPResp(new BasicOCSPResponse(tbsResp, sigAlgId, bitSig, new DERSequence(v))));
            }
            else
            {
                return(new BasicOCSPResp(new BasicOCSPResponse(tbsResp, sigAlgId, bitSig, null)));
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Generate an X509Certificate using your own SecureRandom.
        /// </summary>
        /// <param name="key">The private key of the issuer that is signing this certificate.</param>
        /// <param name="random">You Secure Random instance.</param>
        /// <returns>An X509Certificate.</returns>
        public X509Certificate generateX509Certificate(AsymmetricKeyParameter key, SecureRandom random)
        {
            Signer sig = null;

            if (sigOID == null)
            {
                throw new Exception("no signature algorithm specified");
            }

            try
            {
                sig = SignerUtil.getSigner(sigOID);
            }
            catch
            {
                try
                {
                    sig = SignerUtil.getSigner(signatureAlgorithm);
                }
                catch (Exception e)
                {
                    throw new Exception("exception creating signature: " + e.Message);
                }
            }

            if (random != null)
            {
                sig.init(true, new ParametersWithRandom(key, random));
            }
            else
            {
                // Console.WriteLine("**" + sig.GetType());
                sig.init(true, key);
            }

            if (extensions != null)
            {
                tbsGen.setExtensions(new X509Extensions(extOrdering, extensions));
            }
            TBSCertificateStructure tbsCert = tbsGen.generateTBSCertificate();

            try
            {
                MemoryStream    mStr = new MemoryStream();
                DEROutputStream dOut = new DEROutputStream(mStr);
                dOut.writeObject(tbsCert);
                byte[] b = mStr.ToArray();
                sig.update(b, 0, b.Length);
            }
            catch (Exception e)
            {
                throw new Exception("exception encoding TBS cert - " + e);
            }
            ASN1EncodableVector v = new ASN1EncodableVector();

            v.add(tbsCert);
            v.add(sigAlgId);
            v.add(new DERBitString(sig.generateSignature()));

            return(new X509Certificate(new DERSequence(v)));
        }