模块 OpenSSL::OCSP

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

创建和发送 OCSP 请求需要一个包含 OCSP URL 的 authorityInfoAccess 扩展的主题证书,以及主题证书的发行方证书。首先,加载发行方证书和主题证书

subject = OpenSSL::X509::Certificate.new subject_pem
issuer  = OpenSSL::X509::Certificate.new issuer_pem

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

digest = OpenSSL::Digest.new('SHA1')
certificate_id =
  OpenSSL::OCSP::CertificateId.new subject, issuer, digest

然后创建一个请求并将证书 ID 添加到其中

request = OpenSSL::OCSP::Request.new
request.add_certid certificate_id

向请求添加 nonce 可以防止重放攻击,但并非所有 CA 都处理 nonce。

request.add_nonce

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

ocsp_uris = subject.ocsp_uris

require 'uri'

ocsp_uri = URI ocsp_uris[0]

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

require 'net/http'

http_response =
  Net::HTTP.start ocsp_uri.hostname, ocsp_uri.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

首先,我们检查响应是否具有有效的签名。如果没有有效的签名,我们就无法信任它。如果您在此处遇到失败,可能是您缺少系统证书存储或缺少中间证书。

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

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

puts response.status_string #=> successful

接下来,我们需要了解响应详细信息,以确定响应是否与我们的请求匹配。首先,我们检查 nonce。同样,并非所有 CA 都支持 nonce。有关返回值的含义,请参见 Request#check_nonce

p request.check_nonce basic_response #=> value from -1 to 3

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

single_response = basic_response.find_response(certificate_id)

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

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

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

不要在响应中包含 producedAt 时间

NOVERIFY

不要验证响应

RESPID_KEY

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

RESPONSE_STATUS_INTERNALERROR

颁发者内部错误

RESPONSE_STATUS_MALFORMEDREQUEST

非法确认请求

RESPONSE_STATUS_SIGREQUIRED

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

RESPONSE_STATUS_SUCCESSFUL

Response 有效的确认

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 基于密钥名称。