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

bca*_*lla 70 ssl openssl ssl-certificate chrome

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

相反,它需要使用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
Run Code Online (Sandbox Code Playgroud)

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

openssl req \
-new \
-key server.key \
-out server.csr \
-config config.cnf \
-sha256 \
-days 3650
Run Code Online (Sandbox Code Playgroud)

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

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

但是,在此之后,我仍然ERR_CERT_COMMON_NAME_INVALID在 Chrome 58 中获得了。

bca*_*lla 77

我的解决方案:

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
Run Code Online (Sandbox Code Playgroud)

状态:为我工作

  • 更新到 Chrome 59 后,证书显示如下错误:站点的证书链 (net::ERR_CERT_COMMON_NAME_INVALID) 存在问题。 (3认同)
  • 很好地使用了子外壳。我认为您可以稍微简化一下:`-config &lt;(cat /System/Library/OpenSSL/openssl.cnf ; printf '[SAN]\nsubjectAltName=DNS:dev.mycompany.com')` (2认同)

小智 19

在 Windows 中,将此脚本作为 makeCERT.bat 保存在您的 SSL 文件夹中。它将创建这些文件: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
Run Code Online (Sandbox Code Playgroud)


bin*_*ala 18

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

创建 CA 密钥和证书

# openssl genrsa -out server_rootCA.key 2048
# openssl req -x509 -new -nodes -key server_rootCA.key -sha256 -days 3650 -out server_rootCA.pem
Run Code Online (Sandbox Code Playgroud)

创建 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
Run Code Online (Sandbox Code Playgroud)

创建 v3.ext 配置文件

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

[alt_names]
DNS.1 = server.berlin
Run Code Online (Sandbox Code Playgroud)

创建服务器密钥

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

创建服务器证书

# openssl x509 -req -in server.csr -CA server_rootCA.pem -CAkey server_rootCA.key -CAcreateserial -out server.crt -days 3650 -sha256 -extfile v3.ext
Run Code Online (Sandbox Code Playgroud)

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

SSLCertificateFile    /etc/apache2/ssl/server.crt
SSLCertificateKeyFile    /etc/apache2/ssl/server.key
Run Code Online (Sandbox Code Playgroud)

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

# scp you@server.berlin:~/server_rootCA.pem .
Run Code Online (Sandbox Code Playgroud)

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

Chromium -> Setting -> (Advanced) Manage Certificates -> Import -> 'server_rootCA.pem'
Run Code Online (Sandbox Code Playgroud)

你已经完成了!

PS您可以简单地在 HTTP 服务器配置中禁用 HSTS 标头,而不是创建功能性 CA 和服务器证书对(按照上述说明)。这将阻止 Chromium 强制执行 HTTPS 并允许用户单击“高级?继续到 your.url (unsafe)”,而无需获取和安装您的自定义 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"
Run Code Online (Sandbox Code Playgroud)

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

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

  • 有人可以向我解释为什么这个领域的每个人似乎都使用像 `-config &lt;( cat server_rootCA.csr.cnf )` 这样的 bashisms 而不仅仅是 `-config server_rootCA.csr.cnf` 吗? (7认同)

pav*_*von 16

有几个很好的答案给出了如何让这个工作的例子,但没有一个解释在你的尝试中出现问题的地方。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
         ...
Run Code Online (Sandbox Code Playgroud)

但是,如果您使用 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
         ...
Run Code Online (Sandbox Code Playgroud)

原因是默认情况下 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
Run Code Online (Sandbox Code Playgroud)

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

$ openssl req -x509 -sha256 -days 365 -key server.key -out server.crt -config config.cnf
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

  • 这是帮助我理解为什么证书没有 SAN 的唯一解释(在我的情况下,我需要在配置文件中包含 x509_extensions) (2认同)

JPv*_*iel 5

带有配置的 Bash 脚本

作为应该使用 bash 跨平台工作的 shell 脚本。假设HOSTNAME为 shell 设置了 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, IP:127.0.0.1, IP:::1
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"
Run Code Online (Sandbox Code Playgroud)

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

请注意,包含额外DNS:localhost的 SAN 以允许更轻松地通过本地主机进行测试。如果您不想要它,请从脚本中删除该额外的位。

信用

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

为我工作

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

测试

对于一种测试方法,导入test.cert.pem到 chrome 的权限中chrome://settings/certificates,并且:

openssl s_server -key test.key.pem -cert test.cert.pem -accept 20443 -www &
openssl_pid=$!
google-chrome "https://localhost:20443"
google-chrome "https://127.0.0.1:20443"
google-chrome "https://[::1]:20443"
Run Code Online (Sandbox Code Playgroud)

并且经过测试

kill $openssl_pid
Run Code Online (Sandbox Code Playgroud)

  • 在某些情况下,主机名是 IP 地址。当前的 Chrome (v80) 将拒绝具有标记为“DNS”的 IP 地址的 SAN 的证书,需要将其设置为 IP:123.123.123.123(或任何 IP 地址) (2认同)