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)
def ToDER(self): return asn1.ToDER(asn1.SEQUENCE([self.m, self.e]))
def MakeCertificate( issuer_cn, subject_cn, serial, pubkey, privkey, ocsp_url = None, ca_issuers_url = None, is_ca=False, path_len=None, ip_sans=None, dns_sans=None): '''MakeCertificate returns a DER encoded certificate, signed by privkey.''' extensions = asn1.SEQUENCE([]) # Default subject name fields c = "XX" o = "Testing Org" if is_ca: # Root certificate. c = None o = None extensions.children.append( asn1.SEQUENCE([ BASIC_CONSTRAINTS, True, asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE([ True, # IsCA ] + ([path_len] if path_len is not None else []) # Path len ))), ])) if ip_sans is not None or dns_sans is not None: sans = [] if dns_sans is not None: for dns_name in dns_sans: sans.append( asn1.Raw(asn1.TagAndLength(0x82, len(dns_name)) + dns_name)) if ip_sans is not None: for ip_addr in ip_sans: sans.append( asn1.Raw(asn1.TagAndLength(0x87, len(ip_addr)) + ip_addr)) extensions.children.append( asn1.SEQUENCE([ SUBJECT_ALTERNATIVE_NAME, # There is implicitly a critical=False here. Since false is the # default, encoding the value would be invalid DER. asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE(sans))) ])) if ocsp_url is not None or ca_issuers_url is not None: aia_entries = [] if ocsp_url is not None: aia_entries.append( asn1.SEQUENCE([ AIA_OCSP, asn1.Raw(asn1.TagAndLength(0x86, len(ocsp_url)) + ocsp_url), ])) if ca_issuers_url is not None: aia_entries.append( asn1.SEQUENCE([ AIA_CA_ISSUERS, asn1.Raw(asn1.TagAndLength(0x86, len(ca_issuers_url)) + ca_issuers_url), ])) extensions.children.append( asn1.SEQUENCE([ AUTHORITY_INFORMATION_ACCESS, # There is implicitly a critical=False here. Since false is the default, # encoding the value would be invalid DER. asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE(aia_entries))), ])) extensions.children.append( asn1.SEQUENCE([ CERT_POLICIES, # There is implicitly a critical=False here. Since false is the default, # encoding the value would be invalid DER. asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE([ asn1.SEQUENCE([ # PolicyInformation CERT_POLICY_OID, ]), ]))), ]) ) tbsCert = asn1.ToDER(asn1.SEQUENCE([ asn1.Explicit(0, 2), # Version serial, asn1.SEQUENCE([SHA256_WITH_RSA_ENCRYPTION, None]), # SignatureAlgorithm Name(cn = issuer_cn), # Issuer asn1.SEQUENCE([ # Validity asn1.UTCTime("100101060000Z"), # NotBefore asn1.UTCTime("321201060000Z"), # NotAfter ]), Name(cn = subject_cn, c = c, o = o), # Subject asn1.SEQUENCE([ # SubjectPublicKeyInfo asn1.SEQUENCE([ # Algorithm PUBLIC_KEY_RSA, None, ]), asn1.BitString(asn1.ToDER(pubkey)), ]), asn1.Explicit(3, extensions), ])) return asn1.ToDER(asn1.SEQUENCE([ asn1.Raw(tbsCert), asn1.SEQUENCE([ SHA256_WITH_RSA_ENCRYPTION, None, ]), asn1.BitString(privkey.Sign(tbsCert)), ]))
def MakeCertificate(issuer_cn, subject_cn, serial, pubkey, privkey, ocsp_url=None): '''MakeCertificate returns a DER encoded certificate, signed by privkey.''' extensions = asn1.SEQUENCE([]) # Default subject name fields c = "XX" o = "Testing Org" if issuer_cn == subject_cn: # Root certificate. c = None o = None extensions.children.append( asn1.SEQUENCE([ BASIC_CONSTRAINTS, True, asn1.OCTETSTRING( asn1.ToDER(asn1.SEQUENCE([ True, # IsCA 0, # Path len ]))), ])) if ocsp_url is not None: extensions.children.append( asn1.SEQUENCE([ AUTHORITY_INFORMATION_ACCESS, # There is implicitly a critical=False here. Since false is the default, # encoding the value would be invalid DER. asn1.OCTETSTRING( asn1.ToDER( asn1.SEQUENCE([ asn1.SEQUENCE([ AIA_OCSP, asn1.Raw( asn1.TagAndLength(0x86, len(ocsp_url)) + ocsp_url), ]), ]))), ])) extensions.children.append( asn1.SEQUENCE([ CERT_POLICIES, # There is implicitly a critical=False here. Since false is the default, # encoding the value would be invalid DER. asn1.OCTETSTRING( asn1.ToDER( asn1.SEQUENCE([ asn1.SEQUENCE([ # PolicyInformation CERT_POLICY_OID, ]), ]))), ])) tbsCert = asn1.ToDER( asn1.SEQUENCE([ asn1.Explicit(0, 2), # Version serial, asn1.SEQUENCE([SHA256_WITH_RSA_ENCRYPTION, None]), # SignatureAlgorithm Name(cn=issuer_cn), # Issuer asn1.SEQUENCE([ # Validity asn1.UTCTime("100101060000Z"), # NotBefore asn1.UTCTime("321201060000Z"), # NotAfter ]), Name(cn=subject_cn, c=c, o=o), # Subject asn1.SEQUENCE([ # SubjectPublicKeyInfo asn1.SEQUENCE([ # Algorithm PUBLIC_KEY_RSA, None, ]), asn1.BitString(asn1.ToDER(pubkey)), ]), asn1.Explicit(3, extensions), ])) return asn1.ToDER( asn1.SEQUENCE([ asn1.Raw(tbsCert), asn1.SEQUENCE([ SHA256_WITH_RSA_ENCRYPTION, None, ]), asn1.BitString(privkey.Sign(tbsCert)), ]))