OpenSSL::OCSP
模块 OpenSSL :: OCSP
OpenSSL :: OCSP 实现在线证书状态协议请求和响应。
创建和发送 OCSP 请求需要在authorityInfoAccess扩展中包含 OCSP URL 的主题证书以及主题证书的颁发者证书。首先,加载发行人和主体证书:
subject = OpenSSL::X509::Certificate.new subject_pem
issuer = OpenSSL::X509::Certificate.new issuer_pem
为了创建请求,我们需要为主题证书创建一个证书 ID,以便 CA 知道我们询问的是哪个证书:
digest = OpenSSL::Digest::SHA1.new
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:
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 请求,并且在本例中不处理任何重定向,所以这对于严重使用是不够的。
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
首先我们检查响应是否有有效签名。没有有效的签名,我们不能相信它。如果您在此遇到故障,则可能缺少系统证书存储或者可能缺少中间证书。
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 都支持随机数。有关返回值的含义,请参阅 OpenSSL :: OCSP :: 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 certificiate'
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
不包括产生的响应时间
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 基于密钥名称。