Python 生成数字证书(CA),证书签发,RSA加密,验签

内容待补充。。。。。。

上一篇文章中的 # 测试 RSA 加密结合base64编码 (内容中需要生成的.pem文件在本篇文章中可生成)

代码参考:

# 1. 公钥加密,私钥解密
# 2. 私钥加密,公钥验签

import unittest

class CipherSign(unittest.TestCase):
    """
    密码学中的签名和验签
    """

    def test_rsa(self):
        """
        测试rsa加密
        """
        import base64
        from Crypto import Random
        from Crypto.PublicKey import RSA
        from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
        from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
        from Crypto.Hash import SHA256
        # 伪随机数生成器
        random_generator = Random.new().read
        # rsa算法生成实例
        rsa = RSA.generate(1024, random_generator)
        # master的秘钥对的生成
        private_pem = rsa.exportKey()
        with open("master-private.pem", "wb") as f:
            f.write(private_pem)
        
        public_pem = rsa.publickey().exportKey()
        with open("master-public.pem", "wb") as f:
            f.write(public_pem)
        
        # ghost的秘钥对的生成
        rsa = RSA.generate(1024, random_generator)
        private_pem = rsa.exportKey()
        with open("ghost-private.pem", "wb") as f:
            f.write(private_pem)
        
        public_pem = rsa.publickey().exportKey()
        with open("ghost-public.pem", "wb") as f:
            f.write(public_pem)
        
        # ghost使用master的公钥对数据进行加密
        with open("master-public.pem", "rb") as f:
            key = f.read()
            rsakey = RSA.importKey(key)
            cipher = Cipher_pkcs1_v1_5.new(rsakey)
            text = "ghost"
            cipher_text = base64.b64encode(cipher.encrypt(text.encode()))
            print(cipher_text)
        # master使用自己的私钥对数据进行签名
        with open("master-private.pem", "rb") as f:
            key = f.read()
            rsakey = RSA.importKey(key)
            signer = Signature_pkcs1_v1_5.new(rsakey)
            digest = SHA256.new()
            digest.update(text.encode())
            sign = signer.sign(digest)
            signature = base64.b64encode(sign)
            print(signature)
        
        # ghost使用master的公钥对数据进行验签
        with open("master-public.pem", "rb") as f:
            key = f.read()
            rsakey = RSA.importKey(key)
            verifier = Signature_pkcs1_v1_5.new(rsakey)
            digest = SHA256.new()
            digest.update(text.encode())
            is_verify = verifier.verify(digest, base64.b64decode(signature))
            print(is_verify)

        # master使用自己的私钥对数据进行解密
        with open("master-private.pem", "rb") as f:
            key = f.read()
            rsakey = RSA.importKey(key)
            cipher = Cipher_pkcs1_v1_5.new(rsakey)
            text = cipher.decrypt(base64.b64decode(cipher_text), random_generator)
            print(text.decode())

class CaSign(unittest.TestCase):
    """
    测试证书签发
    数字签名(server):1. 私钥加密,公钥验签
                     2. 公钥加密,私钥解密

    证书签发(CA):1. CA先通过自己的私钥公钥为自己签发证书(ca.crt)
                 2. 服务端通过自己的私钥公钥为生成请求CA签发证书的请求(csr)
                 3. CA通过自己的私钥和自己的签发证书(ca.crt)为服务端签发证书(server.crt)
    英文缩写:
    CA: Certificate Authority
    CSR: Certificate Signing Request
    CRT: Certificate
    PEM: Privacy Enhanced Mail
    """

    def test_create_ca(self):
        """
        测试生成CA证书
        """
        from OpenSSL import crypto

        # 获取秘钥对象
        k = crypto.PKey()
        # 生成RSA秘钥对(这里的2048是秘钥的长度)
        k.generate_key(crypto.TYPE_RSA, 2048)  # generate RSA key-pair
        
        # 生成证书对象
        cert = crypto.X509()

        # 证书的国家名
        cert.get_subject().C = "CN"
        # 证书的州/省名
        cert.get_subject().ST = "GuangDong"
        # 证书的地理位置
        cert.get_subject().L = "ShenZhen"
        # 证书的机构名称
        cert.get_subject().O = "BS, Inc."
        # 证书的机构单元名称
        cert.get_subject().OU = "BS"
        # 证书的通用名称
        cert.get_subject().CN = "localhost"
        # 证书的电子邮箱地址
        cert.get_subject().emailAddress = "123456@qq.com"
        # 添加证书的扩展信息:subjectAltName,创建X509Extension对象,设置IP为127.0.1.1,DNS为localhost,testmysite.com
        cert.add_extensions([crypto.X509Extension(b"subjectAltName", False, b"IP.1:127.0.0.1,DNS.1:localhost,DNS.2:testmysite.com")])
        # 证书的序列号
        cert.set_serial_number(1000)
        # 证书有效期
        cert.gmtime_adj_notBefore(0)
        # 有效期10年
        cert.gmtime_adj_notAfter(10*365*24*60*60)
        # 设置证书签发者
        cert.set_issuer(cert.get_subject())
        # 设置证书公钥
        cert.set_pubkey(k)
        # 签名证书
        cert.sign(k, 'sha256')
        # 保存证书
        open("ca_selfsign.crt", 'wb').write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
        # 保存私钥
        open("ca_private.key", 'wb').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k))
        # 保存公钥
        open("ca_public.key", 'wb').write(crypto.dump_publickey(crypto.FILETYPE_PEM, k))

    def test_parse_ca_crt(self):
        import OpenSSL
        from dateutil import parser

        # cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, open("ca_selfsign.crt").read())
        cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, open("server.crt").read())
        certIssue = cert.get_issuer()

        print ("证书版本:            ",cert.get_version() + 1)

        print ("证书序列号:          ",hex(cert.get_serial_number()))

        print ("证书中使用的签名算法: ",cert.get_signature_algorithm().decode("UTF-8"))

        print ("颁发者:              ",certIssue.commonName)

        print("颁发者信息: ", certIssue.get_components())

        print("颁发对象: ", cert.get_subject().commonName)

        print("颁发对象信息: ", cert.get_subject().get_components())

        datetime_struct = parser.parse(cert.get_notBefore().decode("UTF-8"))

        print ("有效期从:             ",datetime_struct.strftime('%Y-%m-%d %H:%M:%S'))

        datetime_struct = parser.parse(cert.get_notAfter().decode("UTF-8"))

        print ("到:                   ",datetime_struct.strftime('%Y-%m-%d %H:%M:%S'))

        print ("证书是否已经过期:      ",cert.has_expired())

        print("公钥长度" ,cert.get_pubkey().bits())

        print("公钥:\n" ,OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM, cert.get_pubkey()).decode("utf-8"))

        print("颁发者主体信息:")

        print("CN : 通用名称  OU : 机构单元名称")
        print("O  : 机构名    L  : 地理位置")
        print("S  : 州/省名   C  : 国名")

        for item in certIssue.get_components():
            print(item[0].decode("utf-8"), "  ——  ",item[1].decode("utf-8"))
        # 查看证书的扩展信息
        for index in range(cert.get_extension_count()):                                                                                                                                                         
            ext = cert.get_extension(index)
            print("type name: %s, value : %s" % (ext.get_short_name(), ext.get_data()))
        print(cert.get_extension_count())
        subject = cert.get_subject()
        print("域名:\n" ,subject.CN)

    def test_create_csr(self):
        """
        测试服务端生成csr,用于向CA申请证书(server.crt)
        csr: 证书签发请求
        csr = 服务的的公钥 + 服务端的信息
        公钥:被服务端的私钥绑定
        """
        def create_csr(common_name, country=None, state=None, city=None,
                    organization=None, organizational_unit=None,
                    email_address=None):
            """
            Args:
                common_name (str).
                country (str).
                state (str).
                city (str).
                organization (str).
                organizational_unit (str).
                email_address (str).
            Returns:
                (str, str).  Tuple containing private key and certificate
                signing request (PEM).
            """
            import OpenSSL.crypto

            key = OpenSSL.crypto.PKey()
            key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)

            # 类似CA证书签名过程,区别在这是一个证书签发请求(CSR)
            # 证书签发请求(CSR)是一个公钥和一些相关信息,这些信息将包含在最终的证书中     
            req = OpenSSL.crypto.X509Req()
            req.get_subject().CN = common_name
            if country:
                req.get_subject().C = country
            if state:
                req.get_subject().ST = state
            if city:
                req.get_subject().L = city
            if organization:
                req.get_subject().O = organization
            if organizational_unit:
                req.get_subject().OU = organizational_unit
            if email_address:
                req.get_subject().emailAddress = email_address
            # 添加证书的扩展信息:subjectAltName,创建X509Extension对象,设置DNS为localhost
            # 添加了扩展信息,浏览器访问会校验失败:ERR_SSL_SERVER_CERT_BAD_FORMAT。不符合相关安全标准
            # 不扩展python requests访问又需要这个subjectAltName参数
            req.add_extensions([OpenSSL.crypto.X509Extension(b"subjectAltName", False, b"IP.1:127.0.0.1,DNS.1:localhost,DNS.2:testmysite.com")])
            req.set_pubkey(key)
            req.sign(key, 'sha256')

            _private_key = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key).decode("utf-8")
            _public_key = OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM, key).decode("utf-8")
            _csr = OpenSSL.crypto.dump_certificate_request(OpenSSL.crypto.FILETYPE_PEM, req).decode("utf-8")
            with open("server_private.pem", "wb") as f:
                f.write(_private_key.encode())
            with open("server_public.pem", "wb") as f:
                f.write(_public_key.encode())
            with open("server.csr", "wb") as f:
                f.write(_csr.encode())

            return _public_key, _private_key, _csr
    
        common_name = "localhost"
        country = "CN"
        state = "GuangDong"
        city = "ShenZhen"
        organization = "my organization"
        organizational_unit = "my organizational unit"
        email_address = "my email address"
        public_key, private_key, csr = create_csr(common_name, country, state, city, organization, organizational_unit, email_address)
        print("public_key: %s" % public_key)
        print("private_key: %s" % private_key)
        print("csr: %s" % csr)

    def test_sign_server_crt(self):
        """
        测试用ca证书签发服务端证书(将服务端传来的csr文件发送给CA,由CA签发证书crt)
        """
        def sign_csr(csr, ca_crt, ca_key, days=3650):
            """
            Args:
                csr (str): Certificate signing request (PEM).
                ca_crt (str): CA certificate (PEM).
                ca_key (str): CA private key (PEM).
                days (int): Certificate validity period in days.
            Returns:
                str: Signed certificate (PEM).
            """
            import OpenSSL.crypto

            # Convert to OpenSSL objects
            csr_obj = OpenSSL.crypto.load_certificate_request(OpenSSL.crypto.FILETYPE_PEM, csr)
            ca_crt_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, ca_crt)
            ca_key_obj = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, ca_key)

            # Create a new certificate
            cert = OpenSSL.crypto.X509()
            cert.set_subject(csr_obj.get_subject())
            # 将请求者的扩展信息添加到证书中
            cert.add_extensions(csr_obj.get_extensions())
            cert.set_serial_number(0)
            cert.gmtime_adj_notBefore(0)
            cert.gmtime_adj_notAfter(days * 24 * 60 * 60)
            cert.set_issuer(ca_crt_obj.get_subject())
            cert.set_pubkey(csr_obj.get_pubkey())
            cert.sign(ca_key_obj, 'sha256')

            _cert = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert).decode("utf-8")
            with open("server.crt", "wb") as f:
                f.write(_cert.encode())
            return _cert

        csr = open("server.csr").read()
        ca_crt = open("ca_selfsign.crt").read()
        ca_key = open("ca_private.key").read()
        cert = sign_csr(csr, ca_crt, ca_key)
        print("服务端证书: %s" % cert)

    def test_associate_cert_with_pri(self):
        """
        测试生成的证书文件包含的公钥信息(crt)与其私钥的关联
        即:查看证书中的公钥与属于的私钥是否匹配
        """
        def check_associate_cert_with_private_key(cert, private_key):
            """
            :type cert: str
            :type private_key: str
            :rtype: bool
            """
            import OpenSSL
            try:
                private_key_obj = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, private_key)
            except OpenSSL.crypto.Error:
                raise Exception('private key is not correct: %s' % private_key)

            try:
                cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
            except OpenSSL.crypto.Error:
                raise Exception('certificate is not correct: %s' % cert)

            context = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
            context.use_privatekey(private_key_obj)
            context.use_certificate(cert_obj)
            try:
                context.check_privatekey()
                return True
            except OpenSSL.SSL.Error:
                return False
            
        ca_cert_name = "ca_selfsign.crt"
        ca_pri_name = "ca_private.key"
        server_cert_name = "server.crt"
        server_pri_name = "server_private.pem"

        ca_cert = open(ca_cert_name).read()
        ca_private_key = open(ca_pri_name).read()
        server_cert = open(server_cert_name).read()
        server_private_key = open(server_pri_name).read()

        ca_result = check_associate_cert_with_private_key(ca_cert, ca_private_key)
        print("CA的自签证书中的公钥与CA私钥是否关联: %s" % ca_result)
        ca_server_result = check_associate_cert_with_private_key(server_cert, ca_private_key)
        print("服务端证书的公钥与CA私钥是否关联: %s" % ca_server_result)
        server_result = check_associate_cert_with_private_key(server_cert, server_private_key)
        print("服务端证书的公钥与服务端私钥是否关联: %s" % server_result)

    def test_verify_server_crt(self):
        """
        测试服务端的server.crt是否由ca.crt签发
        """
        def verify_cert(cert, ca_cert):
            """
            :type cert: str
            :type ca_cert: str
            :rtype: bool
            """
            import OpenSSL
            try:
                cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
            except OpenSSL.crypto.Error:
                raise Exception('certificate is not correct: %s' % cert)

            try:
                ca_cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, ca_cert)
            except OpenSSL.crypto.Error:
                raise Exception('ca certificate is not correct: %s' % ca_cert)

            store = OpenSSL.crypto.X509Store()
            store.add_cert(ca_cert_obj)
            store_ctx = OpenSSL.crypto.X509StoreContext(store, cert_obj)
            try:
                store_ctx.verify_certificate()
                return True
            except OpenSSL.crypto.X509StoreContextError:
                return False

        ca_cert_name = "ca_selfsign.crt"
        server_cert_name = "server.crt"

        ca_cert = open(ca_cert_name).read()
        server_cert = open(server_cert_name).read()

        result = verify_cert(server_cert, ca_cert)
        print("服务端证书是否由CA证书签发: %s" % result)

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
当然可以,以下是生成证书Python 代码: ```python from cryptography import x509 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.x509.oid import NameOID # 生成 RSA 密钥对 private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, ) # 创建 X.509 证书 subject = issuer = x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Beijing"), x509.NameAttribute(NameOID.LOCALITY_NAME, "Beijing"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, "CSDN"), x509.NameAttribute(NameOID.COMMON_NAME, "CSDN Root CA"), ]) cert = x509.CertificateBuilder().subject_name( subject ).issuer_name( issuer ).public_key( private_key.public_key() ).serial_number( x509.random_serial_number() ).not_valid_before( datetime.datetime.utcnow() ).not_valid_after( datetime.datetime.utcnow() + datetime.timedelta(days=365) ).add_extension( x509.BasicConstraints(ca=True, path_length=None), critical=True, ).sign(private_key, hashes.SHA256()) # 将证书和私钥保存到文件 with open("root_cert.pem", "wb") as f: f.write(cert.public_bytes(serialization.Encoding.PEM)) with open("root_key.pem", "wb") as f: f.write(private_key.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption(), )) ``` 接下来,使用根证书签发加密证书Python 代码如下: ```python from cryptography import x509 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.x509.oid import NameOID # 读取根证书和私钥 with open("root_cert.pem", "rb") as f: root_cert = x509.load_pem_x509_certificate(f.read()) with open("root_key.pem", "rb") as f: root_key = serialization.load_pem_private_key( f.read(), password=None, ) # 生成 RSA 密钥对 private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, ) # 创建 X.509 证书 subject = x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Beijing"), x509.NameAttribute(NameOID.LOCALITY_NAME, "Beijing"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, "CSDN"), x509.NameAttribute(NameOID.COMMON_NAME, "www.csdn.net"), ]) cert = x509.CertificateBuilder().subject_name( subject ).issuer_name( root_cert.subject ).public_key( private_key.public_key() ).serial_number( x509.random_serial_number() ).not_valid_before( datetime.datetime.utcnow() ).not_valid_after( datetime.datetime.utcnow() + datetime.timedelta(days=365) ).add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True, ).sign(root_key, hashes.SHA256()) # 将证书和私钥保存到文件 with open("cert.pem", "wb") as f: f.write(cert.public_bytes(serialization.Encoding.PEM)) with open("key.pem", "wb") as f: f.write(private_key.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption(), )) ``` 希望这些代码能够帮助你生成证书加密证书

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值