本文介绍了如何以编程方式检查证书是否已被撤销?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个xcode自动构建系统。当执行一些预构建验证时,我想检查指定的证书文件是否已被撤销。我理解, security verify-cert 验证其他证书属性,但不是rev​​okation。我如何检查revokation?

I'm working on an xcode automated build system. When performing some pre-build validation I would like to check if the specified certificate file has been revoked. I understand that security verify-cert verifies other cert properties but not revokation. How can I check for revokation?

我在Ruby编写构建系统,但我真的开放于任何语言的想法。

I'm writing the build system in Ruby but am really open to ideas in any language.

我读了这个答案(),但链接指向底部()进入对我的目的用户上传撤销的证书是一个远的边缘情况)。是否有更简单/基于ruby的方法来检查revokation?

I read this answer (Openssl - How to check if a certificate is revoked or not) but the link towards the bottom (Does OpenSSL automatically handle CRLs (Certificate Revocation Lists) now?) gets into material that's a bit too involved for my purposes (a user uploading a revoked cert is a far out edge case). Is there a simpler / ruby oriented method for checking for revokation?

提前感谢!

推荐答案

检查证书是否被撤销可能是一个复杂的过程。首先,您必须查找CDP或OCSP AIA,然后提出请求,解析响应,并检查响应是否由有权对有问题的证书做出响应的CA签名。如果它是一个CRL,则需要查看您检查的证书的序列号是否存在于列表中。如果是OCSP,那么您需要查看是否已收到良好响应(与未知,已撤销或任何各种OCSP响应程序错误(例如未经授权)相对)。此外,您可能要验证证书是否在其有效期内并链接到受信任的根。最后,您应该对每个中间人执行撤销检查,并检查证书的指纹与Mozilla / Apple / Google / Microsoft维护的显式黑名单。

Checking if a certificate is revoked can be a complex process. First you have to look for a CDP or OCSP AIA, then make a request, parse the response, and check that the response is signed against by a CA that is authorized to respond for the certificate in question. If it is a CRL you then need to see if the serial number of the certificate you're checking is present in the list. If it is OCSP then you need to see if you've received a "good" response (as opposed to unknown, revoked, or any of the various OCSP responder errors like unauthorized). Additionally you may want to verify that the certificate is within its validity period and chains to a trusted root. Finally, you should do revocation checks against every intermediate as well and check the certificate's fingerprint against the explicit blacklists that Mozilla/Apple/Google/Microsoft maintain.

我不知道的任何Ruby库的自动化撤销检查过程(最终我希望将其添加到),但鉴于您的更具体的用例这里的一些未经测试的代码,应该指向正确的方向。

I'm unaware of any Ruby libraries that automate the revocation checking process for you (eventually I hope to add it to r509), but given your more specific use case here's some untested code that should point you in the right direction.

require 'r509'
require 'net/http'
cert = R509::Cert.load_from_file("some_iphone_cert.pem")
crl_uri = cert.crl_distribution_points.crl.uris[0]
crl = Net::HTTP.get_response(URI(crl_uri)) # you may need to follow redirects here, but let's assume you got the CRL.
# Also note that the Apple WWDRCA CRL is like 28MB so you may want to cache this damned thing. OCSP would be nicer but it's a bit trickier to validate.
parsed_crl = R509::CRL::SignedList.new(crl)
if not parsed_crl.verify(cert.public_key)
  raise StandardError, "Invalid CRL for certificate"
end
if parsed_crl.revoked?(cert.serial)
  puts 'revoked'
end


不幸的是,由于苹果WWDRCA CRL的庞大大小(〜680k条目),这种检查对于r509当前的哈希映射模型可能很慢。

Unfortunately, due to the enormous size (~680k entries) of the Apple WWDRCA CRL this check can be quite slow with r509's current hash map model.

如果你有兴趣下去OCSP路径,我可以写出如何生成OCSP请求/解析响应在Ruby中。

If you're interested in going down the OCSP path I can write up how to generate OCSP requests/parse responses in Ruby as well.

编辑:它出现了iPhone开发人员证书我没有包含嵌入式OCSP AIA,所以撤销检查的唯一选项将通过CRL分发点如上所示。

It appears the iPhone developer certificates I have do not contain an embedded OCSP AIA so the only option for revocation checking will be via CRL distribution point as presented above.

Edit2:哦,为什么不,让我们做一个OCSP检查Ruby!为此,我们需要证书及其签发证书。您不能使用WWDRCA证书,因此只需从您喜爱的网站抓取一个。我正在使用我自己的网站。

Oh why not, let's do an OCSP check in Ruby! For this we'll need the certificate and its issuing certificate. You can't use a WWDRCA certificate for this so just grab one from your favorite website. I'm using my own website.

require 'net/http'
require 'r509'
cert = R509::Cert.load_from_file("my_website.pem")
# get the first OCSP AIA URI. There can be more than one
# (degenerate example!)
ocsp_uri = cert.aia.ocsp.uris[0]
issuer = R509::Cert.load_from_file("my_issuer.pem")
cert_id = OpenSSL::OCSP::CertificateId.new(cert.cert,issuer.cert)
request = OpenSSL::OCSP::Request.new
request.add_certid(cert_id)
# we're going to make a GET request per RFC 5019. You can also POST the
# binary DER encoded version if you're more of an RFC 2560 partisan
request_uri = URI(ocsp_uri+"/"+URI.encode_www_form_component(req_pem.strip)
http_response = Net::HTTP.get_response(request_uri)
if http_response.code != "200"
  raise StandardError, "Invalid response code from OCSP responder"
end
response = OpenSSL::OCSP::Response.new(http_response.body)
if response.status != 0
  raise StandardError, "Not a successful status"
end
if response.basic[0][0].serial != cert.serial
  raise StandardError, "Not the same serial"
end
if response.basic[0][1] != 0 # 0 is good, 1 is revoked, 2 is unknown.
  raise StandardError, "Not a good status"
end
current_time = Time.now
if response.basic[0][4] > current_time or response.basic[0][5] < current_time
  raise StandardError, "The response is not within its validity window"
end
# we also need to verify that the OCSP response is signed by
# a certificate that is allowed and chains up to a trusted root.
# To do this you'll need to build an OpenSSL::X509::Store object
# that contains the certificate you're checking + intermediates + root.
store = OpenSSL::X509::Store.new
store.add_cert(cert.cert)
store.add_cert(issuer.cert) #assuming issuer is a trusted root here, but in reality you'll need at least one more certificate
if response.basic.verify([],store) != true
  raise StandardError, "Certificate verification error"
end

上面的示例代码忽略了处理许多可能的边缘情况,因此它应该仅被视为一个起点。祝你好运!

The example code above neglects to handle many possible edge cases, so it should be considered a starting point only. Good luck!

这篇关于如何以编程方式检查证书是否已被撤销?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 15:13