C#如何使用弹性城堡库正确发送OCSP请求?

时间:2019-05-17 11:25:06

标签: c# cryptography pki ocsp

当我使用Bouncy Castle库发送OCSP请求时,它不属于“审核”日志表。 我不明白为什么?我的代码有什么问题以及如何解决?

我有客户证书和发行者证书。为此,我创建了两个客户端类。他们每个人使用不同的库。一种使用Bouncy Castle,另一种使用Chilkat。他们每个人都正确地验证证书。但是问题出在服务器端。当我尝试Bouncy Castle版本时,该查询不属于Audit日志表。 但是,当我使用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));

        }

    }

此外,我发现了可以正常使用的在线工具。 here

0 个答案:

没有答案