def GenerateCertKeyAndOCSP(subject = "127.0.0.1", ocsp_url = "http://127.0.0.1", ocsp_states = None, ocsp_dates = None, ocsp_produced = OCSP_PRODUCED_VALID, ip_sans = ["\x7F\x00\x00\x01"], dns_sans = None, serial = 0): '''GenerateCertKeyAndOCSP returns a (cert_and_key_pem, ocsp_der) where: * cert_and_key_pem contains a certificate and private key in PEM format with the given subject common name and OCSP URL. * ocsp_der contains a DER encoded OCSP response or None if ocsp_url is None''' if ocsp_states is None: ocsp_states = [OCSP_STATE_GOOD] if ocsp_dates is None: ocsp_dates = [OCSP_DATE_VALID] if serial == 0: serial = RandomNumber(16) cert_der = MakeCertificate(ROOT_CN, bytes(subject), serial, LEAF_KEY, ROOT_KEY, bytes(ocsp_url), ip_sans=ip_sans, dns_sans=dns_sans) cert_pem = DERToPEM(cert_der) ocsp_der = None if ocsp_url is not None: if ocsp_states[0] == OCSP_STATE_UNAUTHORIZED: ocsp_der = unauthorizedDER elif ocsp_states[0] == OCSP_STATE_INVALID_RESPONSE: ocsp_der = '3' elif ocsp_states[0] == OCSP_STATE_TRY_LATER: resp = asn1.SEQUENCE([ asn1.ENUMERATED(3), ]) ocsp_der = asn1.ToDER(resp) elif ocsp_states[0] == OCSP_STATE_INVALID_RESPONSE_DATA: invalid_data = asn1.ToDER(asn1.OCTETSTRING('not ocsp data')) basic_resp = asn1.SEQUENCE([ asn1.Raw(invalid_data), asn1.SEQUENCE([ SHA256_WITH_RSA_ENCRYPTION, None, ]), asn1.BitString(ROOT_KEY.Sign(invalid_data)), ]) resp = asn1.SEQUENCE([ asn1.ENUMERATED(0), asn1.Explicit(0, asn1.SEQUENCE([ OCSP_TYPE_BASIC, asn1.OCTETSTRING(asn1.ToDER(basic_resp)), ])), ]) ocsp_der = asn1.ToDER(resp) else: ocsp_der = MakeOCSPResponse( ROOT_CN, ROOT_KEY, serial, ocsp_states, ocsp_dates, ocsp_produced) return (cert_pem + LEAF_KEY_PEM, ocsp_der)
def MakeOCSPResponse(issuer_cn, issuer_key, serial, revoked): # https://tools.ietf.org/html/rfc2560 issuer_name_hash = asn1.OCTETSTRING( hashlib.sha1(asn1.ToDER(Name(cn=issuer_cn))).digest()) issuer_key_hash = asn1.OCTETSTRING( hashlib.sha1(asn1.ToDER(issuer_key)).digest()) cert_status = None if revoked: cert_status = asn1.Explicit(1, asn1.GeneralizedTime("20100101060000Z")) else: cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 0, 0)) basic_resp_data_der = asn1.ToDER( asn1.SEQUENCE([ asn1.Explicit(2, issuer_key_hash), asn1.GeneralizedTime("20100101060000Z"), # producedAt asn1.SEQUENCE([ asn1.SEQUENCE([ # SingleResponse asn1.SEQUENCE([ # CertID asn1.SEQUENCE([ # hashAlgorithm HASH_SHA1, None, ]), issuer_name_hash, issuer_key_hash, serial, ]), cert_status, asn1.GeneralizedTime("20100101060000Z"), # thisUpdate asn1.Explicit( 0, asn1.GeneralizedTime("20300101060000Z")), # nextUpdate ]), ]), ])) basic_resp = asn1.SEQUENCE([ asn1.Raw(basic_resp_data_der), asn1.SEQUENCE([ SHA1_WITH_RSA_ENCRYPTION, None, ]), asn1.BitString(issuer_key.Sign(basic_resp_data_der)), ]) resp = asn1.SEQUENCE([ asn1.ENUMERATED(0), asn1.Explicit( 0, asn1.SEQUENCE([ OCSP_TYPE_BASIC, asn1.OCTETSTRING(asn1.ToDER(basic_resp)), ])) ]) return asn1.ToDER(resp)
def MakeOCSPResponse(issuer_cn, issuer_key, serial, ocsp_states, ocsp_dates, ocsp_produced): # https://tools.ietf.org/html/rfc2560 issuer_name_hash = asn1.OCTETSTRING( hashlib.sha1(asn1.ToDER(Name(cn=issuer_cn))).digest()) issuer_key_hash = asn1.OCTETSTRING( hashlib.sha1(asn1.ToDER(issuer_key)).digest()) now = datetime.datetime.fromtimestamp(time.mktime(time.gmtime())) if ocsp_produced == OCSP_PRODUCED_VALID: producedAt = now - datetime.timedelta(days=1) elif ocsp_produced == OCSP_PRODUCED_BEFORE_CERT: producedAt = datetime.datetime.strptime("19100101050000Z", GENERALIZED_TIME_FORMAT) elif ocsp_produced == OCSP_PRODUCED_AFTER_CERT: producedAt = datetime.datetime.strptime("20321201070000Z", GENERALIZED_TIME_FORMAT) else: raise ValueError('Bad OCSP produced: ' + str(ocsp_produced)) single_responses = [ MakeOCSPSingleResponse(issuer_name_hash, issuer_key_hash, serial, ocsp_state, ocsp_date) for ocsp_state, ocsp_date in itertools.izip(ocsp_states, ocsp_dates) ] basic_resp_data_der = asn1.ToDER( asn1.SEQUENCE([ asn1.Explicit(2, issuer_key_hash), asn1.GeneralizedTime(producedAt.strftime(GENERALIZED_TIME_FORMAT)), asn1.SEQUENCE(single_responses), ])) basic_resp = asn1.SEQUENCE([ asn1.Raw(basic_resp_data_der), asn1.SEQUENCE([ SHA256_WITH_RSA_ENCRYPTION, None, ]), asn1.BitString(issuer_key.Sign(basic_resp_data_der)), ]) resp = asn1.SEQUENCE([ asn1.ENUMERATED(0), asn1.Explicit( 0, asn1.SEQUENCE([ OCSP_TYPE_BASIC, asn1.OCTETSTRING(asn1.ToDER(basic_resp)), ])) ]) return asn1.ToDER(resp)