Пример #1
0
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)
Пример #2
0
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))),
    ])
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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)),
  ]))
Пример #6
0
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)),
        ]))