我正在向嵌入式 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
这可行,但我遇到了一些错误,例如,谷歌浏览器:
这可能不是您要找的网站!该站点的安全证书不受信任!
我错过了什么吗?这是构建自签名证书的正确方法吗?
alternate_names
部分的配置文件并使用 -config
选项传递它。此外,IETF 和 CA/浏览器论坛均不赞成(但不禁止)将 DNS 名称放在通用名称 (CN) 中。 CN 中的任何 DNS 名称也必须存在于 SAN 中。没有办法避免使用 SAN。请参阅下面的答案。
您可以在一个命令中执行此操作:
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) 签名的证书。
我错过了什么吗?这是构建自签名证书的正确方法吗?
创建自签名证书很容易。您只需使用 openssl req
命令。创建一个可供最多选择的客户端使用的客户端可能会很棘手,例如浏览器和命令行工具。
这很困难,因为浏览器有自己的一组要求,而且它们比 IETF 更严格。浏览器使用的要求记录在 CA/Browser Forums 中(请参阅下面的参考资料)。限制出现在两个关键领域:(1) 信任锚,和 (2) DNS 名称。
现代浏览器(如我们在 2014/2015 年使用的warez)需要一个链接回信任锚的证书,并且他们希望在证书中以特定方式显示 DNS 名称。浏览器正在积极反对自签名服务器证书。
某些浏览器并不完全可以轻松导入自签名服务器证书。事实上,你不能用一些浏览器,比如Android的浏览器。所以完整的解决方案是成为你自己的权威。
在没有成为您自己的权威的情况下,您必须获得正确的 DNS 名称才能使证书获得最大的成功机会。但我会鼓励你成为自己的权威。成为自己的权威很容易,它会回避所有信任问题(谁比自己更值得信任?)。
这可能不是您要找的网站!该站点的安全证书不受信任!
这是因为浏览器使用预定义的信任锚列表来验证服务器证书。自签名证书不会链接回受信任的锚点。
避免这种情况的最佳方法是:
创建您自己的授权(即成为 CA) 为服务器创建证书签名请求 (CSR) 使用您的 CA 密钥签署服务器的 CSR 在服务器上安装服务器证书 在客户端上安装 CA 证书
第 1 步 - 创建您自己的权限 只是意味着使用 CA: true
和正确的密钥用法创建一个自签名证书。这意味着 Subject 和 Issuer 是同一个实体,CA 在 Basic Constraints 中设置为 true(也应标记为关键),密钥用法是 keyCertSign
和 crlSign
(如果您使用 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 大致是您现在为面向公众的服务器所做的,当您征用像 Startcom 或 CAcert 这样的 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/…
截至 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 的更多信息
/CN=localhost
被扩展为 C:/Progra Files/Git/CN=localhost
。如果添加额外的 /,则不会发生扩展。 //CN=localhost
以下是 @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 365
。 See the docs for more。
我无法发表评论,因此我将其作为单独的答案。我发现接受的单行答案存在一些问题:
单行在密钥中包含密码短语。
单线使用 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
cat server.crt server.key >foo-cert.pem
。适用于 openssl-1.0.2d/demos/ssl/
中的示例
TLS
在 FreeBSD 10
OpenLDAP 2.4
上创建自签名证书
如果现代浏览器缺少 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 的示例配置
-sha256
。
-extension 'subjectAltName = DNS:dom.ain, DNS:oth.er'
在命令行上指定 SAN,请参阅 github.com/openssl/openssl/pull/4986
-addext
。
我建议添加 -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? 中提供了完整的解释。
我无法发表评论,所以我添加了一个单独的答案。我尝试为 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
这是我在本地机器上使用的脚本,用于在自签名证书中设置 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)服务器以使新证书生效。
localhost
或 127.0.0.1:port#
运行,这样的东西对应的 CN
是什么。
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 文件中。
/etc/ssl/openssl.conf
上工作
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' 选项前添加了斜线。
一个班轮 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"
该单个命令包含您通常会为证书详细信息提供的所有答案。通过这种方式,您可以设置参数并运行命令,获取输出 - 然后去喝咖啡。
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 传递不同的属性。我不喜欢弄乱配置文件((
你有正确的一般程序。该命令的语法如下。
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 的帖子中有更多详细信息
生成密钥我使用 /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 中的冗长教程。
正如已经详细讨论过的,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
这对我有用
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`);
经过大量的尝试,尝试了各种解决方案,我仍然面临为本地主机颁发自签名证书的问题,给了我错误
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
文件是什么?
生成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 - 通用名称 - 必填!
这个非常简单的 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 信任您的证书)。
不定期副业成功案例分享
-subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=www.example.com"
-sha256
生成基于 SHA-256 的证书。