首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

OpenSSL::OCSP

OpenSSL :: OCSP 实现在线证书状态协议请求和响应。

创建和发送 OCSP 请求需要在authorityInfoAccess扩展中包含 OCSP URL 的主题证书以及主题证书的颁发者证书。首先,加载发行人和主体证书:

代码语言:javascript
复制
subject = OpenSSL::X509::Certificate.new subject_pem
issuer  = OpenSSL::X509::Certificate.new issuer_pem

为了创建请求,我们需要为主题证书创建一个证书 ID,以便 CA 知道我们询问的是哪个证书:

代码语言:javascript
复制
digest = OpenSSL::Digest::SHA1.new
certificate_id =
  OpenSSL::OCSP::CertificateId.new subject, issuer, digest

然后创建一个请求并向其添加证书 ID:

代码语言:javascript
复制
request = OpenSSL::OCSP::Request.new
request.add_certid certificate_id

在请求中添加一个 nonce 可防止重放攻击,但并非所有 CA 都处理 nonce。

代码语言:javascript
复制
request.add_nonce

要将请求提交给 CA 进行验证,我们需要从主题证书中提取 OCSP URI:

代码语言:javascript
复制
authority_info_access = subject.extensions.find do |extension|
  extension.oid == 'authorityInfoAccess'
end

descriptions = authority_info_access.value.split "\n"
ocsp = descriptions.find do |description|
  description.start_with? 'OCSP'
end

require 'uri'

ocsp_uri = URI ocsp[/URI:(.*)/, 1]

要提交请求,我们会将请求发送到 OCSP URI(根据RFC 2560)。请注意,我们只处理 HTTP 请求,并且在本例中不处理任何重定向,所以这对于严重使用是不够的。

代码语言:javascript
复制
require 'net/http'

http_response =
  Net::HTTP.start ocsp_uri.hostname, ocsp.port do |http|
    http.post ocsp_uri.path, request.to_der,
              'content-type' => 'application/ocsp-request'
end

response = OpenSSL::OCSP::Response.new http_response.body
response_basic = response.basic

首先我们检查响应是否有有效签名。没有有效的签名,我们不能相信它。如果您在此遇到故障,则可能缺少系统证书存储或者可能缺少中间证书。

代码语言:javascript
复制
store = OpenSSL::X509::Store.new
store.set_default_paths

unless response_basic.verify [], store then
  raise 'response is not signed by a trusted certificate'
end

该响应包含状态信息(成功/失败)。我们可以将状态显示为一个字符串:

代码语言:javascript
复制
puts response.status_string #=> successful

接下来,我们需要知道回复的详细信息,以确定回复是否符合我们的要求。首先我们检查nonce。同样,并非所有的 CA 都支持随机数。有关返回值的含义,请参阅 OpenSSL :: OCSP :: Request#check_nonce。

代码语言:javascript
复制
p request.check_nonce basic_response #=> value from -1 to 3

然后从基本响应中提取证书的状态信息。

代码语言:javascript
复制
single_response = basic_response.find_response(certificate_id)

unless single_response
  raise 'basic_response does not have the status for the certificiate'
end

然后检查有效性。未来发布的状态必须被拒绝。

代码语言:javascript
复制
unless single_response.check_validity
  raise 'this_update is in the future or next_update time has passed'
end

case single_response.cert_status
when OpenSSL::OCSP::V_CERTSTATUS_GOOD
  puts 'certificate is still valid'
when OpenSSL::OCSP::V_CERTSTATUS_REVOKED
  puts "certificate has been revoked at #{single_response.revocation_time}"
when OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
  puts 'responder doesn't know about the certificate'
end

常量

NOCASIGN

(这个标志不被 OpenSSL 1.0.1g 使用)

NOCERTS

不要在响应中包含证书

NOCHAIN

不要验证响应中的证书链

NOCHECKS

不要进行额外的签名证书检查

NODELEGATED

(这个标志不被 OpenSSL 1.0.1g 使用)

NOEXPLICIT

不要检查信任

NOINTERN

不要搜索签名者的响应中包含的证书

NOSIGS

不要在响应中检查签名

NOTIME

不包括产生的响应时间

NOVERIFY

根本不验证响应

RESPID_KEY

通过签署证书密钥 ID 来识别响应

RESPONSE_STATUS_INTERNALERROR

发行人内部错误

RESPONSE_STATUS_MALFORMEDREQUEST

非法确认请求

RESPONSE_STATUS_SIGREQUIRED

您必须签署请求并重新提交

RESPONSE_STATUS_SUCCESSFUL

响应有有效的确认

RESPONSE_STATUS_TRYLATER

稍后再试

RESPONSE_STATUS_UNAUTHORIZED

您的请求未经授权。

REVOKED_STATUS_AFFILIATIONCHANGED

证书主题的名称或其他信息已更改

REVOKED_STATUS_CACOMPROMISE

由于密钥泄露,此 CA 证书已被吊销

REVOKED_STATUS_CERTIFICATEHOLD

该证书处于暂停状态

REVOKED_STATUS_CESSATIONOFOPERATION

证书不再需要

REVOKED_STATUS_KEYCOMPROMISE

该证书因重大妥协而被撤销

REVOKED_STATUS_NOSTATUS

该证书因不明原因被撤销

REVOKED_STATUS_REMOVEFROMCRL

该证书先前被搁置,现在应该从 CRL 中删除

REVOKED_STATUS_SUPERSEDED

证书已被新证书取代

REVOKED_STATUS_UNSPECIFIED

该证书因不明原因被撤销

TRUSTOTHER

不要验证其他证书

V_CERTSTATUS_GOOD

表示证书未被吊销,但并不一定意味着已颁发证书或此响应在证书的有效期限内

V_CERTSTATUS_REVOKED

表示证书已被永久或暂时吊销(保留)。

V_CERTSTATUS_UNKNOWN

表示响应者不知道所请求的证书。

V_RESPID_KEY

响应者 ID 基于公钥。

V_RESPID_NAME

响应者 ID 基于密钥名称。

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com