正确处理来自 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
我下面的配置是:
- #1 根证书 - 用于创建可以撤销的所有客户端证书
- #2 ocsp 根证书 - 单独生成用于签署 ocsp 响应
我正在使用以下命令(从命令行)测试我的代码:
$ 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();
我有一个生成 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
我下面的配置是:
- #1 根证书 - 用于创建可以撤销的所有客户端证书
- #2 ocsp 根证书 - 单独生成用于签署 ocsp 响应
我正在使用以下命令(从命令行)测试我的代码:
$ 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();