当我使用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