C # Как правильно отправить запрос OCSP с помощью библиотеки надувных замков? - PullRequest
1 голос
/ 17 мая 2019

Запрос OCSP не попадает в таблицу журнала аудита при отправке с использованием библиотеки Bouncy Castle.Я не понимаю почему?Что не так с моим кодом и как его решить?

У меня есть сертификат клиента и сертификат эмитента.Я создаю два клиентских класса для этой цели.Каждый из них использует разные библиотеки.Один использует Надувной Замок, другой использует Чилкат.Каждый из них правильно проверяет сертификат.Но проблема со стороны сервера.Запрос не попадает в таблицу журнала аудита, когда я пробую версию Bouncy Castle.Но когда я использую Chilkat API, все в порядке.

Версия Bouncy Castle:

class TestOCSPClient
    {
        protected static Asn1Object GetExtensionValue(X509Certificate cert,
               string oid)
        {
            if (cert == null)
            {
                return null;
            }

            byte[] bytes = cert.GetExtensionValue(new DerObjectIdentifier(oid)).GetOctets();

            if (bytes == null)
            {
                return null;
            }

            Asn1InputStream aIn = new Asn1InputStream(bytes);

            return aIn.ReadObject();
        }


        public static List<string> GetAuthorityInformationAccessOcspUrl(X509Certificate cert)
        {
            List<string> ocspUrls = new List<string>();

            try
            {
                Asn1Object obj = GetExtensionValue(cert, X509Extensions.AuthorityInfoAccess.Id);

                if (obj == null)
                {
                    return null;
                }
                Asn1Sequence s = (Asn1Sequence)obj;
                IEnumerator elements = s.GetEnumerator();

                while (elements.MoveNext())
                {
                    Asn1Sequence element = (Asn1Sequence)elements.Current;
                    DerObjectIdentifier oid = (DerObjectIdentifier)element[0];

                    if (oid.Id.Equals("1.3.6.1.5.5.7.48.1")) // Is Ocsp?
                    {
                        Asn1TaggedObject taggedObject = (Asn1TaggedObject)element[1];
                        GeneralName gn = (GeneralName)GeneralName.GetInstance(taggedObject);
                        ocspUrls.Add(((DerIA5String)DerIA5String.GetInstance(gn.Name)).GetString());
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception("Error parsing AIA.", e);
            }

            return ocspUrls;
        }

        public CertificateStatusEnum ValidateOCSP(X509Certificate cert, X509Certificate cacert)
        {
            List<string> urls = GetAuthorityInformationAccessOcspUrl(cert);
            if (urls.Count == 0)
            {
                throw new Exception("No OCSP url found in ee certificate.");
            }

            string url = urls[0];
            Console.WriteLine("Sending to :  '" + url + "'...");

            byte[] packtosend = CreateOCSPPackage(cert, cacert);

            byte[] response = PostRequest(url, packtosend, "Content-Type", "application/ocsp-request");

            return VerifyResponse(response); 
        }

        public byte[] ToByteArray(Stream stream)
        {
            byte[] buffer = new byte[4096 * 8];
            MemoryStream ms = new MemoryStream();

            int read = 0;

            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }

            return ms.ToArray();
        }

        public byte[] PostRequest(string url, byte[] data, string contentType, string accept)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = contentType;
            request.ContentLength = data.Length;
            request.Accept = accept;
            Stream stream = request.GetRequestStream();
            stream.Write(data, 0, data.Length);
            stream.Close();
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream respStream = response.GetResponseStream();
            Console.WriteLine(string.Format("HttpStatusCode : {0}", response.StatusCode.ToString()));
            byte[] resp = ToByteArray(respStream);
            respStream.Close();

            return resp;
        }

         private CertificateStatusEnum VerifyResponse(byte[] response)
         {
             OcspResp r = new OcspResp(response);
            CertificateStatusEnum cStatusEnum = CertificateStatusEnum.Unknown;
          switch (r.Status)
            {
                case OcspRespStatus.Successful:
                    BasicOcspResp or = (BasicOcspResp)r.GetResponseObject();

                    //ValidateResponse(or, issuerCert);
                    Console.WriteLine(or.Responses.Length);
                    if (or.Responses.Length == 1)
                    {
                        SingleResp resp = or.Responses[0];



                        Object certificateStatus = resp.GetCertStatus();

                        //this part returns  null actually 
                        if (certificateStatus == null)
                        {
                            Console.WriteLine("Status is null ! ");
                        }
                        if (certificateStatus==null ||  certificateStatus == Org.BouncyCastle.Ocsp.CertificateStatus.Good)
                        {
                            cStatusEnum = CertificateStatusEnum.Good;
                        }
                        else if (certificateStatus is Org.BouncyCastle.Ocsp.RevokedStatus)
                        {
                            cStatusEnum = CertificateStatusEnum.Revoked;
                        }
                        else if (certificateStatus is Org.BouncyCastle.Ocsp.UnknownStatus)
                        {
                            cStatusEnum = CertificateStatusEnum.Unknown;
                        }
                    }
                    break;
                default:
                    throw new Exception("Unknow status '" + r.Status + "'.");
            }

             return cStatusEnum;
         }


        private static byte[] CreateOCSPPackage(X509Certificate cert, X509Certificate cacert)
        {
            OcspReqGenerator gen = new OcspReqGenerator();
            try
            {
                CertificateID certId = new CertificateID(CertificateID.HashSha1, cacert, cert.SerialNumber);
                gen.AddRequest(certId);
                gen.SetRequestExtensions(CreateExtension());
                OcspReq req;
                req = gen.Generate();
                return req.GetEncoded();
            }
            catch (OcspException e)
            {
                Console.WriteLine(e.StackTrace);
            }
            catch (IOException e)
            {

                Console.WriteLine(e.StackTrace);
            }
            return null;


        }

        private static X509Extensions CreateExtension()
        {
            byte[] nonce = new byte[16];
            Hashtable exts = new Hashtable();

            BigInteger nc = BigInteger.ValueOf(DateTime.Now.Ticks);
            X509Extension nonceext = new X509Extension(false, new DerOctetString(nc.ToByteArray()));


            exts.Add(OcspObjectIdentifiers.PkixOcspNonce, nonceext);
            return new X509Extensions(exts);

        }


    }

Версия Chilkat:


    public static  class ChilCatOCSP
    {


        public static void Validate( string cetpat )
        {
            Chilkat.Global glob = new Chilkat.Global();
            bool chksuccesss = glob.UnlockBundle("Anything for 30-day trial");
            if (chksuccesss != true)
            {
                Console.WriteLine(glob.LastErrorText);
                return;
            }


            Chilkat.Cert cert = new Chilkat.Cert();
            bool success = cert.LoadFromFile(cetpat);
            if (success != true)
            {
                Console.WriteLine(cert.LastErrorText);
                return;
            }

            string ocspUrl = cert.OcspUrl;


            //  Build the JSON that will be the OCSP request.
            Chilkat.Prng prng = new Chilkat.Prng();
            Chilkat.JsonObject json = new Chilkat.JsonObject();
            json.EmitCompact = false;
            json.UpdateString("extensions.ocspNonce", prng.GenRandom(36, "base64"));
            json.I = 0;
            json.UpdateString("request[i].cert.hashAlg", "sha1");
            json.UpdateString("request[i].cert.issuerNameHash", cert.HashOf("IssuerDN", "sha1", "base64"));
            json.UpdateString("request[i].cert.issuerKeyHash", cert.HashOf("IssuerPublicKey", "sha1", "base64"));
            json.UpdateString("request[i].cert.serialNumber", cert.SerialNumber);

            Console.WriteLine(json.Emit());


            Chilkat.BinData ocspRequest = new Chilkat.BinData();
            Chilkat.Http http = new Chilkat.Http();

            //  Convert our JSON to a binary (ASN.1) OCSP request
            http.CreateOcspRequest(json, ocspRequest);

            //  Send the OCSP request to the OCSP server
            Chilkat.HttpResponse resp = http.PBinaryBd("POST", ocspUrl, ocspRequest, "application/ocsp-request", false, false);
            if (http.LastMethodSuccess != true)
            {
                Console.WriteLine(http.LastErrorText);
                return;
            }

            //  Get the binary (ASN.1) OCSP reply
            Chilkat.BinData ocspReply = new Chilkat.BinData();
            resp.GetBodyBd(ocspReply);

            //  Convert the binary reply to JSON.
            //  Also returns the overall OCSP response status.
            Chilkat.JsonObject jsonReply = new Chilkat.JsonObject();
            int ocspStatus = http.ParseOcspReply(ocspReply, jsonReply);

            //  The ocspStatus can have one of these values:
            //  -1:  The ARG1 does not contain a valid OCSP reply.
            //  0:  Successful - Response has valid confirmations..
            //  1: Malformed request - Illegal confirmation request.
            //  2: Internal error - Internal error in issuer.
            //  3: Try later -  Try again later.
            //  4: Not used - This value is never returned.
            //  5: Sig required - Must sign the request.
            //  6: Unauthorized - Request unauthorized.

            if (ocspStatus < 0)
            {
                Console.WriteLine("Invalid OCSP reply.");
                return;
            }



            Console.WriteLine("Overall OCSP Response Status: " + Convert.ToString(ocspStatus));

            //  Let's examine the OCSP response (in JSON).
            jsonReply.EmitCompact = false;
            Console.WriteLine(jsonReply.Emit());

            //  The JSON reply looks like this:
            //  (Use the online tool at https://tools.chilkat.io/jsonParse.cshtml
            //  to generate JSON parsing code.)

            //  {
            //    "responseStatus": 0,
            //    "responseTypeOid": "1.3.6.1.5.5.7.48.1.1",
            //    "responseTypeName": "ocspBasic",
            //    "response": {
            //      "responderIdChoice": "KeyHash",
            //      "responderKeyHash": "d8K4UJpndnaxLcKG0IOgfqZ+uks=",
            //      "dateTime": "20180803193937Z",
            //      "cert": [
            //        {
            //          "hashOid": "1.3.14.3.2.26",
            //          "hashAlg": "SHA-1",
            //          "issuerNameHash": "9u2wY2IygZo19o11oJ0CShGqbK0=",
            //          "issuerKeyHash": "d8K4UJpndnaxLcKG0IOgfqZ+uks=",
            //          "serialNumber": "6175535D87BF94B6",
            //          "status": 0,
            //          "thisUpdate": "20180803193937Z",
            //          "nextUpdate": "20180810193937Z"
            //        }
            //      ]
            //    }
            //  }
            // 

            //  The certificate status:
            int certStatus = json.IntOf("response.cert[0].status");

            //  Possible certStatus values are:
            //  0: Good
            //  1: Revoked
            //  2: Unknown.
            Console.WriteLine("Certificate Status: " + Convert.ToString(certStatus));

        }

    }

Кроме того, я нашел онлайн-инструмент, который работает нормально. здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...