Пример #1
0
 def test_dump_certificate(self):
     cert = asymmetric.load_certificate(
         os.path.join(fixtures_dir, 'keys/test.crt'))
     pem_serialized = asymmetric.dump_certificate(cert)
     cert_reloaded = asymmetric.load_certificate(pem_serialized)
     self.assertIsInstance(cert_reloaded, asymmetric.Certificate)
     self.assertEqual('rsa', cert_reloaded.algorithm)
Пример #2
0
def pem_armor_certificate(certificate):
    """
    Encodes a certificate into PEM format

    :param certificate:
        An asn1crypto.x509.Certificate object of the certificate to armor.
        Typically this is obtained from CertificateBuilder.build().

    :return:
        A byte string of the PEM-encoded certificate
    """

    return asymmetric.dump_certificate(certificate)
Пример #3
0
def pem_armor_certificate(certificate):
    """
    Encodes a certificate into PEM format

    :param certificate:
        An asn1crypto.x509.Certificate object of the certificate to armor.
        Typically this is obtained from CertificateBuilder.build().

    :return:
        A byte string of the PEM-encoded certificate
    """

    return asymmetric.dump_certificate(certificate)
Пример #4
0
def dump_cert(name, certificate):
    with open(path.join(certs_dir, '{}.crt'.format(name)), 'wb') as f:
        f.write(asymmetric.dump_certificate(certificate))
Пример #5
0
builder = CertificateBuilder(
    {
        "country_name": "US",
        "state_or_province_name": "Massachusetts",
        "locality_name": "Newbury",
        "organization_name": "Codex Non Sufficit LC",
        "common_name": "CodexNS Root CA 1",
    },
    root_ca_public_key,
)
builder.self_signed = True
builder.end_entity = False
root_ca_certificate = builder.build(root_ca_private_key)

with open(os.path.join(fixtures_dir, "root.crt"), "wb") as f:
    f.write(asymmetric.dump_certificate(root_ca_certificate))


root_crl_public_key, root_crl_private_key = asymmetric.generate_pair("rsa", bit_size=2048)

with open(os.path.join(fixtures_dir, "crl_issuer.key"), "wb") as f:
    f.write(asymmetric.dump_private_key(root_crl_private_key, "password123", target_ms=20))

builder = CertificateBuilder(
    {
        "country_name": "US",
        "state_or_province_name": "Massachusetts",
        "locality_name": "Newbury",
        "organization_name": "Codex Non Sufficit LC",
        "common_name": "CodexNS Root CA 1 CRL Issuer",
    },
Пример #6
0
def dump_cert(name, certificate):
    with open(path.join(certs_dir, '{}.crt'.format(name)), 'wb') as f:
        f.write(asymmetric.dump_certificate(certificate))
Пример #7
0
root_ca_private_key = asymmetric.load_private_key(
    os.path.join(fixtures_dir, 'test.key'))
root_ca_certificate = asymmetric.load_certificate(
    os.path.join(fixtures_dir, 'test.crt'))

root_ocsp_public_key, root_ocsp_private_key = asymmetric.generate_pair(
    'rsa', bit_size=2048)

with open(os.path.join(fixtures_dir, 'test-ocsp.key'), 'wb') as f:
    f.write(
        asymmetric.dump_private_key(root_ocsp_private_key,
                                    'password',
                                    target_ms=20))

builder = CertificateBuilder(
    {
        'country_name': 'US',
        'state_or_province_name': 'Massachusetts',
        'locality_name': 'Newbury',
        'organization_name': 'Codex Non Sufficit LC',
        'organization_unit_name': 'Testing',
        'common_name': 'CodexNS OCSP Responder',
    }, root_ocsp_public_key)
builder.extended_key_usage = set(['ocsp_signing'])
builder.issuer = root_ca_certificate
root_ocsp_certificate = builder.build(root_ca_private_key)

with open(os.path.join(fixtures_dir, 'test-ocsp.crt'), 'wb') as f:
    f.write(asymmetric.dump_certificate(root_ocsp_certificate))
Пример #8
0
def _sign(csr,
          buf,
          profile,
          skip_notify=False,
          skip_push=False,
          overwrite=False,
          signer=None):
    # TODO: CRLDistributionPoints, OCSP URL, Certificate URL
    assert buf.startswith(b"-----BEGIN ")
    assert isinstance(csr, CertificationRequest)
    csr_pubkey = asymmetric.load_public_key(
        csr["certification_request_info"]["subject_pk_info"])
    common_name = csr["certification_request_info"]["subject"].native[
        "common_name"]
    cert_path = os.path.join(config.SIGNED_DIR, "%s.pem" % common_name)
    renew = False

    attachments = [
        (buf, "application/x-pem-file", common_name + ".csr"),
    ]

    revoked_path = None
    overwritten = False

    # Move existing certificate if necessary
    if os.path.exists(cert_path):
        with open(cert_path, "rb") as fh:
            prev_buf = fh.read()
            header, _, der_bytes = pem.unarmor(prev_buf)
            prev = x509.Certificate.load(der_bytes)

            # TODO: assert validity here again?
            renew = \
                asymmetric.load_public_key(prev["tbs_certificate"]["subject_public_key_info"]) == \
                csr_pubkey
            # BUGBUG: is this enough?

        if overwrite:
            # TODO: is this the best approach?
            # TODO: why didn't unittest detect bugs here?
            prev_serial_hex = "%x" % prev.serial_number
            revoked_path = os.path.join(config.REVOKED_DIR,
                                        "%040x.pem" % prev.serial_number)
            os.rename(cert_path, revoked_path)
            attachments += [(prev_buf, "application/x-pem-file",
                             "deprecated.crt" if renew else "overwritten.crt")]
            overwritten = True
        else:
            raise FileExistsError("Will not overwrite existing certificate")

    builder = CertificateBuilder(
        cn_to_dn(common_name,
                 const.FQDN,
                 o=certificate["tbs_certificate"]["subject"].native.get(
                     "organization_name"),
                 ou=profile.ou), csr_pubkey)
    builder.serial_number = generate_serial()

    now = datetime.utcnow()
    builder.begin_date = now - const.CLOCK_SKEW_TOLERANCE
    builder.end_date = now + timedelta(days=profile.lifetime)
    builder.issuer = certificate
    builder.ca = profile.ca
    builder.key_usage = profile.key_usage
    builder.extended_key_usage = profile.extended_key_usage
    builder.subject_alt_domains = [common_name]
    builder.ocsp_url = profile.responder_url
    builder.crl_url = profile.revoked_url

    end_entity_cert = builder.build(private_key)
    end_entity_cert_buf = asymmetric.dump_certificate(end_entity_cert)
    with open(cert_path + ".part", "wb") as fh:
        fh.write(end_entity_cert_buf)

    os.rename(cert_path + ".part", cert_path)
    attachments.append(
        (end_entity_cert_buf, "application/x-pem-file", common_name + ".crt"))
    cert_serial_hex = "%x" % end_entity_cert.serial_number

    # Create symlink
    link_name = os.path.join(config.SIGNED_BY_SERIAL_DIR,
                             "%040x.pem" % end_entity_cert.serial_number)
    assert not os.path.exists(
        link_name
    ), "Certificate with same serial number already exists: %s" % link_name
    os.symlink("../%s.pem" % common_name, link_name)

    # Copy filesystem attributes to newly signed certificate
    if revoked_path:
        for key in listxattr(revoked_path):
            if not key.startswith(b"user."):
                continue
            setxattr(cert_path, key, getxattr(revoked_path, key))

    # Attach signer username
    if signer:
        setxattr(cert_path, "user.signature.username", signer)

    if not skip_notify:
        # Send mail
        if renew:  # Same keypair
            mailer.send("certificate-renewed.md", **locals())
        else:  # New keypair
            mailer.send("certificate-signed.md", **locals())

    if not skip_push:
        url = config.LONG_POLL_PUBLISH % hashlib.sha256(buf).hexdigest()
        click.echo("Publishing certificate at %s ..." % url)
        requests.post(url,
                      data=end_entity_cert_buf,
                      headers={
                          "User-Agent": "Certidude API",
                          "Content-Type": "application/x-x509-user-cert"
                      })
        if renew:
            # TODO: certificate-renewed event
            push.publish("certificate-revoked", common_name)
            push.publish("request-signed", common_name)
        else:
            push.publish("request-signed", common_name)
    return end_entity_cert, end_entity_cert_buf
Пример #9
0
 def test_dump_certificate(self):
     cert = asymmetric.load_certificate(os.path.join(fixtures_dir, 'keys/test.crt'))
     pem_serialized = asymmetric.dump_certificate(cert)
     cert_reloaded = asymmetric.load_certificate(pem_serialized)
     self.assertIsInstance(cert_reloaded, asymmetric.Certificate)
     self.assertEqual('rsa', cert_reloaded.algorithm)
Пример #10
0

fixtures_dir = os.path.join(os.path.dirname(__file__), '..', 'tests', 'fixtures')


root_ca_private_key = asymmetric.load_private_key(os.path.join(fixtures_dir, 'test.key'))
root_ca_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, 'test.crt'))

root_ocsp_public_key, root_ocsp_private_key = asymmetric.generate_pair('rsa', bit_size=2048)

with open(os.path.join(fixtures_dir, 'test-ocsp.key'), 'wb') as f:
    f.write(asymmetric.dump_private_key(root_ocsp_private_key, 'password', target_ms=20))

builder = CertificateBuilder(
    {
        'country_name': 'US',
        'state_or_province_name': 'Massachusetts',
        'locality_name': 'Newbury',
        'organization_name': 'Codex Non Sufficit LC',
        'organization_unit_name': 'Testing',
        'common_name': 'CodexNS OCSP Responder',
    },
    root_ocsp_public_key
)
builder.extended_key_usage = set(['ocsp_signing'])
builder.issuer = root_ca_certificate
root_ocsp_certificate = builder.build(root_ca_private_key)

with open(os.path.join(fixtures_dir, 'test-ocsp.crt'), 'wb') as f:
    f.write(asymmetric.dump_certificate(root_ocsp_certificate))
Пример #11
0
def _sign(csr, buf, overwrite=False):
    # TODO: CRLDistributionPoints, OCSP URL, Certificate URL

    assert buf.startswith("-----BEGIN CERTIFICATE REQUEST-----\n")
    assert isinstance(csr, CertificationRequest)
    csr_pubkey = asymmetric.load_public_key(
        csr["certification_request_info"]["subject_pk_info"])
    common_name = csr["certification_request_info"]["subject"].native[
        "common_name"]
    cert_path = os.path.join(config.SIGNED_DIR, "%s.pem" % common_name)
    renew = False

    attachments = [
        (buf, "application/x-pem-file", common_name + ".csr"),
    ]

    revoked_path = None
    overwritten = False

    # Move existing certificate if necessary
    if os.path.exists(cert_path):
        with open(cert_path) as fh:
            prev_buf = fh.read()
            header, _, der_bytes = pem.unarmor(prev_buf)
            prev = x509.Certificate.load(der_bytes)

            # TODO: assert validity here again?
            renew = \
                asymmetric.load_public_key(prev["tbs_certificate"]["subject_public_key_info"]) == \
                csr_pubkey
            # BUGBUG: is this enough?

        if overwrite:
            # TODO: is this the best approach?
            prev_serial_hex = "%x" % prev.serial_number
            revoked_path = os.path.join(config.REVOKED_DIR,
                                        "%s.pem" % prev_serial_hex)
            os.rename(cert_path, revoked_path)
            attachments += [(prev_buf, "application/x-pem-file",
                             "deprecated.crt" if renew else "overwritten.crt")]
            overwritten = True
        else:
            raise EnvironmentError("Will not overwrite existing certificate")

    # Sign via signer process
    builder = CertificateBuilder({u'common_name': common_name}, csr_pubkey)
    builder.serial_number = random.randint(
        0x1000000000000000000000000000000000000000,
        0xffffffffffffffffffffffffffffffffffffffff)

    now = datetime.utcnow()
    builder.begin_date = now - timedelta(minutes=5)
    builder.end_date = now + timedelta(
        days=config.SERVER_CERTIFICATE_LIFETIME
        if server_flags(common_name) else config.CLIENT_CERTIFICATE_LIFETIME)
    builder.issuer = certificate
    builder.ca = False
    builder.key_usage = set([u"digital_signature", u"key_encipherment"])

    # OpenVPN uses CN while StrongSwan uses SAN
    if server_flags(common_name):
        builder.subject_alt_domains = [common_name]
        builder.extended_key_usage = set(
            [u"server_auth", u"1.3.6.1.5.5.8.2.2", u"client_auth"])
    else:
        builder.extended_key_usage = set([u"client_auth"])

    end_entity_cert = builder.build(private_key)
    end_entity_cert_buf = asymmetric.dump_certificate(end_entity_cert)
    with open(cert_path + ".part", "wb") as fh:
        fh.write(end_entity_cert_buf)

    os.rename(cert_path + ".part", cert_path)
    attachments.append(
        (end_entity_cert_buf, "application/x-pem-file", common_name + ".crt"))
    cert_serial_hex = "%x" % end_entity_cert.serial_number

    # Create symlink
    link_name = os.path.join(config.SIGNED_BY_SERIAL_DIR,
                             "%x.pem" % end_entity_cert.serial_number)
    assert not os.path.exists(
        link_name
    ), "Certificate with same serial number already exists: %s" % link_name
    os.symlink("../%s.pem" % common_name, link_name)

    # Copy filesystem attributes to newly signed certificate
    if revoked_path:
        for key in listxattr(revoked_path):
            if not key.startswith("user."):
                continue
            setxattr(cert_path, key, getxattr(revoked_path, key))

    # Send mail
    if renew:  # Same keypair
        mailer.send("certificate-renewed.md", **locals())
    else:  # New keypair
        mailer.send("certificate-signed.md", **locals())

    url = config.LONG_POLL_PUBLISH % hashlib.sha256(buf).hexdigest()
    click.echo("Publishing certificate at %s ..." % url)
    requests.post(url,
                  data=end_entity_cert_buf,
                  headers={
                      "User-Agent": "Certidude API",
                      "Content-Type": "application/x-x509-user-cert"
                  })

    push.publish("request-signed", common_name)
    return end_entity_cert, end_entity_cert_buf
Пример #12
0
def _sign(csr,
          buf,
          skip_notify=False,
          skip_push=False,
          overwrite=False,
          profile="default",
          signer=None):
    # TODO: CRLDistributionPoints, OCSP URL, Certificate URL
    if profile not in config.PROFILES:
        raise ValueError("Invalid profile supplied '%s'" % profile)

    assert buf.startswith(b"-----BEGIN ")
    assert isinstance(csr, CertificationRequest)
    csr_pubkey = asymmetric.load_public_key(
        csr["certification_request_info"]["subject_pk_info"])
    common_name = csr["certification_request_info"]["subject"].native[
        "common_name"]
    cert_path = os.path.join(config.SIGNED_DIR, "%s.pem" % common_name)
    renew = False

    attachments = [
        (buf, "application/x-pem-file", common_name + ".csr"),
    ]

    revoked_path = None
    overwritten = False

    # Move existing certificate if necessary
    if os.path.exists(cert_path):
        with open(cert_path, "rb") as fh:
            prev_buf = fh.read()
            header, _, der_bytes = pem.unarmor(prev_buf)
            prev = x509.Certificate.load(der_bytes)

            # TODO: assert validity here again?
            renew = \
                asymmetric.load_public_key(prev["tbs_certificate"]["subject_public_key_info"]) == \
                csr_pubkey
            # BUGBUG: is this enough?

        if overwrite:
            # TODO: is this the best approach?
            prev_serial_hex = "%x" % prev.serial_number
            revoked_path = os.path.join(config.REVOKED_DIR,
                                        "%s.pem" % prev_serial_hex)
            os.rename(cert_path, revoked_path)
            attachments += [(prev_buf, "application/x-pem-file",
                             "deprecated.crt" if renew else "overwritten.crt")]
            overwritten = True
        else:
            raise FileExistsError("Will not overwrite existing certificate")

    # Sign via signer process
    dn = {u'common_name': common_name}
    profile_server_flags, lifetime, dn[
        "organizational_unit_name"], _ = config.PROFILES[profile]
    lifetime = int(lifetime)

    builder = CertificateBuilder(dn, csr_pubkey)
    builder.serial_number = random.randint(
        0x1000000000000000000000000000000000000000,
        0x7fffffffffffffffffffffffffffffffffffffff)

    now = datetime.utcnow()
    builder.begin_date = now - timedelta(minutes=5)
    builder.end_date = now + timedelta(days=lifetime)
    builder.issuer = certificate
    builder.ca = False
    builder.key_usage = set(["digital_signature", "key_encipherment"])

    # If we have FQDN and profile suggests server flags, enable them
    if server_flags(common_name) and profile_server_flags:
        builder.subject_alt_domains = [
            common_name
        ]  # OpenVPN uses CN while StrongSwan uses SAN to match hostname of the server
        builder.extended_key_usage = set(
            ["server_auth", "1.3.6.1.5.5.8.2.2", "client_auth"])
    else:
        builder.subject_alt_domains = [common_name
                                       ]  # iOS demands SAN also for clients
        builder.extended_key_usage = set(["client_auth"])

    end_entity_cert = builder.build(private_key)
    end_entity_cert_buf = asymmetric.dump_certificate(end_entity_cert)
    with open(cert_path + ".part", "wb") as fh:
        fh.write(end_entity_cert_buf)

    os.rename(cert_path + ".part", cert_path)
    attachments.append(
        (end_entity_cert_buf, "application/x-pem-file", common_name + ".crt"))
    cert_serial_hex = "%x" % end_entity_cert.serial_number

    # Create symlink
    link_name = os.path.join(config.SIGNED_BY_SERIAL_DIR,
                             "%x.pem" % end_entity_cert.serial_number)
    assert not os.path.exists(
        link_name
    ), "Certificate with same serial number already exists: %s" % link_name
    os.symlink("../%s.pem" % common_name, link_name)

    # Copy filesystem attributes to newly signed certificate
    if revoked_path:
        for key in listxattr(revoked_path):
            if not key.startswith(b"user."):
                continue
            setxattr(cert_path, key, getxattr(revoked_path, key))

    # Attach signer username
    if signer:
        setxattr(cert_path, "user.signature.username", signer)

    if not skip_notify:
        # Send mail
        if renew:  # Same keypair
            mailer.send("certificate-renewed.md", **locals())
        else:  # New keypair
            mailer.send("certificate-signed.md", **locals())

    if not skip_push:
        url = config.LONG_POLL_PUBLISH % hashlib.sha256(buf).hexdigest()
        click.echo("Publishing certificate at %s ..." % url)
        requests.post(url,
                      data=end_entity_cert_buf,
                      headers={
                          "User-Agent": "Certidude API",
                          "Content-Type": "application/x-x509-user-cert"
                      })

        push.publish("request-signed", common_name)
    return end_entity_cert, end_entity_cert_buf
Пример #13
0
 def to_pem(self):
     return asymmetric.dump_certificate(self._certificate, encoding='pem')
Пример #14
0
 def to_der(self):
     return asymmetric.dump_certificate(self._certificate, encoding='der')
Пример #15
0
                                    target_ms=20))

builder = CertificateBuilder(
    {
        'country_name': 'US',
        'state_or_province_name': 'Massachusetts',
        'locality_name': 'Newbury',
        'organization_name': 'Codex Non Sufficit LC',
        'common_name': 'CodexNS Root CA 1',
    }, root_ca_public_key)
builder.self_signed = True
builder.end_entity = False
root_ca_certificate = builder.build(root_ca_private_key)

with open(os.path.join(fixtures_dir, 'root.crt'), 'wb') as f:
    f.write(asymmetric.dump_certificate(root_ca_certificate))

root_crl_public_key, root_crl_private_key = asymmetric.generate_pair(
    'rsa', bit_size=2048)

with open(os.path.join(fixtures_dir, 'crl_issuer.key'), 'wb') as f:
    f.write(
        asymmetric.dump_private_key(root_crl_private_key,
                                    'password123',
                                    target_ms=20))

builder = CertificateBuilder(
    {
        'country_name': 'US',
        'state_or_province_name': 'Massachusetts',
        'locality_name': 'Newbury',