ChatGPT解决这个技术问题 Extra ChatGPT

如何使用 OpenSSL 生成自签名 SSL 证书?

我正在向嵌入式 Linux 设备添加 HTTPS 支持。我尝试使用以下步骤生成自签名证书:

openssl req -new > cert.csr
openssl rsa -in privkey.pem -out key.pem
openssl x509 -in cert.csr -out cert.pem -req -signkey key.pem -days 1001
cat key.pem>>cert.pem

这可行,但我遇到了一些错误,例如,谷歌浏览器:

这可能不是您要找的网站!该站点的安全证书不受信任!

我错过了什么吗?这是构建自签名证书的正确方法吗?

对于 Internet,自签名证书被认为是不安全的。 Firefox 会将该站点视为具有无效证书,而 Chrome 会认为该连接是纯 HTTP。更多详情:gerv.net/security/self-signed-certs
您需要将 CA 证书导入浏览器并告诉浏览器您信任该证书 - 或 - 由浏览器信任的大型无偿组织之一对其进行签名 - 或 - 忽略警告并单击过去了。我自己喜欢最后一个选项。
您不应该使用这样的“库存” OpenSSL 设置。这是因为您不能将 DNS 名称放在使用者备用名称 (SAN) 中。您需要提供带有 alternate_names 部分的配置文件并使用 -config 选项传递它。此外,IETF 和 CA/浏览器论坛均不赞成(但不禁止)将 DNS 名称放在通用名称 (CN) 中。 CN 中的任何 DNS 名称也必须存在于 SAN 中。没有办法避免使用 SAN。请参阅下面的答案。
除了@jww 的评论。 2017 年 5 月 Chrome 不再接受没有(emtpy)SAN 的证书:“该站点的证书不包含包含域名或 IP 地址的主题备用名称扩展。”
如今,只要您的网络服务器可以通过 Internet 的 80 端口上的 FQDN 访问,您就可以使用 LetsEncrypt 并获得免费的完整 CA 证书(有效期为 90 天,可以自动续订),不会发出任何浏览器警告/消息。 www.letsencrypt.com

M
Mark Amery

您可以在一个命令中执行此操作:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365

如果您不想使用密码保护您的私钥,也可以添加 -nodes(“no DES”的缩写)。否则它将提示您输入“至少 4 个字符”的密码。

您可以将 days 参数 (365) 替换为任何数字以影响到期日期。然后它会提示您输入“国家名称”之类的内容,但您只需点击 Enter 并接受默认值即可。

添加 -subj '/CN=localhost' 以隐藏有关证书内容的问题(将 localhost 替换为您想要的域)。

除非您之前将自签名证书导入浏览器,否则不会向任何第三方验证自签名证书。如果您需要更高的安全性,您应该使用由 certificate authority (CA) 签名的证书。


对于任何感兴趣的人,如果您想自己验证任何内容,这里是 the documentation
与第 3 方签署如何提供更高的安全性?
对于在自动化中使用它的任何其他人,以下是该主题的所有常用参数:-subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=www.example.com"
@JamesMills 我的意思是,想想看——如果一个看起来阴暗的家伙在他的货车侧面写着“免费糖果”邀请你进来,你完全会三思而后行并保持警惕——但是如果你信任的人——就像真正信任的人——都是这样的,“老兄,他是合法的”,你就会全心全意地享受免费的糖果。
请记住使用 -sha256 生成基于 SHA-256 的证书。
C
Community

我错过了什么吗?这是构建自签名证书的正确方法吗?

创建自签名证书很容易。您只需使用 openssl req 命令。创建一个可供最多选择的客户端使用的客户端可能会很棘手,例如浏览器和命令行工具。

这很困难,因为浏览器有自己的一组要求,而且它们比 IETF 更严格。浏览器使用的要求记录在 CA/Browser Forums 中(请参阅下面的参考资料)。限制出现在两个关键领域:(1) 信任锚,和 (2) DNS 名称。

现代浏览器(如我们在 2014/2015 年使用的warez)需要一个链接回信任锚的证书,并且他们希望在证书中以特定方式显示 DNS 名称。浏览器正在积极反对自签名服务器证书。

某些浏览器并不完全可以轻松导入自签名服务器证书。事实上,你不能用一些浏览器,比如Android的浏览器。所以完整的解决方案是成为你自己的权威。

在没有成为您自己的权威的情况下,您必须获得正确的 DNS 名称才能使证书获得最大的成功机会。但我会鼓励你成为自己的权威。成为自己的权威很容易,它会回避所有信任问题(谁比自己更值得信任?)。

这可能不是您要找的网站!该站点的安全证书不受信任!

这是因为浏览器使用预定义的信任锚列表来验证服务器证书。自签名证书不会链接回受信任的锚点。

避免这种情况的最佳方法是:

创建您自己的授权(即成为 CA) 为服务器创建证书签名请求 (CSR) 使用您的 CA 密钥签署服务器的 CSR 在服务器上安装服务器证书 在客户端上安装 CA 证书

第 1 步 - 创建您自己的权限 只是意味着使用 CA: true 和正确的密钥用法创建一个自签名证书。这意味着 SubjectIssuer 是同一个实体,CA 在 Basic Constraints 中设置为 true(也应标记为关键),密钥用法是 keyCertSigncrlSign(如果您使用 CRL),Subject Key Identifier (SKI) 与 Authority Key Identifier (AKI) 相同)。

要成为您自己的证书颁发机构,请参阅 Stack Overflow 上的 *How do you sign a certificate signing request with your certification authority?。然后,将您的 CA 导入浏览器使用的信任库。

步骤 2 - 4 大致是您现在为面向公众的服务器所做的,当您征用像 StartcomCAcert 这样的 CA 的服务时。步骤 1 和 5 可以让您避开第三方权威,并充当自己的权威(谁比自己更值得信任?)。

避免浏览器警告的下一个最佳方法是信任服务器的证书。但是有些浏览器,比如 Android 的默认浏览器,不允许你这样做。所以它永远不会在平台上工作。

浏览器(和其他类似的用户代理)不信任自签名证书的问题将成为物联网 (IoT) 中的一个大问题。例如,当您连接到恒温器或冰箱对其进行编程时会发生什么?答案是,就用户体验而言,没什么好说的。

W3C 的 WebAppSec 工作组开始研究这个问题。例如,参见 Proposal: Marking HTTP As Non-Secure

如何使用 OpenSSL 创建自签名证书

下面的命令和配置文件创建一个自签名证书(它还向您展示了如何创建一个签名请求)。它们在一个方面与其他答案不同:用于自签名证书的 DNS 名称在主题备用名称 (SAN) 中,而不是在通用名称 (CN) 中。

DNS 名称通过配置文件的 subjectAltName = @alternate_names 行放置在 SAN 中(无法通过命令行进行)。然后在配置文件中有一个 alternate_names 部分(您应该根据自己的喜好调整它):

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# IP.1        = 127.0.0.1
# IP.2        = ::1

将 DNS 名称放在 SAN 而不是 CN 中很重要,因为 IETF 和 CA/浏览器论坛都指定了这种做法。他们还指定不推荐使用 CN 中的 DNS 名称(但不禁止)。如果您将 DNS 名称放在 CN 中,则它必须包含在 CA/B 策略下的 SAN 中。所以你不能避免使用主题备用名称。

如果您不将 DNS 名称放在 SAN 中,则证书将无法在遵循 CA/浏览器论坛指南的浏览器和其他用户代理下验证。

相关:浏览器遵循 CA/浏览器论坛政策;而不是 IETF 政策。这就是使用 OpenSSL(通常遵循 IETF)创建的证书有时无法在浏览器下验证的原因之一(浏览器遵循 CA/B)。它们是不同的标准,它们有不同的发布政策和不同的验证要求。

创建自签名证书(注意添加了 -x509 选项):

openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.cert.pem

创建签名请求(注意缺少 -x509 选项):

openssl req -config example-com.conf -new -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.req.pem

打印自签名证书:

openssl x509 -in example-com.cert.pem -text -noout

打印签名请求:

openssl req -in example-com.req.pem -text -noout

配置文件(通过 -config 选项传递)

[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = NY

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here because it's presented to the user. The server's DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums. If you place a DNS name here, then you
#   must include the DNS name in the SAN too (otherwise, Chrome and others that
#   strictly follow the CA/Browser Baseline Requirements will fail).
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = test@example.com

# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier    = keyid,issuer

# You only need digitalSignature below. *If* you don't allow
#   RSA Key transport (i.e., you use ephemeral cipher suites), then
#   omit keyEncipherment because that's key transport.
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage    = serverAuth, clientAuth

# Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage    = serverAuth, clientAuth

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

您可能需要对 Chrome 执行以下操作。否则 Chrome may complain a Common Name is invalid (ERR_CERT_COMMON_NAME_INVALID)。在这种情况下,我不确定 SAN 中的 IP 地址和 CN 之间的关系是什么。

# IPv4 localhost
# IP.1       = 127.0.0.1

# IPv6 localhost
# IP.2     = ::1

关于在 X.509/PKIX 证书中处理 DNS 名称还有其他规则。有关规则,请参阅这些文档:

RFC 5280,互联网 X.509 公钥基础设施证书和证书撤销列表 (CRL) 配置文件

RFC 6125,在传输层安全 (TLS) 上下文中使用 X.509 (PKIX) 证书在互联网公钥基础设施中表示和验证基于域的应用程序服务身份

RFC 6797,附录 A,HTTP 严格传输安全 (HSTS)

RFC 7469,HTTP 的公钥固定扩展

CA/浏览器论坛基线要求

CA/浏览器论坛扩展验证指南

列出了 RFC 6797 和 RFC 7469,因为它们比其他 RFC 和 CA/B 文档更严格。 RFC 6797 和 7469 也不允许 IP 地址。


是否可以在 alternate_names 部分使用通配符?特别是子子域。我有一个问题在这里引用这个答案:serverfault.com/questions/711596/…
我刚刚回答了他的具体问题。当答案如此简单时,我认为添加这么长的安全描述是没有意义的
@diegows - 您的答案不完整或不正确。它不正确的原因在您不想阅读的长篇文章中进行了讨论:)
谢谢!我发现你的帖子很有帮助。仅供参考,我最近在玩 Vault,发现它坚持使用 IP.x 127.0.0.1 而不是 DNS.x 127 ......我没有检查这是否符合标准。
谢谢@jww。你说,“1.创建自己的权限(即成为CA)”,然后说,“5.在客户端安装CA证书”。如果根密钥被泄露,恶意人员可以使用该密钥为任何域签署证书,如果他们诱骗您访问他们的网站,他们现在可以进行中间人攻击。有没有办法创建根 CA,使其只能签署中间 CA 而不能签署证书?然后,您可以使用名称约束来保护您的中间 CA。
m
miken32

截至 2022 年,OpenSSL ≥ 1.1.1,以下命令可满足您的所有需求,包括 Subject Alternate Name (SAN)

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout example.key -out example.crt -subj "/CN=example.com" \
  -addext "subjectAltName=DNS:example.com,DNS:www.example.net,IP:10.0.0.1"

在 OpenSSL ≤ 1.1.0 的旧系统上,例如 Debian ≤ 9 或 CentOS ≤ 7,需要使用更长版本的此命令:

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout example.key -out example.crt -extensions san -config \
  <(echo "[req]"; 
    echo distinguished_name=req; 
    echo "[san]"; 
    echo subjectAltName=DNS:example.com,DNS:www.example.net,IP:10.0.0.1
    ) \
  -subj "/CN=example.com"

任一命令都会创建一个证书,该证书是

适用于(子)域 example.com 和 www.example.net (SAN),

也适用于 IP 地址 10.0.0.1 (SAN),

相对强劲(截至 2022 年)和

有效期为 3650 天(约 10 年)。

生成以下文件:

私钥:example.key

证书:example.crt

所有信息都在命令行中提供。没有让您烦恼的交互式输入。没有配置文件你必须弄乱。所有必要的步骤都由一个 OpenSSL 调用执行:从生成私钥到自签名证书。

备注 #1:加密参数

由于证书是自签名的,需要用户手动接受,所以使用短过期或弱密码是没有意义的。

将来,您可能希望为 RSA 密钥使用超过 4096 位和比 sha256 更强的哈希算法,但截至 2022 年,这些都是合理的值。它们足够强大,同时受到所有现代浏览器的支持。

备注#2:参数“-nodes”

从理论上讲,您可以省略 -nodes 参数(这意味着“没有 DES 加密”),在这种情况下 example.key 将使用密码进行加密。但是,这对于服务器安装几乎没有用处,因为您要么必须将密码也存储在服务器上,要么必须在每次重新启动时手动输入。

备注#3:另见

直接在命令行上将 subjectAltName 提供给 openssl

如何通过命令行将多个电子邮件地址添加到 SSL 证书?

有关 MSYS_NO_PATHCONV 的更多信息


我尝试在 mingw64 的 windows 上使用 oneliner #2(现代),但我遇到了 -subj 参数的错误。 ` $ openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout localhost.key -out localhost.crt -subj '/CN=localhost' -addext subjectAltName=DNS:localhost,IP:127.0.0.1 正在生成一个 RSA 私钥 [...] 将新私钥写入 'localhost.key' ----- 名称应采用 /type0=value0/type1=value1/type2=... 格式,其中字符可能是被\逃脱。此名称不是那种格式:'C:/Program Files/Git/CN=localhost' 提出证书请求的问题`
我无法弄清楚扩展为 C:/Program Files/Git/CN=localhost 的 arg /CN=localhost 到底应该归咎于什么,所以我只是在普通的 cmd.exe 中运行了整个命令,它工作得很好。以防万一有人为此苦苦挣扎。
@FranklinYu 你确定 rsa:2048 在 10 年后就足够了吗?因为那是有效期。如前所述,使用短期到期或弱加密是没有意义的。大多数 2048 位 RSA 密钥的有效期最长为 1-3 年。关于 OpenSSL 1.1.1,我仍然将 sha256 留在其中,因此如果您想要更强的哈希值,更改会更加明确和明显。
如果您在 Windows 上使用 git bash,例如 @YuriyPozniak,您将收到他列出的错误,其中 /CN=localhost 被扩展为 C:/Progra Files/Git/CN=localhost。如果添加额外的 /,则不会发生扩展。 //CN=localhost
1000 +1 用于创建使用新所需 SAN 的“单线”,而无需创建包含大量样板的冗长配置文件。做得好!
P
Peter Mortensen

以下是 @diegows's answer 中描述的选项,在 the documentation 中进行了更详细的描述:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX

req PKCS#10 证书请求和证书生成实用程序。 -x509 此选项输出自签名证书而不是证书请求。这通常用于生成测试证书或自签名根 CA。 -newkey arg 此选项创建一个新的证书请求和一个新的私钥。论证采用几种形式之一。 rsa:nbits,其中 nbits 是位数,生成大小为 nbits 的 RSA 密钥。 -keyout filename 这给出了将新创建的私钥写入的文件名。 -out filename 默认情况下指定要写入的输出文件名或标准输出。 -days n 当使用 -x509 选项时,它指定认证证书的天数。默认值为 30 天。 -nodes 如果指定了此选项,那么如果创建了私钥,它将不会被加密。

文档实际上比上面的更详细;我只是在这里总结了一下。


原始命令中的 XXX 应替换为“证明证书的天数”。默认值为 30 天。例如,如果您希望证书有效期为 365 天,则 -days XXX 变为 -days 365See the docs for more
感谢您添加文档。此 IBM 链接使用 command which seems identical to this answer 创建自签名证书
P
Peter Mortensen

我无法发表评论,因此我将其作为单独的答案。我发现接受的单行答案存在一些问题:

单行在密钥中包含密码短语。

单线使用 SHA-1,它在许多浏览器中会在控制台中引发警告。

这是一个简化版本,它删除了密码,提高了安全性以抑制警告,并在评论中包含一个建议以传递 -subj 以删除完整的问题列表:

openssl genrsa -out server.key 2048
openssl rsa -in server.key -out server.key
openssl req -sha256 -new -key server.key -out server.csr -subj '/CN=localhost'
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

将“localhost”替换为您需要的任何域。您需要一个一个地运行前两个命令,因为 OpenSSL 会提示输入密码。

要将两者组合成一个 .pem 文件:

cat server.crt server.key > cert.pem

我需要 github.com/molnarg/node-http2 的开发证书,这个答案是最好的。
将证书和密钥合并到一个文件中:cat server.crt server.key >foo-cert.pem。适用于 openssl-1.0.2d/demos/ssl/ 中的示例
我以这种方式生成的证书仍在使用 SHA1。
Tks,非常适合使用 TLSFreeBSD 10 OpenLDAP 2.4 上创建自签名证书
key.pem 文件呢?
v
vcsjones

如果现代浏览器缺少 SAN(主题备用名称),则现代浏览器现在会为其他格式良好的自签名证书引发安全错误。 OpenSSL 没有提供命令行方式来指定这一点,所以很多开发者的教程和书签突然就过时了。

再次运行的最快方法是一个简短的独立 conf 文件:

创建一个 OpenSSL 配置文件(例如:req.cnf) [req] distinct_name = req_distinguished_name x509_extensions = v3_req prompt = no [req_distinguished_name] C = US ST = VA L = SomeCity O = MyCompany OU = MyDivision CN = www.company.com [ v3_req] keyUsage = critical, digitalSignature, keyAgreement extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = www.company.com DNS.2 = company.com DNS.3 = company.net 创建引用此配置文件的证书 openssl req -x509 -nodes -days 730 -newkey rsa:2048 \ -keyout cert.key -out cert.pem -config req.cnf -sha256

来自 https://support.citrix.com/article/CTX135602 的示例配置


在删除导致错误的最后一个参数 -extensions 'v3_req' 后,它对我有用。在 Windows 上使用 OpenSSL。最后,我设法解决了这个问题!谢谢。
@Kyopaxa 你是对的 - 该参数与 cnf 文件的第 3 行是多余的;更新。
坚实的方式。谢谢。我建议添加 -sha256
您现在可以使用 -extension 'subjectAltName = DNS:dom.ain, DNS:oth.er' 在命令行上指定 SAN,请参阅 github.com/openssl/openssl/pull/4986
看起来此选项现在称为 -addext
P
Peter Mortensen

我建议添加 -sha256 参数以使用 SHA-2 哈希算法,因为主要浏览器正在考虑将“SHA-1 证书”显示为不安全。

来自已接受答案的相同命令行 - @diegows 添加了 -sha256

openssl req -x509 -sha256 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX

Google Security blog 中的更多信息。

2018 年 5 月更新。 正如许多人在评论中指出的那样,使用 SHA-2 不会为自签名证书增加任何安全性。但我仍然建议使用它作为不使用过时/不安全的加密哈希函数的好习惯。 Why is it fine for certificates above the end-entity certificate to be SHA-1 based? 中提供了完整的解释。


如果它是自签名密钥,无论如何它都会产生浏览器错误,所以这并不重要
@Mark,这很重要,因为 SHA-2 更安全
将 cert.pem 重命名为 cert.cer 后在 windows 中打开证书说指纹算法仍然是 Sha1,但签名哈希算法是 sha256。
“世界级加密 * 零认证 = 零安全”gerv.net/security/self-signed-certs
请注意,自签名证书上使用的签名算法与决定它是否可信无关。根 CA 证书是自签名的。截至 2018 年 5 月,仍有许多 SHA-1 签名的活动根 CA 证书。因为证书是否信任自己以及该证书如何验证该信任都无关紧要。您要么信任它所说的 的根/自签名证书,要么不信任。请参阅security.stackexchange.com/questions/91913/…
D
Doug

我无法发表评论,所以我添加了一个单独的答案。我尝试为 NGINX 创建一个自签名证书,这很容易,但是当我想将它添加到 Chrome 白名单时,我遇到了问题。我的解决方案是创建一个根证书并用它签署一个子证书。

所以一步一步来。创建文件 config_ssl_ca.cnf 注意,配置文件有一个选项 basicConstraints=CA:true 这意味着这个证书应该是根证书。

这是一个很好的做法,因为您创建一次就可以重复使用。

[ req ]
default_bits = 2048

prompt = no
distinguished_name=req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
countryName=UA
stateOrProvinceName=root region
localityName=root city
organizationName=Market(localhost)
organizationalUnitName=roote department
commonName=market.localhost
emailAddress=root_email@root.localhost

[ alternate_names ]
DNS.1        = market.localhost
DNS.2        = www.market.localhost
DNS.3        = mail.market.localhost
DNS.4        = ftp.market.localhost
DNS.5        = *.market.localhost

[ v3_req ]
keyUsage=digitalSignature
basicConstraints=CA:true
subjectKeyIdentifier = hash
subjectAltName = @alternate_names

您的子证书的下一个配置文件将调用 config_ssl.cnf。

[ req ]
default_bits = 2048

prompt = no
distinguished_name=req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
countryName=UA
stateOrProvinceName=Kyiv region
localityName=Kyiv
organizationName=market place
organizationalUnitName=market place department
commonName=market.localhost
emailAddress=email@market.localhost

[ alternate_names ]
DNS.1        = market.localhost
DNS.2        = www.market.localhost
DNS.3        = mail.market.localhost
DNS.4        = ftp.market.localhost
DNS.5        = *.market.localhost

[ v3_req ]
keyUsage=digitalSignature
basicConstraints=CA:false
subjectAltName = @alternate_names
subjectKeyIdentifier = hash

第一步——创建根密钥和证书

openssl genrsa -out ca.key 2048
openssl req -new -x509 -key ca.key -out ca.crt -days 365 -config config_ssl_ca.cnf

第二步创建子密钥和文件 CSR - 证书签名请求。因为想法是通过root签署子证书并获得正确的证书

openssl genrsa -out market.key 2048
openssl req -new -sha256 -key market.key -config config_ssl.cnf -out market.csr

打开 Linux 终端并执行此命令

echo 00 > ca.srl
touch index.txt

ca.srl 文本文件,包含下一个要使用的十六进制序列号。强制的。该文件必须存在并包含有效的序列号。

最后一步,再创建一个配置文件并将其命名为 config_ca.cnf

# we use 'ca' as the default section because we're usign the ca command
[ ca ]
default_ca = my_ca

[ my_ca ]
#  a text file containing the next serial number to use in hex. Mandatory.
#  This file must be present and contain a valid serial number.
serial = ./ca.srl

# the text database file to use. Mandatory. This file must be present though
# initially it will be empty.
database = ./index.txt

# specifies the directory where new certificates will be placed. Mandatory.
new_certs_dir = ./

# the file containing the CA certificate. Mandatory
certificate = ./ca.crt

# the file contaning the CA private key. Mandatory
private_key = ./ca.key

# the message digest algorithm. Remember to not use MD5
default_md = sha256

# for how many days will the signed certificate be valid
default_days = 365

# a section with a set of variables corresponding to DN fields
policy = my_policy

# MOST IMPORTANT PART OF THIS CONFIG
copy_extensions = copy

[ my_policy ]
# if the value is "match" then the field value must match the same field in the
# CA certificate. If the value is "supplied" then it must be present.
# Optional means it may be present. Any fields not mentioned are silently
# deleted.
countryName = match
stateOrProvinceName = supplied
organizationName = supplied
commonName = market.localhost
organizationalUnitName = optional
commonName = supplied

您可能会问,为什么这么难,为什么我们必须再创建一个配置来通过 root 签署子证书。答案很简单,因为子证书必须有一个 SAN 块 - 主题备用名称。如果我们通过“openssl x509”工具对子证书进行签名,根证书将删除子证书中的SAN字段。所以我们使用“openssl ca”而不是“openssl x509”来避免删除SAN字段。我们创建一个新的配置文件并告诉它复制所有扩展字段 copy_extensions = copy.

openssl ca -config config_ca.cnf -out market.crt -in market.csr

该程序会问您 2 个问题:

签署证书?说“Y” 1 个认证请求中的 1 个,提交?说“Y”

在终端中,您可以看到一个带有“数据库”一词的句子,它表示您通过“触摸”命令创建的文件 index.txt。它将包含您通过“openssl ca”实用程序创建的所有证书的所有信息。要检查证书有效使用:

openssl rsa -in market.key -check

如果您想查看 CRT 中的内容:

openssl x509 -in market.crt -text -noout

如果您想查看 CSR 的内容:

openssl req -in market.csr -noout -text 

虽然这个过程看起来很复杂,但这正是我们需要的 .dev 域,因为这个域不支持自签名证书,Chrome 和 Firefox 正在强制使用 HSTS。我所做的是遵循以下步骤,即创建 CA、创建证书并使用我的 CA 对其进行签名,最后在浏览器中信任我的 CA。谢谢。
你的通用名是错误的。不是名字/姓氏。它是您的域 cn 即 www.yoursite.com 。见ssl.com/faqs/common-name
没问题。有一些文件也写着名字(你的名字),这有点误导。但通用名称应该是实际的域。从这个意义上说,他们试图说的是(您的“域名”名称)。当通过创建证书的交互式方法运行时,它确实说 cn=domain 示例。所以 commonname 应该是 domain
P
Peter Mortensen

这是我在本地机器上使用的脚本,用于在自签名证书中设置 SAN(subjectAltName)。

此脚本采用域名 (example.com) 并在同一证书中为 *.example.com 和 example.com 生成 SAN。下面的部分进行了评论。为脚本命名(例如 generate-ssl.sh)并赋予它可执行权限。这些文件将被写入与脚本相同的目录。

Chrome 58 及更高版本要求在自签名证书中设置 SAN。

#!/usr/bin/env bash

# Set the TLD domain we want to use
BASE_DOMAIN="example.com"

# Days for the cert to live
DAYS=1095

# A blank passphrase
PASSPHRASE=""

# Generated configuration file
CONFIG_FILE="config.txt"

cat > $CONFIG_FILE <<-EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn

[dn]
C = CA
ST = BC
L = Vancouver
O = Example Corp
OU = Testing Domain
emailAddress = webmaster@$BASE_DOMAIN
CN = $BASE_DOMAIN

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.$BASE_DOMAIN
DNS.2 = $BASE_DOMAIN
EOF

# The file name can be anything
FILE_NAME="$BASE_DOMAIN"

# Remove previous keys
echo "Removing existing certs like $FILE_NAME.*"
chmod 770 $FILE_NAME.*
rm $FILE_NAME.*

echo "Generating certs for $BASE_DOMAIN"

# Generate our Private Key, CSR and Certificate
# Use SHA-2 as SHA-1 is unsupported from Jan 1, 2017

openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout "$FILE_NAME.key" -days $DAYS -out "$FILE_NAME.crt" -passin pass:$PASSPHRASE -config "$CONFIG_FILE"

# OPTIONAL - write an info to see the details of the generated crt
openssl x509 -noout -fingerprint -text < "$FILE_NAME.crt" > "$FILE_NAME.info"

# Protect the key
chmod 400 "$FILE_NAME.key"

此脚本还会写入信息文件,因此您可以检查新证书并验证 SAN 设置是否正确。

                ...
                28:dd:b8:1e:34:b5:b1:44:1a:60:6d:e3:3c:5a:c4:
                da:3d
            Exponent: 65537 (0x10001)
    X509v3 extensions:
        X509v3 Subject Alternative Name: 
            DNS:*.example.com, DNS:example.com
Signature Algorithm: sha256WithRSAEncryption
     3b:35:5a:d6:9e:92:4f:fc:f4:f4:87:78:cd:c7:8d:cd:8c:cc:
     ...

如果您使用的是 Apache,那么您可以在配置文件中引用上述证书,如下所示:

<VirtualHost _default_:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/htdocs

    SSLEngine on
    SSLCertificateFile path/to/your/example.com.crt
    SSLCertificateKeyFile path/to/your/example.com.key
</VirtualHost>

请记住重新启动您的 Apache(或 Nginx 或 IIS)服务器以使新证书生效。


适用于 macOS High Siera 和 Chrome 58
我仍然不确定 CN 如何影响整体设置?我正在尝试将它作为 localhost127.0.0.1:port# 运行,这样的东西对应的 CN 是什么。
@DJ2 我会设置 BASE_DOMAIN=“localhost”
P
Peter Mortensen

2017年单行:

openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout server.pem \
-new \
-out server.pem \
-subj /CN=localhost \
-reqexts SAN \
-extensions SAN \
-config <(cat /System/Library/OpenSSL/openssl.cnf \
    <(printf '[SAN]\nsubjectAltName=DNS:localhost')) \
-sha256 \
-days 3650

这也适用于 Chrome 57,因为它提供了 SAN,而无需其他配置文件。它取自答案 here

这将创建一个包含私钥和证书的单个 .pem 文件。如果需要,您可以将它们移动到单独的 .pem 文件中。


对于 Linux 用户,您需要更改配置的路径。例如在当前的 Ubuntu /etc/ssl/openssl.conf 上工作
对于不需要您指定 openssl.cnf 位置的单行代码,请参阅:stackoverflow.com/a/41366949/19163
C
Community

2017 年单线版本:

中央操作系统:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))

Ubuntu:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "/CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))

编辑:在 Ubuntu 的 'subj' 选项前添加了斜线。


P
Peter Mortensen

一个班轮 FTW。我喜欢保持简单。为什么不使用一个包含所有所需参数的命令呢?这就是我喜欢的方式——这会创建一个 x509 证书及其 PEM 密钥:

openssl req -x509 \
 -nodes -days 365 -newkey rsa:4096 \
 -keyout self.key.pem \
 -out self-x509.crt \
 -subj "/C=US/ST=WA/L=Seattle/CN=example.com/emailAddress=someEmail@gmail.com"

该单个命令包含您通常会为证书详细信息提供的所有答案。通过这种方式,您可以设置参数并运行命令,获取输出 - 然后去喝咖啡。

>> More here <<


除了 SAN 之外的所有论点……@vog 的回答也涵盖了这一点(并且早于这个)(尽管填写了更完整的“主题”字段……)(也不是一年到期的忠实粉丝)
vog's answer。链接,因为用户名既不是唯一的也不是不可变的。 “vog”可以随时更改为“scoogie”。
g
gavenkoa

openssl 允许通过单个命令生成自签名证书(-newkey 指示生成私钥,-x509 指示颁发自签名证书而不是签名请求)::

openssl req -x509 -newkey rsa:4096 \
-keyout my.key -passout pass:123456 -out my.crt \
-days 365 \
-subj /CN=localhost/O=home/C=US/emailAddress=me@mail.internal \
-addext "subjectAltName = DNS:localhost,DNS:web.internal,email:me@mail.internal" \
-addext keyUsage=digitalSignature -addext extendedKeyUsage=serverAuth

您可以在不同的步骤中生成私钥并构建自签名证书:

openssl genrsa -out my.key -passout pass:123456 2048

openssl req -x509 \
-key my.key -passin pass:123456 -out my.csr \
-days 3650 \
-subj /CN=localhost/O=home/C=US/emailAddress=me@mail.internal \
-addext "subjectAltName = DNS:localhost,DNS:web.internal,email:me@mail.internal" \
-addext keyUsage=digitalSignature -addext extendedKeyUsage=serverAuth

查看生成的证书::

openssl x509 -text -noout -in my.crt

Java keytool 创建 PKCS#12 存储::

keytool -genkeypair -keystore my.p12 -alias master \
-storetype pkcs12 -keyalg RSA -keysize 2048 -validity 3650 \
-storepass 123456 \
-dname "CN=localhost,O=home,C=US" \
-ext 'san=dns:localhost,dns:web.internal,email:me@mail.internal'

导出自签名证书:

keytool -exportcert -keystore my.p12 -file my.crt \
-alias master -rfc -storepass 123456

查看生成的证书::

keytool -printcert -file my.crt

GnuTLS 中的 certtool 不允许从 CLI 传递不同的属性。我不喜欢弄乱配置文件((


我不能强调这一点!!!!!!! extendedKeyUsage = serverAuth, clientAuth 是什么让我获得了“Proceed to localhost (unsafe)”按钮
P
Peter Mortensen

你有正确的一般程序。该命令的语法如下。

openssl req -new -key {private key file} -out {output file}

但是,会显示警告,因为浏览器无法通过使用已知的证书颁发机构 (CA) 验证证书来验证身份。

由于这是一个自签名证书,因此没有 CA,您可以放心地忽略警告并继续。如果您想获得公共 Internet 上任何人都可以识别的真实证书,那么过程如下。

生成私钥 使用该私钥创建 CSR 文件 将 CSR 提交给 CA(Verisign 或其他等) 在 Web 服务器上安装从 CA 收到的证书 根据证书类型将其他证书添加到身份验证链

我在 Securing the Connection: Creating a Security Certificate with OpenSSL 的帖子中有更多详细信息


3
3 revs, 3 users 80%

生成密钥我使用 /etc/mysql 进行证书存储,因为 /etc/apparmor.d/usr.sbin.mysqld 包含 /etc/mysql/*.pem r。 sudo su - cd /etc/mysql openssl genrsa -out ca-key.pem 2048; openssl req -new -x509 -nodes -days 1000 -key ca-key.pem -out ca-cert.pem; openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem -out server-req.pem; openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem; openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem -out client-req.pem; openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem;添加配置/etc/mysql/my.cnf [client] ssl-ca=/etc/mysql/ca-cert.pem ssl-cert=/etc/mysql/client-cert.pem ssl-key=/etc/mysql/ client-key.pem [mysqld] ssl-ca=/etc/mysql/ca-cert.pem ssl-cert=/etc/mysql/server-cert.pem ssl-key=/etc/mysql/server-key.pem

在我的设置中,Ubuntu 服务器登录到:/var/log/mysql/error.log

后续注意事项:

SSL 错误:如果您的证书文件不在 apparmors 配置中,则无法从“...”获取证书 MySQL 可能会被拒绝读取访问权限。正如前面步骤中提到的^,将我们所有的证书保存为 .pem 文件在 apparmor 默认批准的 /etc/mysql/ 目录中(或修改 apparmor/SELinux 以允许访问您存储它们的任何位置。)

SSL 错误:无法获取私钥您的 MySQL 服务器版本可能不支持默认的 rsa:2048 格式将生成的 rsa:2048 转换为普通 rsa:openssl rsa -in server-key.pem -out server-key.pem openssl rsa -在 client-key.pem -out client-key.pem

检查本地服务器是否支持 SSL: mysql -u root -p mysql> show variables like "%ssl%"; +---------------+----------------+ |变量名 |价值 | +---------------+----------------+ |有_openssl |是 | |有_ssl |是 | | ssl_ca | /etc/mysql/ca-cert.pem | | ssl_capath | | | ssl_cert | /etc/mysql/server-cert.pem | | ssl_cipher | | | ssl_key | /etc/mysql/server-key.pem | +---------------+----------------+

验证与数据库的连接是 SSL 加密的: 验证连接 当登录到 MySQL 实例时,您可以发出查询: show status like 'Ssl_cipher';如果您的连接未加密,则结果将为空白:mysql> show status like 'Ssl_cipher'; +---------------+--------+ |变量名 |价值 | +---------------+--------+ | ssl_cipher | | +---------------+-------+ 1 row in set (0.00 sec) 否则,它将显示正在使用的密码的非零长度字符串: mysql> 显示类似“Ssl_cipher”的状态; +---------------+--------+ |变量名 |价值 | +---------------+--------+ | ssl_cipher | DHE-RSA-AES256-SHA | +---------------+--------+ 1 行在集合中(0.00 秒)

特定用户的连接需要 ssl('require ssl'):SSL 告诉服务器只允许该帐户的 SSL 加密连接。在测试中授予所有特权。* TO 'root'@'localhost' REQUIRE SSL;要连接,客户端必须指定 --ssl-ca 选项来验证服务器证书,并且可以另外指定 --ssl-key 和 --ssl-cert 选项。如果既没有指定 --ssl-ca 选项也没有指定 --ssl-capath 选项,客户端不会验证服务器证书。

SSL

备用链接:Secure PHP Connections to MySQL with SSL 中的冗长教程。


-1;这在很大程度上与所提出的问题相切,并且在明确其引用的来源方面也做得不好。
这显示了配置 CA、由 CA 签名的服务器/客户端证书,将它们配置为由具有 apparmor 的主机上的 mysqld 读取。它举例说明了在同一台机器上托管 ca、服务器和客户端并将该 ca 的权限危险地暴露给 mysqld 进程的相当无用的情况。除了在测试环境中测试 ssl 配置之外,此设置实际上没有任何意义。对于操作内部 CA,我建议使用 gnuttls 工具链而不是 openssl help.ubuntu.com/community/GnuTLS 并在解决 mysqld+apparmor 案例之前对 tls 有很好的了解
P
Peter Jirak Eldritch

正如已经详细讨论过的,self-signed certificates are not trusted for the Internet。您可以add your self-signed certificate to many but not all browsers。或者,您可以become your own certificate authority

不想从证书颁发机构获得签名证书的主要原因是成本 -- Symantec charges between $995 - $1,999 per year for certificates -- just for a certificate intended for internal network, Symantec charges $399 per year。如果您正在处理信用卡付款或为高利润公司的利润中心工作,那么这笔费用很容易证明是合理的。对于一个在互联网上创建的个人项目,或者对于一个以最低预算运行的非营利组织,或者如果一个人在组织的成本中心工作——成本中心总是试图做更多的事情,这超出了许多人所能承受的范围。少。

另一种方法是使用 certbot(请参阅 about certbot)。 Certbot 是一个易于使用的自动客户端,可为您的 Web 服务器获取和部署 SSL/TLS 证书。

如果您设置 certbot,您可以启用它来为您创建和维护由 Let’s Encrypt 证书颁发机构颁发的证书。

我在周末为我的组织做了这个。我在我的服务器(Ubuntu 16.04)上安装了 certbot 所需的软件包,然后运行了设置和启用 certbot 所需的命令。 certbot 可能需要一个 DNS plugin - 我们目前正在使用 DigitalOcean,但可能很快会迁移到另一项服务。

请注意,有些说明并不完全正确,需要花一点时间在 Google 上摸索才能弄清楚。第一次这花了我相当多的时间,但现在我想我可以在几分钟内完成。

对于 DigitalOcean,我遇到的一个问题是当我被提示输入 DigitalOcean 凭据 INI 文件的路径时。脚本所指的是 Applications & API 页面和该页面上的 Tokens/Key 选项卡。您需要为 DigitalOcean 的 API 拥有或生成个人访问令牌(读取和写入)——这是一个 65 个字符的十六进制字符串。然后需要将此字符串放入运行 certbot 的网络服务器上的文件中。该文件的第一行可以有注释(注释以# 开头)。第二行是:

dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff

一旦我弄清楚如何为 DigitalOcean 的 API 设置读写令牌,使用 certbot 设置 wildcard certificate 就非常容易了。请注意,不必设置通配符证书,而是可以指定希望证书应用到的每个域和子域。通配符证书需要包含来自 DigitalOcean 的个人访问令牌的凭据 INI 文件。

请注意,公钥证书(也称为身份证书或 SSL 证书)过期并需要续订。因此,您需要定期(重复)更新您的证书。 certbot 文档涵盖 renewing certificates

我的计划是编写一个脚本来使用 openssl 命令获取我的证书的到期日期,并在到期前 30 天或更短时间触发续订。然后我会将此脚本添加到 cron 并每天运行一次。

这是读取证书到期日期的命令:

root@prod-host:~# /usr/bin/openssl x509 -enddate -noout -in path-to-certificate-pem-file
notAfter=May 25 19:24:12 2019 GMT

L
Leonardo Pineda

这对我有用

openssl req -x509 -nodes -subj '/CN=localhost'  -newkey rsa:4096 -keyout ./sslcert/key.pem -out ./sslcert/cert.pem -days 365

服务器.js

var fs = require('fs');
var path = require('path');
var http = require('http');
var https = require('https');
var compression = require('compression');
var express = require('express');
var app = express();

app.use(compression());
app.use(express.static(__dirname + '/www'));    

app.get('/*', function(req,res) {
  res.sendFile(path.join(__dirname+'/www/index.html'));
});

// your express configuration here

var httpServer = http.createServer(app);
var credentials = {
    key: fs.readFileSync('./sslcert/key.pem', 'utf8'),
    cert: fs.readFileSync('./sslcert/cert.pem', 'utf8')
};
var httpsServer = https.createServer(credentials, app);

httpServer.listen(8080);
httpsServer.listen(8443);

console.log(`RUNNING ON  http://127.0.0.1:8080`);
console.log(`RUNNING ON  http://127.0.0.1:8443`);

J
JohnnyJS

经过大量的尝试,尝试了各种解决方案,我仍然面临为本地主机颁发自签名证书的问题,给了我错误

ERR_CERT_INVALID

在展开细节时,chrome 表示:

您现在无法访问 localhost,因为该网站发送了加密凭据...

唯一难看的方法是输入(直接在这个屏幕上,看不到任何文本光标):

(输入键盘)thisisunsafe

这让我继续。

直到我找到extendedKeyUsage = serverAuth, clientAuth

TL;博士

openssl genrsa -out localhost.key 2048 openssl req -key localhost.key -new -out localhost.csr(在所有内容上单击输入,只需使用 localhost 或您的其他 FQDN 填写公用名(CN)。将以下内容放入文件中命名为 v3.ext (编辑您需要的任何内容):

subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints       = CA:TRUE
keyUsage               = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign
extendedKeyUsage       = serverAuth, clientAuth
subjectAltName         = DNS:localhost, DNS:localhost.localdomain
issuerAltName          = issuer:copy

openssl x509 -req -in localhost.csr -signkey localhost.key -out localhost.pem -days 3650 -sha256 -extfile v3.ext

瞧!您可以访问该网站,展开“高级”并单击“继续访问本地主机(不安全)”。


也许一些聪明的家伙能够把这一切变成一个很好的单线……
您最后一个命令中的 v3.ext 文件是什么?
编辑了答案。看第4点。
M
Maoz Zadok

生成10年无密码无证书的密钥,捷径:

openssl req  -x509 -nodes -new  -keyout server.key -out server.crt -days 3650 -subj "/C=/ST=/L=/O=/OU=web/CN=www.server.com"

对于标志 -subj | -subject 允许空值 -subj "/C=/ST=/L=/O=/OU=web/CN=www.server.com",但您可以根据需要设置更多详细信息:

C - 国家名称(2 个字母代码)

ST - 状态

- 地区名称(例如,城市)

O - 组织名称

OU - 组织单位名称

CN - 通用名称 - 必填!


A
Anonymous

这个非常简单的 Python 应用程序可以创建自签名证书。代码:

from OpenSSL import crypto, SSL
from secrets import randbelow
print("Please know, if you make a mistake, you must restart the program.")
def cert_gen(
    emailAddress=input("Enter Email Address: "),
    commonName=input("Enter Common Name: "),
    countryName=input("Enter Country Name (2 characters): "),
    localityName=input("Enter Locality Name: "),
    stateOrProvinceName=input("Enter State of Province Name: "),
    organizationName=input("Enter Organization Name: "),
    organizationUnitName=input("Enter Organization Unit Name: "),
    serialNumber=randbelow(1000000),
    validityStartInSeconds=0,
    validityEndInSeconds=10*365*24*60*60,
    KEY_FILE = "private.key",
    CERT_FILE="selfsigned.crt"):
    #can look at generated file using openssl:
    #openssl x509 -inform pem -in selfsigned.crt -noout -text
    # create a key pair
    k = crypto.PKey()
    k.generate_key(crypto.TYPE_RSA, 4096)
    # create a self-signed cert
    cert = crypto.X509()
    cert.get_subject().C = countryName
    cert.get_subject().ST = stateOrProvinceName
    cert.get_subject().L = localityName
    cert.get_subject().O = organizationName
    cert.get_subject().OU = organizationUnitName
    cert.get_subject().CN = commonName
    cert.get_subject().emailAddress = emailAddress
    cert.set_serial_number(serialNumber)
    cert.gmtime_adj_notBefore(0)
    cert.gmtime_adj_notAfter(validityEndInSeconds)
    cert.set_issuer(cert.get_subject())
    cert.set_pubkey(k)
    cert.sign(k, 'sha512')
    with open(CERT_FILE, "wt") as f:
        f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8"))
    with open(KEY_FILE, "wt") as f:
        f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8"))
    print("GENERATED")
    input("Press enter to close program.")
cert_gen()

但是,您仍然会收到“证书不受信任”错误。这是因为几个原因:

它是自签名/未验证的(经过验证的证书需要 CA(证书颁发机构),例如 Let's Encrypt 才能在所有设备上受信任)。它在您的机器上不受信任。 (此答案显示了如何使 Windows 信任您的证书)。