예제 #1
0
def _decode_certificate_policies(backend, cp):
  cp = backend._ffi.cast("Cryptography_STACK_OF_POLICYINFO *", cp)
  cp = backend._ffi.gc(cp, backend._lib.CERTIFICATEpOLICIES_free)

  num = backend._lib.sk_POLICYINFO_num(cp)
  certificate_policies = []
  for i in range(num):
    qualifiers = None
    pi = backend._lib.sk_POLICYINFO_value(cp, i)
    oid = x509.ObjectIdentifier(_obj2txt(backend, pi.policyid))
    if pi.qualifiers != backend._ffi.NULL:
      qnum = backend._lib.sk_POLICYQUALINFO_value(
        pi.qualifiers, j        
      )
      pqalid = x509.ObjectIdenrifier(
        _obj2txt(backend, pqi.pqualid)        
      )
      if pqualid == CertificatePolicyOID.CPS_QUALIFIER:
        cpsuri = backend._ffi.buffer(
          pqi.d.cpsuri.data, pqi.d.cpsuri.length
        )[:].decode('ascii')
      else:
        assert pqualid == CertificatePoliciesOID.CPS_USER_NOTICE
        user_notice = _decode_user_notice(
          backend, pqi.d.usernotice
        )
        qualifiers.append(user_notice)

    certificate_policies.append(
      x509.CertificatePolicies(oid, qualifiers)        
    )

  return x509.CertificatePolicies(certificate_policies)
예제 #2
0
def _decode_certificate_policies(backend, ext):
    cp = backend._ffi.cast("Cryptography_STACK_OF_POLICYINFO *",
                           backend._lib.X509V3_EXT_d2i(ext))
    assert cp != backend._ffi.NULL
    cp = backend._ffi.gc(cp, backend._lib.sk_POLICYINFO_free)
    num = backend._lib.sk_POLICYINFO_num(cp)
    certificate_policies = []
    for i in range(num):
        qualifiers = None
        pi = backend._lib.sk_POLICYINFO_value(cp, i)
        oid = x509.ObjectIdentifier(_obj2txt(backend, pi.policyid))
        if pi.qualifiers != backend._ffi.NULL:
            qnum = backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers)
            qualifiers = []
            for j in range(qnum):
                pqi = backend._lib.sk_POLICYQUALINFO_value(pi.qualifiers, j)
                pqualid = x509.ObjectIdentifier(_obj2txt(backend, pqi.pqualid))
                if pqualid == x509.OID_CPS_QUALIFIER:
                    cpsuri = backend._ffi.buffer(
                        pqi.d.cpsuri.data,
                        pqi.d.cpsuri.length)[:].decode('ascii')
                    qualifiers.append(cpsuri)
                elif pqualid == x509.OID_CPS_USER_NOTICE:
                    user_notice = _decode_user_notice(backend,
                                                      pqi.d.usernotice)
                    qualifiers.append(user_notice)

        certificate_policies.append(x509.PolicyInformation(oid, qualifiers))

    return x509.CertificatePolicies(certificate_policies)
예제 #3
0
def _decode_certificate_policies(backend, cp):
    cp = backend._ffi.cast("Cryptography_STACK_OF_POLICYINFO *", cp)

    cp_freefunc = backend._ffi.addressof(backend._lib._original_lib,
                                         "POLICYINFO_free")
    cp = backend._ffi.gc(
        cp, lambda c: backend._lib.sk_POLICYINFO_pop_free(c, cp_freefunc))

    num = backend._lib.sk_POLICYINFO_num(cp)
    certificate_policies = []
    for i in range(num):
        qualifiers = None
        pi = backend._lib.sk_POLICYINFO_value(cp, i)
        oid = x509.ObjectIdentifier(_obj2txt(backend, pi.policyid))
        if pi.qualifiers != backend._ffi.NULL:
            qnum = backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers)
            qualifiers = []
            for j in range(qnum):
                pqi = backend._lib.sk_POLICYQUALINFO_value(pi.qualifiers, j)
                pqualid = x509.ObjectIdentifier(_obj2txt(backend, pqi.pqualid))
                if pqualid == CertificatePoliciesOID.CPS_QUALIFIER:
                    cpsuri = backend._ffi.buffer(
                        pqi.d.cpsuri.data,
                        pqi.d.cpsuri.length)[:].decode('ascii')
                    qualifiers.append(cpsuri)
                else:
                    assert pqualid == CertificatePoliciesOID.CPS_USER_NOTICE
                    user_notice = _decode_user_notice(backend,
                                                      pqi.d.usernotice)
                    qualifiers.append(user_notice)

        certificate_policies.append(x509.PolicyInformation(oid, qualifiers))

    return x509.CertificatePolicies(certificate_policies)
예제 #4
0
def _extensions(key: rsa.RSAPrivateKey,
                cert_opts: Dict) -> List[Tuple[bool, x509.Extension]]:  # noqa
    sector = cert_opts['sector']

    # certificate policies
    policies = [
        x509.PolicyInformation(x509.ObjectIdentifier('1.3.76.16'),
                               [x509.UserNotice(None, 'AgIDroot')]),
        x509.PolicyInformation(x509.ObjectIdentifier('1.3.76.16.6'),
                               [x509.UserNotice(None, 'agIDcert')]),
    ]
    if sector == 'private':
        policies.append(
            x509.PolicyInformation(x509.ObjectIdentifier('1.3.76.16.4.3.1'),
                                   [x509.UserNotice(None, 'cert_SP_Priv')]))
    elif sector == 'public':
        policies.append(
            x509.PolicyInformation(x509.ObjectIdentifier('1.3.76.16.4.2.1'),
                                   [x509.UserNotice(None, 'cert_SP_Pub')]))
    else:
        emsg = 'Invalid value for sector (%s)' % sector
        raise Exception(emsg)

    # extensions list
    return [
        # basicCinstraints
        (False, x509.BasicConstraints(ca=False, path_length=None)),
        # keyUsage
        (True,
         x509.KeyUsage(
             digital_signature=True,
             content_commitment=True,
             key_encipherment=False,
             data_encipherment=False,
             key_agreement=False,
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
             decipher_only=False,
         )),
        # certifcatePolicies
        (False, x509.CertificatePolicies(policies)),
        # subjectKeyIdentifier
        (False, x509.SubjectKeyIdentifier.from_public_key(key.public_key())),
    ]
예제 #5
0
def create():
    """
    Create
    :return:
    """
    parent_id = request.args.get("parent")
    parent_cert = Certificate.objects(
        id=parent_id).first() if parent_id else None

    form_default_data = {}

    # @todo how to list meta fields
    # @todo rewrite with a intersect
    field_names = [
        f.name for f in CreateCertificateForm()
        if hasattr(x509.NameOID, f.name)
    ]

    for field_name in field_names:
        # get default value from environment variables
        form_default_data[field_name] = os.environ.get(f"DEFAULT_{field_name}")
        # get default value from parent certificate if any
        if parent_cert:
            for item in parent_cert.cert.subject:
                if item.oid == getattr(x509.NameOID, field_name):
                    form_default_data[field_name] = item.value

    if parent_cert:
        form = CreateCertificateForm(
            data={
                **form_default_data, "duration":
                int(current_app.config.get("DEFAULT_DURATION")),
                "parent":
                parent_cert.cert.serial_number,
                "mode": {
                    "is_server_auth": True,
                    "is_client_auth": True,
                },
                "policy": {
                    "oid": current_app.config.get('DEFAULT_POLICY_OID'),
                    "url": current_app.config.get('DEFAULT_POLICY_URL'),
                },
                "crl": {
                    "url":
                    current_app.config.get("DEFAULT_CA_ISSUER_URL") +
                    url_for("repository.download",
                            id=parent_cert.id,
                            file_format="crl"),
                },
                "aia": {
                    "enabled":
                    True,
                    'ca_issuers':
                    current_app.config.get("DEFAULT_CA_ISSUER_URL") + url_for(
                        "repository.download", id=parent_id,
                        file_format="crt"),
                    'ocsp':
                    current_app.config.get("DEFAULT_OCSP_URL")
                }
            })
    else:
        form = CreateCertificateForm(
            data={
                **form_default_data, "duration":
                10 * int(current_app.config.get("DEFAULT_DURATION")),
                "parent":
                0,
                "mode": {
                    "is_ca": True,
                },
                "policy": {
                    "oid": current_app.config.get('DEFAULT_POLICY_OID'),
                    "url": current_app.config.get('DEFAULT_POLICY_URL'),
                },
                "aia": {
                    "enabled": False,
                    'ca_issuers': current_app.config.get(
                        "DEFAULT_CA_ISSUER_URL"),
                    'ocsp': current_app.config.get("DEFAULT_OCSP_URL")
                }
            })

    if form.validate_on_submit():
        # key
        key = rsa.generate_private_key(public_exponent=65537,
                                       key_size=2048,
                                       backend=default_backend())

        # serial number
        serial_number = x509.random_serial_number()

        # subject
        names = []
        for field_name in field_names:
            if getattr(form, field_name).data:
                names.append(
                    x509.NameAttribute(getattr(x509.NameOID, field_name),
                                       getattr(form, field_name).data))
        subject = x509.Name(names)

        # issuer and signing key
        issuer = parent_cert.cert.subject if parent_cert else subject
        signing_key = parent_cert.key if parent_cert else key

        cert = x509.CertificateBuilder(
        ).subject_name(subject).issuer_name(issuer).public_key(
            key.public_key()).serial_number(serial_number).not_valid_before(
                datetime.utcnow()).not_valid_after(
                    datetime.utcnow() +
                    timedelta(days=int(form.duration.data))).add_extension(
                        x509.SubjectKeyIdentifier.from_public_key(
                            key.public_key()),
                        critical=False).add_extension(
                            x509.AuthorityKeyIdentifier.from_issuer_public_key(
                                signing_key.public_key()),
                            critical=False)

        # basic constraints
        cert = cert.add_extension(x509.BasicConstraints(
            form.mode.data.get('is_ca'), None),
                                  critical=False)

        # ocsp
        if form.aia.data.get("enabled"):
            cert = cert.add_extension(
                x509.AuthorityInformationAccess([
                    # openssl x509 -in 95285781730451486911577519787958288522332983584.crt -ocsp_uri -noout
                    x509.AccessDescription(
                        x509.OID_OCSP,
                        x509.UniformResourceIdentifier(
                            form.aia.data.get('ocsp'))),
                    # @todo validate issuers
                    x509.AccessDescription(
                        x509.OID_CA_ISSUERS,
                        x509.UniformResourceIdentifier(
                            form.aia.data.get('ca_issuers')))
                ]),
                critical=False)

        # key_usage
        if form.mode.data.get('is_ca'):
            cert = cert.add_extension(
                x509.KeyUsage(
                    # 数字签名
                    digital_signature=True,
                    # 认可签名
                    content_commitment=False,
                    # 秘钥加密
                    key_encipherment=False,
                    # 数据加密
                    data_encipherment=False,
                    # 秘钥协商
                    key_agreement=False,
                    # 证书签名
                    key_cert_sign=True,
                    # CRL 签名
                    crl_sign=True,
                    # 仅加密
                    encipher_only=False,
                    # 仅解密
                    decipher_only=False,
                ),
                critical=True)
        else:
            cert = cert.add_extension(x509.KeyUsage(digital_signature=True,
                                                    content_commitment=False,
                                                    key_encipherment=True,
                                                    data_encipherment=True,
                                                    key_agreement=False,
                                                    key_cert_sign=False,
                                                    crl_sign=False,
                                                    encipher_only=False,
                                                    decipher_only=False),
                                      critical=True)

        # extended_key_usage
        # @todo render all extended key usage
        extended_key_usage = []
        if form.mode.data.get('is_server_auth'):
            extended_key_usage.append(x509.oid.ExtendedKeyUsageOID.SERVER_AUTH)
        if form.mode.data.get('is_client_auth'):
            extended_key_usage.append(x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH)
        if len(extended_key_usage):
            cert = cert.add_extension(
                x509.ExtendedKeyUsage(extended_key_usage), critical=False)

        # subject alternative name
        san = []
        for item in form.san.data.split("\n"):
            if item:
                try:
                    ipaddress = IPv4Address(item)
                    san.append(x509.IPAddress(ipaddress))
                except Exception as e:
                    logger.info(e)
                    san.append(x509.DNSName(item))
        if len(san):
            cert = cert.add_extension(x509.SubjectAlternativeName(san),
                                      critical=False)

        # certificate policies
        if form.policy.data.get('url') and form.policy.data.get('oid'):
            cert = cert.add_extension(x509.CertificatePolicies([
                x509.PolicyInformation(
                    x509.ObjectIdentifier(form.policy.data.get('oid')),
                    [form.policy.data.get('url')],
                )
            ]),
                                      critical=False)

        # crl distribution points
        if form.crl.data.get('url'):
            cert = cert.add_extension(x509.CRLDistributionPoints([
                x509.DistributionPoint(
                    full_name=[
                        x509.UniformResourceIdentifier(
                            form.crl.data.get('url'))
                    ],
                    relative_name=None,
                    reasons=None,
                    crl_issuer=None,
                )
            ]),
                                      critical=False)

        # sign
        cert = cert.sign(signing_key, hashes.SHA256(), default_backend())

        # save
        c = Certificate(key=key,
                        cert=cert,
                        serial_number=str(serial_number),
                        pid=parent_cert.id if parent_cert else None)
        c.save()

        flash(f"Certificate create successful")

        return redirect(url_for(".home"))

    return render_template("create.html", form=form)
    def create_smartcard_cert(self,
                              issuer_private_key,
                              private_key,
                              outpath=None):
        subject_entries = [
            (NameOID.COUNTRY_NAME, "US"),
            (NameOID.ORGANIZATION_NAME, "My Company"),
            (NameOID.COMMON_NAME, "*****@*****.**"),
        ]
        issuer_entries = [
            (NameOID.COUNTRY_NAME, "US"),
            (NameOID.ORGANIZATION_NAME, "My Company"),
            (NameOID.COMMON_NAME, "My Company Name"),
        ]

        not_before = datetime.datetime.fromisoformat("2016-08-08 15:15:15")
        not_after = datetime.datetime.fromisoformat("2025-08-08 15:15:15")
        serial_number = x509.random_serial_number()

        aia_descriptions = [
            x509.AccessDescription(
                x509.oid.AuthorityInformationAccessOID.CA_ISSUERS,
                x509.UniformResourceIdentifier(
                    "http://sub.mycompany.com/sica.crt")),
        ]
        eku_usages = [
            x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH,
            x509.oid.ExtendedKeyUsageOID.EMAIL_PROTECTION,
            x509.ObjectIdentifier(
                "1.3.6.1.4.1.311.20.2.2"
            ),  # smartcardLogon (Microsoft enhanced key usage)
        ]
        # basic constraints
        basic_constraints_ca = False
        basic_constraints_pathlen = None

        certificate_policies = [
            x509.PolicyInformation(
                x509.oid.CertificatePoliciesOID.CPS_QUALIFIER,
                ["http://www.mycompany.com/cp/"]),
        ]

        # key usage:  Signing only
        key_usages = [True] + 8 * [False]

        # subject alternative names
        subject_alternative_names = [
            x509.DNSName("*****@*****.**"),
        ]

        crl_distribution_points = [
            x509.DistributionPoint([
                x509.UniformResourceIdentifier(
                    "http://crl.mycompany.com/sica.crl")
            ], None, None, None)
        ]

        extensions = [
            (x509.AuthorityInformationAccess(descriptions=aia_descriptions),
             False),
            (x509.SubjectKeyIdentifier.from_public_key(
                private_key.public_key()), False),
            (x509.BasicConstraints(basic_constraints_ca,
                                   basic_constraints_pathlen), True),
            (x509.AuthorityKeyIdentifier.from_issuer_public_key(
                issuer_private_key.public_key()), False),
            (x509.CertificatePolicies(policies=certificate_policies), False),
            (x509.CRLDistributionPoints(crl_distribution_points), False),
            (x509.KeyUsage(*key_usages), True),
            (x509.ExtendedKeyUsage(usages=eku_usages), False),
            (x509.SubjectAlternativeName(subject_alternative_names), False),
        ]

        cert = self.create_cert(
            not_before,
            not_after,
            serial_number,
            issuer_private_key,  # use issuer private key to sign => do not self sign
            private_key,
            subject_entries=subject_entries,
            issuer_entries=issuer_entries,
            extensions=extensions)

        self.save_to_pem(cert, outpath)

        return cert
    def create_sica_cert(self,
                         issuer_private_key,
                         private_key,
                         outpath=None,
                         ocsp_signing_eku=True):
        subject_entries = [
            (NameOID.COUNTRY_NAME, "US"),
            (NameOID.ORGANIZATION_NAME, "My Company"),
            (NameOID.COMMON_NAME, "My Company Name"),
        ]
        issuer_entries = [
            (NameOID.COUNTRY_NAME, "US"),
            (NameOID.ORGANIZATION_NAME, "Intermediate CA"),
            (NameOID.COMMON_NAME, "Intermediate CA Name"),
        ]

        not_before = datetime.datetime.fromisoformat("2016-02-02 10:10:10")
        not_after = datetime.datetime.fromisoformat("2022-02-02 10:10:10")
        serial_number = x509.random_serial_number()

        aia_descriptions = [
            x509.AccessDescription(
                x509.oid.AuthorityInformationAccessOID.CA_ISSUERS,
                x509.UniformResourceIdentifier(
                    "http://sub.rootca.com/ica.crt")),
            x509.AccessDescription(
                x509.oid.AuthorityInformationAccessOID.OCSP,
                x509.UniformResourceIdentifier("http://ica.ocsp.rootca.com")),
        ]
        eku_usages = [
            x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH,
            x509.oid.ExtendedKeyUsageOID.EMAIL_PROTECTION,
            x509.ObjectIdentifier(
                "1.3.6.1.4.1.311.20.2.2"
            ),  # smartcardLogon (Microsoft enhanced key usage)
        ]
        if ocsp_signing_eku:
            eku_usages.append(x509.oid.ExtendedKeyUsageOID.OCSP_SIGNING)

        # basic constraints
        basic_constraints_ca = True
        basic_constraints_pathlen = 0

        certificate_policies = [
            x509.PolicyInformation(
                x509.oid.CertificatePoliciesOID.CPS_QUALIFIER,
                ["http://www.rootca.com/repo"]),
            x509.PolicyInformation(
                x509.oid.CertificatePoliciesOID.CPS_QUALIFIER,
                ["http://www.mycompany.com/cp/"]),
        ]

        crl_distribution_points = [
            x509.DistributionPoint([
                x509.UniformResourceIdentifier("http://crl.rootca.com/ica.crl")
            ], None, None, None)
        ]

        # key usage:  Certificate Sign and CRL Sign set to True, rest set to False
        key_usages = 5 * [False] + 2 * [True] + 2 * [False]

        extensions = [
            (x509.AuthorityInformationAccess(descriptions=aia_descriptions),
             False),
            (x509.SubjectKeyIdentifier.from_public_key(
                private_key.public_key()), False),
            (x509.BasicConstraints(basic_constraints_ca,
                                   basic_constraints_pathlen), True),
            (x509.AuthorityKeyIdentifier.from_issuer_public_key(
                issuer_private_key.public_key()), False),
            (x509.CertificatePolicies(policies=certificate_policies), False),
            (x509.CRLDistributionPoints(crl_distribution_points), False),
            (x509.KeyUsage(*key_usages), True),
            (x509.ExtendedKeyUsage(usages=eku_usages), False),
        ]

        cert = self.create_cert(
            not_before,
            not_after,
            serial_number,
            issuer_private_key,  # use issuer private key to sign => do not self sign
            private_key,
            subject_entries=subject_entries,
            issuer_entries=issuer_entries,
            extensions=extensions)

        self.save_to_pem(cert, outpath)

        return cert
    def create_ica_cert(self, issuer_private_key, private_key, outpath=None):
        subject_entries = [
            (NameOID.COUNTRY_NAME, "US"),
            (NameOID.ORGANIZATION_NAME, "Intermediate CA"),
            (NameOID.COMMON_NAME, "Intermediate CA Name"),
        ]
        issuer_entries = [
            (NameOID.COUNTRY_NAME, "US"),
            (NameOID.ORGANIZATION_NAME, "Root CA"),
            (NameOID.COMMON_NAME, "Root CA Name"),
        ]

        not_before = datetime.datetime.fromisoformat("2016-01-01 11:11:11")
        not_after = datetime.datetime.fromisoformat("2031-01-01 11:11:11")
        serial_number = x509.random_serial_number()

        aia_descriptions = [
            x509.AccessDescription(
                x509.oid.AuthorityInformationAccessOID.OCSP,
                x509.UniformResourceIdentifier("http://ocsp.rootca.com")),
            x509.AccessDescription(
                x509.oid.AuthorityInformationAccessOID.CA_ISSUERS,
                x509.UniformResourceIdentifier(
                    "http://sub.rootca.com/rca.crt")),
        ]

        # basic constraints
        basic_constraints_ca = True
        basic_constraints_pathlen = None

        certificate_policies = [
            x509.PolicyInformation(x509.oid.CertificatePoliciesOID.ANY_POLICY,
                                   ["http://www.rootca.com/repo"]),
        ]

        crl_distribution_points = [
            x509.DistributionPoint([
                x509.UniformResourceIdentifier("http://crl.rootca.com/rca.crl")
            ], None, None, None)
        ]

        # key usage:  Certificate Sign and CRL Sign set to True, rest set to False
        key_usages = 5 * [False] + 2 * [True] + 2 * [False]

        extensions = [
            (x509.BasicConstraints(basic_constraints_ca,
                                   basic_constraints_pathlen), True),
            (x509.CertificatePolicies(policies=certificate_policies), False),
            (x509.AuthorityInformationAccess(descriptions=aia_descriptions),
             False),
            (x509.KeyUsage(*key_usages), True),
            (x509.AuthorityKeyIdentifier.from_issuer_public_key(
                issuer_private_key.public_key()), False),
            (x509.CRLDistributionPoints(crl_distribution_points), False),
            (x509.SubjectKeyIdentifier.from_public_key(
                private_key.public_key()), False),
        ]

        cert = self.create_cert(not_before,
                                not_after,
                                serial_number,
                                issuer_private_key,
                                private_key,
                                subject_entries=subject_entries,
                                issuer_entries=issuer_entries,
                                extensions=extensions)

        self.save_to_pem(cert, outpath)

        return cert
예제 #9
0
 def extension_type(self) -> x509.CertificatePolicies:
     return x509.CertificatePolicies(
         policies=[p.for_extension_type for p in self.value])