module OpenSSL::OCSP

OpenSSL::OCSP implementiert Online Certificate Status Protocol-Anfragen und -Antworten.

Um eine OCSP-Anfrage zu erstellen und zu senden, wird ein Subjektzertifikat benötigt, das eine OCSP-URL in einer authorityInfoAccess-Erweiterung enthält, sowie das Ausstellerzertifikat für das Subjektzertifikat. Laden Sie zuerst die Aussteller- und Subjektzertifikate.

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

Um die Anfrage zu erstellen, müssen wir eine Zertifikats-ID für das Subjektzertifikat erstellen, damit die CA weiß, nach welchem Zertifikat wir fragen.

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

Erstellen Sie dann eine Anfrage und fügen Sie die Zertifikats-ID hinzu.

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

Das Hinzufügen eines Nonce zur Anfrage schützt vor Replay-Angriffen, aber nicht alle CAs verarbeiten den Nonce.

request.add_nonce

Um die Anfrage zur Verifizierung an die CA zu übermitteln, müssen wir die OCSP URI aus dem Subjektzertifikat extrahieren.

ocsp_uris = subject.ocsp_uris

require 'uri'

ocsp_uri = URI ocsp_uris[0]

Um die Anfrage zu übermitteln, werden wir die Anfrage per POST an die OCSP URI senden (gemäß RFC 2560). Beachten Sie, dass wir in diesem Beispiel nur HTTP-Anfragen verarbeiten und keine Weiterleitungen handhaben, daher ist dies für den ernsthaften Gebrauch unzureichend.

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

Zuerst prüfen wir, ob die Antwort eine gültige Signatur hat. Ohne eine gültige Signatur können wir ihr nicht vertrauen. Wenn Sie hier einen Fehler erhalten, fehlt Ihnen möglicherweise ein Systemzertifikatsspeicher oder Zwischenzertifikate.

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

Die Antwort enthält die Statusinformationen (Erfolg/Fehler). Wir können den Status als String anzeigen.

puts response.status_string #=> successful

Als Nächstes müssen wir die Antwortdetails kennen, um zu bestimmen, ob die Antwort mit unserer Anfrage übereinstimmt. Zuerst prüfen wir den Nonce. Auch hier unterstützen nicht alle CAs einen Nonce. Sehen Sie Request#check_nonce für die Bedeutung der Rückgabewerte.

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

Extrahieren Sie dann die Statusinformationen für das Zertifikat aus der Basisantwort.

single_response = basic_response.find_response(certificate_id)

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

Prüfen Sie dann die Gültigkeit. Ein zukünftig ausgestellter Status muss abgelehnt werden.

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