使用可在Chrome 58中运行的openssl生成自签名证书


52

从Chrome 58开始,它不再接受依赖于Common Name以下各项的自签名证书:https : //productforums.google.com/forum/#! topic/chrome/zVo3M8CgKzQ;context-place = topicsearchin/chrome/category $ 3ACanary%7Csort:相关性%7Cspell:假

相反,它需要使用Subject Alt Name。之前,我一直在遵循有关如何生成自签名证书的指南:https : //devcenter.heroku.com/articles/ssl-certificate-self,该方法非常有效,因为我需要在执行操作时使用server.crtserver.key文件。现在,我需要生成新的证书,其中包括SAN我所做的所有尝试都不适用于Chrome 58。

这是我所做的:

我按照上述Heroku文章中的步骤生成了密钥。然后,我编写了一个新的OpenSSL配置文件:

[ req ]
default_bits        = 2048
distinguished_name  = req_distinguished_name
req_extensions      = san
extensions          = san
[ req_distinguished_name ]
countryName         = US
stateOrProvinceName = Massachusetts
localityName        = Boston
organizationName    = MyCompany
[ san ]
subjectAltName      = DNS:dev.mycompany.com

然后server.crt使用以下命令生成:

openssl req \
-new \
-key server.key \
-out server.csr \
-config config.cnf \
-sha256 \
-days 3650

我在Mac上,因此我server.crt使用钥匙串打开了文件,并将其添加到了系统证书中。然后将其设置为Always Trust

除了用于设置SAN值的配置文件外,这些与我在早期版本的Chrome中用于生成并信任自签名证书的步骤相似。

但是,在此之后,我仍然可以使用ERR_CERT_COMMON_NAME_INVALIDChrome 58。

Answers:


61

我的解决方案:

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

状态:对我有用


2
大量使用subshel​​l。我认为您可以简化一下:-config <(cat /System/Library/OpenSSL/openssl.cnf ; printf '[SAN]\nsubjectAltName=DNS:dev.mycompany.com')
jrwren

1
我不再收到“主题替代名称”错误,但是现在我收到有关通用名称的错误,并且将下载的证书设置为“始终信任”不起作用。有什么想法吗?@bcardarella
橄榄球,

2
随着Chrome 59的更新,证书显示如下错误:网站的证书链(net :: ERR_CERT_COMMON_NAME_INVALID)出现问题。
theHarsh

1
我更改dev.company.namelocalhost,这适用于从本地主机服务本地开发站点。在macOS上,我还必须将证书添加到“钥匙串”并将SSL设置为“始终信任”。
Daniel M.

1
到目前为止,这是最简单的解决方案,不需要拧紧sslconf或安装CA。
bp。

16

在Windows中,将此脚本保存为SSL文件夹中的makeCERT.bat。它将创建以下文件:example.cnf,example.crt,example.key

@echo off

REM IN YOUR SSL FOLDER, SAVE THIS FILE AS: makeCERT.bat
REM AT COMMAND LINE IN YOUR SSL FOLDER, RUN: makecert
REM IT WILL CREATE THESE FILES: example.cnf, example.crt, example.key
REM IMPORT THE .crt FILE INTO CHROME Trusted Root Certification Authorities
REM REMEMBER TO RESTART APACHE OR NGINX AFTER YOU CONFIGURE FOR THESE FILES

REM PLEASE UPDATE THE FOLLOWING VARIABLES FOR YOUR NEEDS.
SET HOSTNAME=example
SET DOT=com
SET COUNTRY=US
SET STATE=KS
SET CITY=Olathe
SET ORGANIZATION=IT
SET ORGANIZATION_UNIT=IT Department
SET EMAIL=webmaster@%HOSTNAME%.%DOT%

(
echo [req]
echo default_bits = 2048
echo prompt = no
echo default_md = sha256
echo x509_extensions = v3_req
echo distinguished_name = dn
echo:
echo [dn]
echo C = %COUNTRY%
echo ST = %STATE%
echo L = %CITY%
echo O = %ORGANIZATION%
echo OU = %ORGANIZATION_UNIT%
echo emailAddress = %EMAIL%
echo CN = %HOSTNAME%.%DOT%
echo:
echo [v3_req]
echo subjectAltName = @alt_names
echo:
echo [alt_names]
echo DNS.1 = *.%HOSTNAME%.%DOT%
echo DNS.2 = %HOSTNAME%.%DOT%
)>%HOSTNAME%.cnf

openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout %HOSTNAME%.key -days 3560 -out %HOSTNAME%.crt -config %HOSTNAME%.cnf

13

这是一个对我有用的解决方案:

创建CA密钥和证书

# openssl genrsa -out server_rootCA.key 2048
# openssl req -x509 -new -nodes -key server_rootCA.key -sha256 -days 3650 -out server_rootCA.pem

创建server_rootCA.csr.cnf

# server_rootCA.csr.cnf
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C=DE
ST=Berlin
L=NeuKoelln
O=Weisestrasse
OU=local_RootCA
emailAddress=ikke@server.berlin
CN = server.berlin

创建v3.ext配置文件

# v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = server.berlin

创建服务器密钥

# openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key -config <( cat server_rootCA.csr.cnf )

创建服务器证书

# openssl x509 -req -in server.csr -CA server_rootCA.pem -CAkey server_rootCA.key -CAcreateserial -out server.crt -days 3650 -sha256 -extfile v3.ext

将证书和密钥添加到Apache2站点文件的HTTPS(端口443)部分

SSLCertificateFile    /etc/apache2/ssl/server.crt
SSLCertificateKeyFile    /etc/apache2/ssl/server.key

将server_rootCA.pem从服务器复制到您的计算机。

# scp you@server.berlin:~/server_rootCA.pem .

..并将其添加到Chromium浏览器

Chromium -> Setting -> (Advanced) Manage Certificates -> Import -> 'server_rootCA.pem'

你都做完了!

PS无需创建功能性的CA和服务器证书对(按照上述说明),您只需在HTTP服务器配置中禁用HSTS标头即可。这将阻止Chromium强制执行HTTPS,并允许用户单击“高级→继续执行your.url(不安全)”,而无需获取并安装自定义CA(server_rootCA.pem)证书。换句话说,必须禁用HSTS,才能通过HTTP和/或不安全的HTTPS连接公开查看您的网站(请注意!)。

对于Apache2,将以下内容添加到站点文件的HTTP(端口80)部分

Header unset Strict-Transport-Security
Header always set Strict-Transport-Security "max-age=0;includeSubDomains"

在Debian / Apache2.4 + Debian / Chromium 59上测试

https://ram.k0a1a.net/self-signed_https_cert_after_chrome_58


遵循根CA权威机构的路径,该机构随后会对各个证书进行签名,这是我可以对chrome进行完全身份验证的唯一方法。还有一个优点是,我只需要让人们安装一个证书即可。谢谢
geoff

4
有人可以向我解释为什么这个领域的每个人似乎都在使用bashisms -config <( cat server_rootCA.csr.cnf )而不是just -config server_rootCA.csr.cnf吗?
凯撒

您能否更新与可以绕过此问题的apache标头有关的答案(我不介意这仅适用于本地站点开发,我喜欢通用解决方案,而不必每次都生成新证书)。您能指出这些应该在虚拟主机定义中的哪个位置。我尝试了几种替代方法,但仍然无法通过https访问网站。谢谢
Nikos M.

12

有几个很棒的答案给出了如何使它工作的示例,但没有一个可以解释您尝试中哪里出了问题。OpenSSL在某些时候可能非常不直观,因此值得一遍。

首先,顺便说一句,OpenSSL默认会忽略您在配置中提供的任何可分辨的名称值。如果要使用它们,则必须将其添加prompt = no 到配置中。另外,编写的命令仅生成证书 请求,而不生成证书本身,因此该-days命令不执行任何操作。

如果使用给出的此命令生成证书请求并检查结果,则将显示“主题替代名称”:

$ openssl req -new -key server.key -out server.csr -config config.cnf -sha256
$ openssl req -text -noout -in server.csr
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = US, ST = Massachusetts, L = Boston, O = MyCompany
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
        Attributes:
        Requested Extensions:
            X509v3 Subject Alternative Name:
                DNS:dev.mycompany.com
    Signature Algorithm: sha256WithRSAEncryption
         ...

但是,如果您使用heroku链接中的命令生成证书并检查结果,则缺少主题替代名称:

$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
$ openssl x509 -text -noout -in server.crt
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            89:fd:75:26:43:08:04:61
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = Massachusetts, L = Boston, O = MyCompany
        Validity
            Not Before: Jan 21 04:27:21 2018 GMT
            Not After : Jan 21 04:27:21 2019 GMT
        Subject: C = US, ST = Massachusetts, L = Boston, O = MyCompany
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         ...

原因是默认情况下,OpenSSL不会将扩展名从请求复制到证书。通常,证书将由CA根据客户的请求来创建/签名,如果某些扩展盲目地信任请求中定义的扩展,则某些扩展可以为证书授予比CA更大的权限。

有多种方法可以告诉OpenSSL复制扩展,但是恕我直言,这比在生成证书时仅在配置文件中提供扩展要复杂得多。

如果要尝试使用现有的配置文件,则该文件将不起作用,因为已标记了顶层部分,[req]因此这些设置仅适用于req命令而不适用于x509命令。不需要顶级标记,因此您只需删除第一行,然后对于生成请求或证书就可以正常工作。

$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt -extfile config.cnf

或者,您可以使用命令的-x509参数req在单个命令中生成自签名证书,而不是先创建请求然后创建证书。在这种情况下,不必删除 [req]节线,因为req命令可以读取和使用该节。

$ openssl req -x509 -sha256 -days 365 -key server.key -out server.crt -config config.cnf

回顾一下,这是上述命令中使用的修改后的配置文件:

default_bits        = 2048
distinguished_name  = dn
x509_extensions     = san
req_extensions      = san
extensions          = san
prompt              = no
[ dn ]
countryName         = US
stateOrProvinceName = Massachusetts
localityName        = Boston
organizationName    = MyCompany
[ san ]
subjectAltName      = DNS:dev.mycompany.com

2
这是唯一可以帮助我理解为什么证书不带SAN的原因的解释(对于我而言,我需要在配置文件中包含x509_extensions)
Daniel Beardsmore

2

我的解决方案是使主体保持不变,openssl.cnf并在最后添加一个新部分,例如[ cert_www.example.com ]www.example.com是我要为其创建证书的网站,并在其中放入subjectAltName我需要的(和还要别的吗)。当然,您可以根据需要命名该部分。

之后,我可以openssl req像以前一样运行该命令,只需添加-extensions cert_www.example.com其内容即可,然后-subj直接添加所有DN信息。

创建证书之后和使用之前,请不要忘记使用以下方法来验证证书内容: openssl x509 -text


1

带有配置的Bash脚本

作为一个shell脚本,应该可以在所有使用bash的平台上工作。假定HOSTNAME为外壳设置了env或提供了您选择的主机名,例如self_signed_cert.sh test

set -e

if [ -z "$1" ]; then
  hostname="$HOSTNAME"
else
  hostname="$1"
fi

local_openssl_config="
[ req ]
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = san_self_signed
[ req_distinguished_name ]
CN=$hostname
[ san_self_signed ]
subjectAltName = DNS:$hostname, DNS:localhost
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = CA:true
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign, cRLSign
extendedKeyUsage = serverAuth, clientAuth, timeStamping
"

openssl req \
  -newkey rsa:2048 -nodes \
  -keyout "$hostname.key.pem" \
  -x509 -sha256 -days 3650 \
  -config <(echo "$local_openssl_config") \
  -out "$hostname.cert.pem"
openssl x509 -noout -text -in "$hostname.cert.pem"

以上或多或少注入了openssl需求的最低限度的配置文件信息。

注意,DNS:localhost作为SAN 包含了额外的组件,以便更轻松地通过本地主机进行测试。如果不需要,请从脚本中删除该多余的位。

信用

bcardarella的答案很好(由于代表不足,无法发表评论/投票)。但是,答案使用的是特定于平台的现有openssl配置文件位置...因此:

为我工作

显然,只需要找到您自己给定平台的openssl配置文件并替换正确的位置即可。

测试

要进行测试,请在中导入test.cert.pemchrome的权威chrome://settings/certificates,并:

openssl s_server -key test.key.pem -cert test.cert.pem -accept 20443 -www &
openssl_pid=$!
google-chrome https://localhost:20443

并经过测试

kill $openssl_pid
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.