正确处理来自 C# / Java 应用程序 (+ BouncyCastle) 的 OCSP 请求

Correctly handle OCSP requests from C# / Java app (+ BouncyCastle)

我有一个生成 X509 证书的应用程序(带有 Bouncy Castle 的 dotnet 核心)。证书管理的重要部分也是撤销它们。我目前确实支持通过 CRL 撤销,但我们的供应商也要求实施 OCSP。问题开始出现了。

我已经实现了一些看起来与 RFC 6960 和一些随机的 Java 部分兼容的东西,它们做的事情非常相似。 但是我遇到了以下我无法弄清楚的错误:

OCSP Request Data:
    Version: 1 (0x0)
    Requestor List:
        Certificate ID:
          Hash Algorithm: sha1
          Issuer Name Hash: 5ED580C3E05BAB929E3B5FE31AF1FD2D63DA2B66
          Issuer Key Hash: 0BA5610F200458E9183155354D0956598285F833
          Serial Number: 2D9E89A741BE3BED
    Request Extensions:
        OCSP Nonce:
            0410D596BF4A21EA59007CAD5AE306DCF349
Error querying OCSP responder
27384:error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag:../openssl-1.1.1c/crypto/asn1/tasn_dec.c:1130:
27384:error:0D06C03A:asn1 encoding routines:asn1_d2i_ex_primitive:nested asn1 error:../openssl-1.1.1c/crypto/asn1/tasn_dec.c:694:
27384:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../openssl-1.1.1c/crypto/asn1/tasn_dec.c:627:Field=responseStatus, Type=OCSP_RESPONSE

我下面的配置是:

我正在使用以下命令(从命令行)测试我的代码:

$ openssl ocsp -issuer certs/root-ocsp.crt -cert client-cert.crt -text -url http://localhost:12345/certificate/ocsp

老实说,我不知道可能出了什么问题...根据错误,我怀疑 Asn1 签名有问题,但在检查了几个选项(包括链中的 rootCert 等)后,结果是一直都一样。

生成 OCSP 响应的代码的关键部分如下所示:

public byte[] GenerateOcsp(OcspReq ocspReq, IList<Certificate> certificates)
{
    //Should be used at all for OCSP?
    var rootCert = _rootCertificateProvider.GetBouncyRootCert("development");
    var ocspCert = _rootCertificateProvider.GetBouncyRootCert("ocsp");

    var respGen = new BasicOcspRespGenerator(ocspCert.Certificate.GetPublicKey());
    var nonceExt = ocspReq.RequestExtensions.GetExtension(OcspObjectIdentifiers.PkixOcspNonce);
    if (nonceExt != null)
        respGen.SetResponseExtensions(new X509Extensions(new[] { OcspObjectIdentifiers.PkixOcspNonce }, new[] { nonceExt }));

    foreach (var req in ocspReq.GetRequestList())
    {
        var serialNo = req.GetCertID().SerialNumber;
        var dbCert = certificates.FirstOrDefault(c => BigInteger.ValueOf(c.SerialNumber).Equals(serialNo));
        if (dbCert == null)
        {
            respGen.AddResponse(req.GetCertID(), new UnknownStatus());
        }
        else if (dbCert.Revocated)
        {
            respGen.AddResponse(req.GetCertID(), new RevokedStatus(dbCert.RevocationDate ?? DateTime.Now, 0));
        }
        else
        {
            respGen.AddResponse(req.GetCertID(), CertificateStatus.Good);
        }
    }

    var random = new SecureRandom();
    var signFactory = new Asn1SignatureFactory("SHA256WithRSA", ocspCert.PrivKey, random);
    var ocspResponse = respGen.Generate(signFactory, new[] { ocspCert.Certificate }, DateTime.UtcNow);
    
    return ocspResponse.GetEncoded();
}

结果通过控制器返回如下:

  return new FileContentResult(result, "application/ocsp-response");

有什么想法是错误的吗?

谢谢!

所有未来到达这个问题的人:

我在这个问题上的总体方法很好,唯一缺少的是通过额外的响应生成器传递结果。

因此,与其返回 ocspResponse.GetEncoded(),不如这样做,您就完成了:

var builder = new OCSPRespGenerator();
var response = builder.Generate(OCSPRespGenerator.Successful, ocspResponse);

return response.GetEncoded();