1700

我正在向嵌入式 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

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

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

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

4

19 回答 19

2729

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

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为您想要的域)。

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

于 2012-04-16T15:04:51.010 回答
626

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

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

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

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

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

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


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

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

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

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

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

要成为您自己的证书颁发机构,请参阅 *如何使用您的证书颁发机构签署证书签名请求?关于堆栈溢出。然后,将您的 CA 导入浏览器使用的信任库。

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

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

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

W3C 的 WebAppSec 工作组开始研究这个问题。例如,请参阅提案:将 HTTP 标记为不安全


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

下面的命令和配置文件创建一个自签名证书(它还向您展示了如何创建一个签名请求)。它们在一个方面与其他答案不同:用于自签名证书的 DNS 名称位于Subject Alternate Name (SAN)中,而不是Common Name (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/浏览器论坛指南的浏览器和其他用户代理下验证。

相关:浏览器遵循 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 可能会抱怨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 6797 和 RFC 7469,因为它们比其他 RFC 和 CA/B 文档更严格。RFC 6797 和 7469也不允许IP 地址。

于 2015-01-13T21:12:18.497 回答
546

# 2022 年更新

截至 2022 年,OpenSSL ≥ 1.1.1,以下命令可满足您的所有需求,包括主题备用名称 (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.comwww.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:另见

于 2016-12-28T17:30:16.993 回答
441

以下是@diegows 的答案中描述的选项,在文档中进行了更详细的描述:

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

如果指定了此选项,则如果创建了私钥,则不会对其进行加密。

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

于 2014-04-13T01:48:24.573 回答
170

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

  • 单行在密钥中包含密码短语。
  • 单线使用 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
于 2015-08-13T09:44:52.237 回答
80

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

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

  1. 创建一个 OpenSSL 配置文件(例如req.cnf:)

    [req]
    distinguished_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
    
  2. 创建引用此配置文件的证书

    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的示例配置

于 2017-05-09T02:37:22.057 回答
73

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

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

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

Google 安全博客中的更多信息。

2018 年 5 月更新。正如许多人在评论中指出的那样,使用 SHA-2 不会为自签名证书增加任何安全性。但我仍然建议使用它作为不使用过时/不安全的加密哈希函数的好习惯。完整的解释可以在为什么最终实体证书之上的证书是基于 SHA-1 的?.

于 2014-10-20T09:52:10.360 回答
23

这是我在本地机器上使用的脚本,用于在自签名证书中设置 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)服务器以使新证书生效。

于 2017-05-13T20:21:16.093 回答
23

我无法发表评论,所以我添加了一个单独的答案。我尝试为 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 个问题:

  1. 签署证书?说“Y”
  2. 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 
于 2020-01-21T07:23:31.097 回答
9

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,而无需其他配置文件。它取自这里的答案。

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

于 2017-09-20T16:27:21.243 回答
8

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' 选项前添加了斜线。

于 2017-11-28T10:11:39.947 回答
7

一个班轮 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"

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

>>更多这里<<

于 2017-09-11T15:14:39.710 回答
7

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

Javakeytool创建 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

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

于 2020-11-07T22:36:39.290 回答
6

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

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

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

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

  1. 生成私钥
  2. 使用该私钥创建 CSR 文件
  3. 向 CA 提交 CSR(威瑞信或其他等)
  4. 在 Web 服务器上安装从 CA 收到的证书
  5. 根据类型证书将其他证书添加到身份验证链

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

于 2015-04-02T06:15:31.100 回答
6

生成密钥

/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 error: Unable to get certificate from '...'

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

  • SSL error: Unable to get private key

    您的 MySQL 服务器版本可能不支持默认rsa:2048格式

    将生成的转换rsa:2048为普通rsa的:

    openssl rsa -in server-key.pem -out server-key.pem
    openssl rsa -in client-key.pem -out client-key.pem
    
  • 检查本地服务器是否支持 SSL

    mysql -u root -p
    mysql> show variables like "%ssl%";
    +---------------+----------------------------+
    | Variable_name | Value                      |
    +---------------+----------------------------+
    | have_openssl  | YES                        |
    | have_ssl      | YES                        |
    | 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';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | Ssl_cipher    |       |
    +---------------+-------+
    1 row in set (0.00 sec)
    

    否则,它将显示正在使用的密码的非零长度字符串:

    mysql> show status like 'Ssl_cipher';
    +---------------+--------------------+
    | Variable_name | Value              |
    +---------------+--------------------+
    | Ssl_cipher    | DHE-RSA-AES256-SHA |
    +---------------+--------------------+
    1 row in set (0.00 sec)
    
  • 特定用户的连接需要 ssl(“需要 ssl”):

    • SSL

    告诉服务器只允许该帐户的 SSL 加密连接。

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      REQUIRE SSL;
    

    要连接,客户端必须指定 --ssl-ca 选项来验证服务器证书,并且可以另外指定 --ssl-key 和 --ssl-cert 选项。如果既没有指定 --ssl-ca 选项也没有指定 --ssl-capath 选项,客户端不会验证服务器证书。


备用链接:使用 SSL 安全 PHP 连接到 MySQL中的冗长教程。

于 2015-10-08T21:36:12.357 回答
4

正如已经详细讨论过的,自签名证书 对于 Internet 是不可信的。您可以将自签名证书添加到许多但不是所有浏览器。或者,您可以成为自己的证书颁发机构

不想从证书颁发机构获得签名证书的主要原因是成本——赛门铁克每年为证书收取 995 美元到 1,999 美元之间的费用——仅针对用于内部网络的证书,赛门铁克每年收费 399 美元。如果您正在处理信用卡付款或为高利润公司的利润中心工作,那么这笔费用很容易证明是合理的。对于一个在互联网上创建的个人项目,或者对于一个以最低预算运行的非营利组织,或者如果一个人在组织的成本中心工作——成本中心总是试图做更多的事情,这超出了许多人所能承受的范围。少。

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

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

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

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

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

dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff

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

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

我的计划是编写一个脚本来使用 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
于 2019-02-25T21:52:11.490 回答
3

这对我有用

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`);
于 2020-12-05T06:16:28.567 回答
1

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

ERR_CERT_INVALID

在展开细节时,chrome 表示:

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

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

(输入键盘)thisisunsafe

这让我继续。

直到我发现extendedKeyUsage = serverAuth, clientAuth

TL;博士

  1. openssl genrsa -out localhost.key 2048

  2. openssl req -key localhost.key -new -out localhost.csr

  3. (在所有内容上单击输入,只需使用 localhost 或您的其他 FQDN 填写公用名 (CN)。

echo "
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
" > v3.ext
  1. openssl x509 -req -in localhost.csr -signkey localhost.key -out localhost.pem -days 3650 -sha256 -extfile v3.ext

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

于 2022-02-28T11:15:28.943 回答
0

生成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"
于 2021-12-27T13:35:30.253 回答