我想念什么吗?这是构建自签名证书的正确方法吗?
创建自签名证书很容易。您只需要使用openssl req
命令。创建一个可供最多客户端选择(例如浏览器和命令行工具)使用的客户端可能很棘手。
这很困难,因为浏览器有自己的一套要求,并且比IETF更具限制性。浏览器使用的要求记录在CA /浏览器论坛中(请参阅下面的参考资料)。限制出现在两个关键领域:(1)信任锚,和(2)DNS名称。
现代浏览器(例如我们在2014/2015年使用的warez)需要一个链接回信任锚的证书,并且他们希望DNS名称以特定方式在证书中显示。浏览器正在积极反对自签名服务器证书。
某些浏览器不能完全轻松地导入自签名服务器证书。实际上,您无法使用某些浏览器,例如Android的浏览器。因此,完整的解决方案是成为您自己的权威。
如果没有自己的权限,则必须正确设置DNS名称,以使证书获得最大的成功机会。但是我鼓励你成为自己的权威。成为您自己的权威很容易,它将回避所有信任问题(谁比自己更信任?)。
这可能不是您要查找的网站!
该站点的安全证书不受信任!
这是因为浏览器使用预定义的信任锚列表来验证服务器证书。自签名证书不会链接回受信任的锚。
避免这种情况的最佳方法是:
- 创建您自己的权限(即成为CA)
- 为服务器创建证书签名请求(CSR)
- 使用您的CA密钥签署服务器的CSR
- 在服务器上安装服务器证书
- 在客户端上安装CA证书
第1步- 创建您自己的权限仅意味着创建具有CA: true
适当密钥用法的自签名证书。这意味着主题和颁发者是同一实体,在基本约束中将CA设置为true (也应将其标记为关键),密钥用法为keyCertSign
和crlSign
(如果使用的是CRL),主题密钥标识符(SKI)为与授权机构密钥标识符(AKI)相同。
要成为自己的证书颁发机构,请参阅* 如何与证书颁发机构签署证书签名请求?在堆栈溢出。然后,将您的CA导入浏览器使用的信任库中。
当您征求诸如Startcom或CAcert之类的CA服务时,步骤2-4大致就是您现在要对面向公众的服务器执行的操作。步骤1和5使您可以避开第三方权限,而充当自己的权限(谁比自己更信任?)。
避免浏览器警告的下一个最佳方法是信任服务器的证书。但是某些浏览器(例如Android的默认浏览器)不允许您这样做。因此它将永远无法在平台上运行。
浏览器(和其他类似的用户代理)不信任自签名证书的问题将成为物联网(IoT)中的一个大问题。例如,当您连接恒温器或冰箱进行编程时会发生什么?答案是,就用户体验而言,这没有什么好处。
W3C的WebAppSec工作组开始研究此问题。例如,参见提案:将HTTP标记为不安全。
如何使用OpenSSL创建自签名证书
下面的命令和配置文件将创建一个自签名证书(还显示了如何创建签名请求)。它们在一个方面与其他答案有所不同:用于自签名证书的DNS名称在主题备用名称(SAN)中,而不是公用名(CN)中。
DNS名称通过带有行的配置文件放置在SAN中subjectAltName = @alternate_names
(无法通过命令行来完成)。然后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 / Browser Forum指南的浏览器和其他用户代理下进行验证。
相关:浏览器遵循CA / Browser论坛策略;而不是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可能会抱怨“ 通用名称”无效(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 6797和RFC 7469,因为它们比其他RFC和CA / B文档更具限制性。RFC 6797和7469 也不允许IP地址。