From a07de31096767abd3b4529ae29c0487c8f21310b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 2 Oct 2018 07:54:31 +0800 Subject: support OCSP response parsing (#4452) * support OCSP response parsing * move the decorator to make pep8 happy * add some missing docs * review feedback * more review feedback --- tests/x509/test_ocsp.py | 137 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) (limited to 'tests/x509/test_ocsp.py') diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index a646f4b7..aeaa6e6c 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -5,6 +5,7 @@ from __future__ import absolute_import, division, print_function import base64 +import datetime import os import pytest @@ -12,6 +13,7 @@ import pytest from cryptography import x509 from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15 from cryptography.x509 import ocsp from .test_x509 import _load_cert @@ -146,3 +148,138 @@ class TestOCSPRequestBuilder(object): b"MEMwQTA/MD0wOzAJBgUrDgMCGgUABBRAC0Z68eay0wmDug1gfn5ZN0gkxAQUw5zz" b"/NNGCDS7zkZ/oHxb8+IIy1kCAj8g" ) + + +class TestOCSPResponse(object): + def test_bad_response(self): + with pytest.raises(ValueError): + ocsp.load_der_ocsp_response(b"invalid") + + def test_load_response(self): + resp = _load_data( + os.path.join("x509", "ocsp", "resp-sha256.der"), + ocsp.load_der_ocsp_response, + ) + from cryptography.hazmat.backends.openssl.backend import backend + issuer = _load_cert( + os.path.join("x509", "letsencryptx3.pem"), + x509.load_pem_x509_certificate, + backend + ) + assert resp.response_status == ocsp.OCSPResponseStatus.SUCCESSFUL + assert (resp.signature_algorithm_oid == + x509.SignatureAlgorithmOID.RSA_WITH_SHA256) + assert resp.signature == base64.b64decode( + b"I9KUlyLV/2LbNCVu1BQphxdNlU/jBzXsPYVscPjW5E93pCrSO84GkIWoOJtqsnt" + b"78DLcQPnF3W24NXGzSGKlSWfXIsyoXCxnBm0mIbD5ZMnKyXEnqSR33Z9He/A+ML" + b"A8gbrDUipGNPosesenkKUnOtFIzEGv29hV5E6AMP2ORPVsVlTAZegPJFbbVIWc0" + b"rZGFCXKxijDxtUtgWzBhpBAI50JbPHi+IVuaOe4aDJLYgZ0BIBNa6bDI+rScyoy" + b"5U0DToV7SZn6CoJ3U19X7BHdYn6TLX0xi43eXuzBGzdHnSzmsc7r/DvkAKJm3vb" + b"dVECXqe/gFlXJUBcZ25jhs70MUA==" + ) + assert resp.tbs_response_bytes == base64.b64decode( + b"MIHWoUwwSjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzA" + b"hBgNVBAMTGkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzGA8yMDE4MDgzMDExMT" + b"UwMFowdTBzMEswCQYFKw4DAhoFAAQUfuZq53Kas/z4oiBkbBahLWBxCF0EFKhKa" + b"mMEfd265tE5t6ZFZe/zqOyhAhIDHHh6fckClQB7xfIiCztSevCAABgPMjAxODA4" + b"MzAxMTAwMDBaoBEYDzIwMTgwOTA2MTEwMDAwWg==" + ) + issuer.public_key().verify( + resp.signature, + resp.tbs_response_bytes, + PKCS1v15(), + hashes.SHA256() + ) + assert resp.certificates == [] + assert resp.responder_key_hash is None + assert resp.responder_name == issuer.subject + assert resp.produced_at == datetime.datetime(2018, 8, 30, 11, 15) + assert resp.certificate_status == ocsp.OCSPCertStatus.GOOD + assert resp.revocation_time is None + assert resp.revocation_reason is None + assert resp.this_update == datetime.datetime(2018, 8, 30, 11, 0) + assert resp.next_update == datetime.datetime(2018, 9, 6, 11, 0) + assert resp.issuer_key_hash == ( + b'\xa8Jjc\x04}\xdd\xba\xe6\xd19\xb7\xa6Ee\xef\xf3\xa8\xec\xa1' + ) + assert resp.issuer_name_hash == ( + b'~\xe6j\xe7r\x9a\xb3\xfc\xf8\xa2 dl\x16\xa1-`q\x08]' + ) + assert isinstance(resp.hash_algorithm, hashes.SHA1) + assert resp.serial_number == 271024907440004808294641238224534273948400 + + def test_load_unauthorized(self): + resp = _load_data( + os.path.join("x509", "ocsp", "resp-unauthorized.der"), + ocsp.load_der_ocsp_response, + ) + assert resp.response_status == ocsp.OCSPResponseStatus.UNAUTHORIZED + with pytest.raises(ValueError): + assert resp.signature_algorithm_oid + with pytest.raises(ValueError): + assert resp.signature + with pytest.raises(ValueError): + assert resp.tbs_response_bytes + with pytest.raises(ValueError): + assert resp.certificates + with pytest.raises(ValueError): + assert resp.responder_key_hash + with pytest.raises(ValueError): + assert resp.responder_name + with pytest.raises(ValueError): + assert resp.produced_at + with pytest.raises(ValueError): + assert resp.certificate_status + with pytest.raises(ValueError): + assert resp.revocation_time + with pytest.raises(ValueError): + assert resp.revocation_reason + with pytest.raises(ValueError): + assert resp.this_update + with pytest.raises(ValueError): + assert resp.next_update + with pytest.raises(ValueError): + assert resp.issuer_key_hash + with pytest.raises(ValueError): + assert resp.issuer_name_hash + with pytest.raises(ValueError): + assert resp.hash_algorithm + with pytest.raises(ValueError): + assert resp.serial_number + + def test_load_revoked(self): + resp = _load_data( + os.path.join("x509", "ocsp", "resp-revoked.der"), + ocsp.load_der_ocsp_response, + ) + assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED + assert resp.revocation_time == datetime.datetime( + 2016, 9, 2, 21, 28, 48 + ) + assert resp.revocation_reason is None + + def test_load_delegate_unknown_cert(self): + resp = _load_data( + os.path.join("x509", "ocsp", "resp-delegate-unknown-cert.der"), + ocsp.load_der_ocsp_response, + ) + assert len(resp.certificates) == 1 + assert isinstance(resp.certificates[0], x509.Certificate) + assert resp.certificate_status == ocsp.OCSPCertStatus.UNKNOWN + + def test_load_responder_key_hash(self): + resp = _load_data( + os.path.join("x509", "ocsp", "resp-responder-key-hash.der"), + ocsp.load_der_ocsp_response, + ) + assert resp.responder_name is None + assert resp.responder_key_hash == ( + b'\x0f\x80a\x1c\x821a\xd5/(\xe7\x8dF8\xb4,\xe1\xc6\xd9\xe2' + ) + + def test_load_revoked_reason(self): + resp = _load_data( + os.path.join("x509", "ocsp", "resp-revoked-reason.der"), + ocsp.load_der_ocsp_response, + ) + assert resp.revocation_reason is x509.ReasonFlags.superseded -- cgit v1.2.3