def return_ocsp_request_object(cert, issuer, algo, nonce=True): cert_details = ocsp.CertId({ 'issuer_name_hash': getattr(cert.issuer, algo), 'issuer_key_hash': getattr(issuer.public_key, algo), 'hash_algorithm': algos.DigestAlgorithm({'algorithm': algo}), 'serial_number': cert.serial_number, }) request_obj = ocsp.Request({ 'req_cert': cert_details, }) tbs_request_obj = ocsp.TBSRequest( {'request_list': ocsp.Requests([request_obj])}) if nonce: nonce_extension = ocsp.TBSRequestExtension({ 'extn_id': 'nonce', 'critical': True, 'extn_value': core.OctetString(os.urandom(16)), }) tbs_request_obj['request_extensions']: ocsp.TBSRequestExtensions( [nonce_extension]) ocsp_request_obj = ocsp.OCSPRequest({ 'tbs_request': tbs_request_obj, }) return ocsp_request_obj
def fetch(cert, issuer, hash_algo='sha1', nonce=True, user_agent=None, timeout=10): """ Fetches an OCSP response for a certificate :param cert: An asn1cyrpto.x509.Certificate object to get an OCSP reponse for :param issuer: An asn1crypto.x509.Certificate object that is the issuer of cert :param hash_algo: A unicode string of "sha1" or "sha256" :param nonce: A boolean - if the nonce extension should be used to prevent replay attacks :param user_agent: The HTTP user agent to use when requesting the OCSP response. If None, a default is used in the format "certvalidation 1.0.0". :param timeout: The number of seconds after which an HTTP request should timeout :raises: urllib.error.URLError/urllib2.URLError - when a URL/HTTP error occurs socket.error - when a socket error occurs :return: An asn1crypto.ocsp.OCSPResponse object """ if not isinstance(cert, x509.Certificate): raise TypeError( 'cert must be an instance of asn1crypto.x509.Certificate, not %s' % type_name(cert)) if not isinstance(issuer, x509.Certificate): raise TypeError( 'issuer must be an instance of asn1crypto.x509.Certificate, not %s' % type_name(issuer)) if hash_algo not in set(['sha1', 'sha256']): raise ValueError('hash_algo must be one of "sha1", "sha256", not %s' % repr(hash_algo)) if not isinstance(nonce, bool): raise TypeError('nonce must be a bool, not %s' % type_name(nonce)) if user_agent is None: user_agent = 'certvalidator %s' % __version__ elif not isinstance(user_agent, str_cls): raise TypeError('user_agent must be a unicode string, not %s' % type_name(user_agent)) cert_id = ocsp.CertId({ 'hash_algorithm': algos.DigestAlgorithm({'algorithm': hash_algo}), 'issuer_name_hash': getattr(cert.issuer, hash_algo), 'issuer_key_hash': getattr(issuer.public_key, hash_algo), 'serial_number': cert.serial_number, }) request = ocsp.Request({ 'req_cert': cert_id, }) tbs_request = ocsp.TBSRequest({ 'request_list': ocsp.Requests([request]), }) if nonce: nonce_extension = ocsp.TBSRequestExtension({ 'extn_id': 'nonce', 'critical': False, 'extn_value': core.OctetString(core.OctetString(os.urandom(16)).dump()) }) tbs_request['request_extensions'] = ocsp.TBSRequestExtensions( [nonce_extension]) ocsp_request = ocsp.OCSPRequest({ 'tbs_request': tbs_request, }) last_e = None for ocsp_url in cert.ocsp_urls: try: request = Request(ocsp_url) request.add_header('Accept', 'application/ocsp-response') request.add_header('Content-Type', 'application/ocsp-request') request.add_header('User-Agent', user_agent) response = urlopen(request, ocsp_request.dump(), timeout) ocsp_response = ocsp.OCSPResponse.load(response.read()) request_nonce = ocsp_request.nonce_value if ocsp_response['response_status'].native == 'unauthorized': raise errors.OCSPNoMatchesError( 'Unable to verify OCSP response since the responder returned unauthorized' ) response_nonce = ocsp_response.nonce_value if request_nonce and response_nonce and request_nonce.native != response_nonce.native: raise errors.OCSPValidationError( 'Unable to verify OCSP response since the request and response nonces do not match' ) return ocsp_response except (URLError) as e: last_e = e raise last_e