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)
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)
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)
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())), ]
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
def extension_type(self) -> x509.CertificatePolicies: return x509.CertificatePolicies( policies=[p.for_extension_type for p in self.value])