求助:为什么证书不受信任(CA已经导入了)

代码

import os
import datetime
from cryptography import x509
from cryptography.x509 import CertificateBuilder
from cryptography.x509.oid import NameOID
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import Encoding


def generate_ssl(
        C: str = 'CN', ST: str = 'Shanghai', L: str = 'Shanghai', O: str = '', OU: str = '',
        CN: str = '', SANS=None, days: int = 730
):
    """
    默认使用RSA2048
    :param C: 国家
    :param ST: 省份
    :param L: 城市
    :param O: 组织
    :param OU: 组织单位
    :param CN: 通用名
    :param SANS: 备用名
    :param days: 有效期(天),从当日开始计算
    :return: crt, key
    """
    if SANS is None:
        SANS = []
    root_crt = os.path.join(os.getcwd(), "cer/root/root.crt")
    root_key = os.path.join(os.getcwd(), "cer/root/root.key.pem")
    # 使用CA证书签发新证书
    csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
        x509.NameAttribute(NameOID.COUNTRY_NAME, C),
        x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, ST),
        x509.NameAttribute(NameOID.LOCALITY_NAME, L),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, O),
        x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, OU),
        x509.NameAttribute(NameOID.COMMON_NAME, CN),
    ]))
    # SAN
    san = [x509.DNSName(i) for i in SANS]
    csr = csr.add_extension(
        x509.SubjectAlternativeName(san),
        critical=False,
    )
    # CA签名CSR
    new_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
    csr = csr.sign(new_key, hashes.SHA256(), default_backend())
    builder = CertificateBuilder()
    builder = builder.issuer_name(csr.subject)
    builder = builder.subject_name(csr.subject)
    builder = builder.public_key(csr.public_key())
    builder = builder.serial_number(x509.random_serial_number())
    builder = builder.not_valid_before(datetime.datetime.utcnow())
    builder = builder.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=days))
    builder = builder.add_extension(
        x509.SubjectAlternativeName(san),
        critical=False,
    )
    # 签发证书
    with open(root_key, "rb") as key_file:
        ca_private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None,
            backend=default_backend()
        )
    cert = builder.sign(ca_private_key, hashes.SHA256(), default_backend())
    _crt = cert.public_bytes(Encoding.PEM)
    # 生成证书链
    _crt = _crt + open(root_crt, 'rb').read()
    # 私钥PEM格式
    _key = new_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption()
    )
    return _crt, _key


if __name__ == '__main__':
    _crt, _key = generate_ssl(
        C='CN', ST='Shanghai', L='Shanghai', O='', OU='', CN='192.168.176.138', days=730,
        SANS=['192.168.176.138', '192.168.1.1']
    )
    print(_crt.decode())
    print(_key.decode())

mark,学习一下

我的理解,你只是生成了个证书,但你生成的证书并不被浏览器信任的,被信任的证书是要特定机构签发的

免费为ip添加ssl证书 - 网络安全 - LINUX DO

CA已经导入了…

值得注意到的应该是subject alt name应该是必填的,里面应该是你的域名、ip信息

之前我是吃过类似的亏,在中文chrome查看的话,应该叫主题备用名称

---------更新
好吧,刚刚没看你的代码,你有写sns,但是应该也还是可以通过F12来查看具体的问题

1 个赞

根证书添加信任了吗

1 个赞

要确认是否是这个问题可以利用好DevTools | Security,操作方法是F12或者右键-检查,切换到安全tab页面,证书的问题会显示在这

另一个思路,你在导入根证书后有尝试过重启浏览器么?有在证书管理器中确认是否在受信任的根证书颁发机构中有你的自签发证书么?

mark

看起来你对IP和域名哪里的设置都是正确的,问题应该在:
网站上需要使用的必须是用根证书签发的站点证书,并且时间不能超过365天。这样导入根证书之后,才可以正确的使用。
大概过程是:

  1. 自行签发一个根证书(可以长期使用,用于签发站点证书,有效期可以设置较长例如10年)
  2. 自行签发一个站点证书(当前站点使用,有效期最大只能设置为365天)
  3. 使用步骤1中生成的根证书对步骤2中生成的子证书进行签名

必须要有签发过程,不然浏览器不认可。

这样会得到一个根证书和一个站点证书。将根证书导入你的操作系统的受信任的根证书颁发机构,将站点证书配置到你的站点。后边就是每隔1年,新生成一个站点证书,并用根证书再对站点证书签名,配置到你的站点中。