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 MakeOCSPSingleResponse(issuer_name_hash, issuer_key_hash, serial, ocsp_state, ocsp_date): cert_status = None if ocsp_state == OCSP_STATE_REVOKED: cert_status = asn1.Explicit(1, asn1.GeneralizedTime("20100101060000Z")) elif ocsp_state == OCSP_STATE_UNKNOWN: cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 2, 0)) elif ocsp_state == OCSP_STATE_GOOD: cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 0, 0)) elif ocsp_state == OCSP_STATE_MISMATCHED_SERIAL: cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 0, 0)) serial -= 1 else: raise ValueError('Bad OCSP state: ' + str(ocsp_state)) now = datetime.datetime.fromtimestamp(time.mktime(time.gmtime())) if ocsp_date == OCSP_DATE_VALID: thisUpdate = now - datetime.timedelta(days=1) nextUpdate = thisUpdate + datetime.timedelta(weeks=1) elif ocsp_date == OCSP_DATE_OLD: thisUpdate = now - datetime.timedelta(days=1, weeks=1) nextUpdate = thisUpdate + datetime.timedelta(weeks=1) elif ocsp_date == OCSP_DATE_EARLY: thisUpdate = now + datetime.timedelta(days=1) nextUpdate = thisUpdate + datetime.timedelta(weeks=1) elif ocsp_date == OCSP_DATE_LONG: thisUpdate = now - datetime.timedelta(days=365) nextUpdate = thisUpdate + datetime.timedelta(days=366) elif ocsp_date == OCSP_DATE_LONGER: thisUpdate = now - datetime.timedelta(days=367) nextUpdate = thisUpdate + datetime.timedelta(days=368) else: raise ValueError('Bad OCSP date: ' + str(ocsp_date)) return asn1.SEQUENCE([ # SingleResponse asn1.SEQUENCE([ # CertID asn1.SEQUENCE([ # hashAlgorithm HASH_SHA1, None, ]), issuer_name_hash, issuer_key_hash, serial, ]), cert_status, asn1.GeneralizedTime( # thisUpdate thisUpdate.strftime(GENERALIZED_TIME_FORMAT)), asn1.Explicit( # nextUpdate 0, asn1.GeneralizedTime( nextUpdate.strftime(GENERALIZED_TIME_FORMAT))), ])
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)