Spec-Zone.ru › Ruby 3

модуль OpenSSL::OCSP

OpenSSL::OCSP реализует запросы и ответы протокола Online Certificate Status Protocol.

Создание и отправка запроса OCSP требует сертификата субъекта, содержащего URL OCSP в расширении authorityInfoAccess, и сертификата издателя для сертификата субъекта. Сначала загрузите сертификаты издателя и субъекта:

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

Для создания запроса нам необходимо создать идентификатор сертификата для сертификата субъекта, чтобы CA знал, о каком сертификате мы спрашиваем:

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

Затем создайте запрос и добавьте в него идентификатор сертификата:

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.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 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

Не включать время producedAt в ответе

NOVERIFY

Не проверять ответ вообще

RESPID_KEY

Идентифицировать ответ, подписав идентификатор ключа сертификата

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

Идентификатор ответчика основан на открытом ключе.

V_RESPID_NAME

Идентификатор ответчика основан на имени ключа.

Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API