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


1291

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

可以,但是我在使用Google Chrome时遇到了一些错误:

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

我想念什么吗?这是构建自签名证书的正确方法吗?


40
自签名证书被认为对Internet不安全。Firefox会将网站视为无效证书,而Chrome则将其视为纯HTTP连接。更多详细信息:gerv.net/security/self-signed-certs
user1202136 2012年

34
您需要将CA证书导入到浏览器中,并告诉浏览器您信任该证书-或-由已经被浏览器信任的大型无偿组织之一对其进行签名-或-忽略警告并单击过去了。我自己喜欢最后的选择。
trojanfoe 2012年

12
您不应该那样使用“常规” OpenSSL设置。这是因为您无法将DNS名称放在主题备用名称(SAN)中。您需要为配置文件提供一个alternate_names部分,并将其与-config选项一起传递。同样,IETF和CA /浏览器论坛均不建议(但不禁止)在通用名称(CN)中放置DNS名称。CN中的任何DNS名称也必须存在于SAN中。无法避免使用SAN。请参阅下面的答案。
jww 2015年

5
除了@jww的评论。2017年5月,Chrome不再接受不包含(空)SAN的证书:“此站点的证书不包含包含域名或IP地址的使用者备用名称扩展名。”
GerardJP

6
这些天来,只要您的Web服务器可以通过Internet上的端口80上的FQDN对其进行访问,就可以使用LetsEncrypt并获得免费的完整CA证书(有效期为90天,可以自动更新),该证书不会给出任何浏览器警告/消息。www.letsencrypt.com
巴尼

Answers:


2130

您可以通过以下命令执行此操作:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

如果您不想使用密码来保护私钥,也可以添加-nodes(的缩写no DES)。否则,它将提示您输入“至少4个字符”的密码。

days您可以将参数(365)替换为任何数字以影响到期日期。然后,它将提示您输入“国家名称”之类的内容,但是您只需点击Enter并接受默认值即可。

添加-subj '/CN=localhost'以消除关于证书内容的问题(替换localhost为所需的域)。

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


8
如果您想自己验证任何内容,对于有兴趣的任何人,这里是文档

17
与第三方签约如何提供更高的安全性?
James Mills 2014年

201
对于在自动化中使用此工具的其他人,这里是该主题的所有常用参数:-subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=www.example.com"
Alex S

16
@JamesMills我的意思是,考虑一下-如果在他面包车侧面写有“免费糖果”的阴凉面的家伙邀请你进去,那你将要三思而后行-但是如果您信任的人- 真正信任的人-就像“裸体男人,他是合法的”,那么您将只剩下那免费的糖果。
BrainSlugs83 2015年

73
切记用于-sha256生成基于SHA-256的证书。
Gea-Suan Lin

534

我想念什么吗?这是构建自签名证书的正确方法吗?

创建自签名证书很容易。您只需要使用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适当密钥用法的自签名证书。这意味着主题颁发者是同一实体,在基本约束中将CA设置为true (也应将其标记为关键),密钥用法为keyCertSigncrlSign(如果使用的是CRL),主题密钥标识符(SKI)为与授权机构密钥标识符(AKI)相同。

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

当您征求诸如StartcomCAcert之类的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地址。


4
可以在本alternate_names节中使用通配符吗?特别是子子域。我有一个问题在这里引用此答案:serverfault.com/questions/711596/…–
LeonardChallis

3
我刚刚回答了他的具体问题。我觉得没有意义添加此长的安全说明当答案是如此简单
迭戈Woitasen

14
@diegows-您的答案不完整或不正确。不正确的原因在您不想读的长篇文章中进行了讨论:)
jww

1
谢谢!我发现您的帖子非常有帮助。仅供参考,我最近正在与Vault一起玩,发现它坚持使用IP.x 127.0.0.1而不是DNS.x 127 ...我没有检查这是否在标准中。
Chomeh

4
谢谢@jww。您说:“ 1。创建自己的权限(即成为CA)”,然后说:“ 5。在客户端上安装CA证书”。如果根密钥被盗用,则恶意人员可以使用该密钥为任何域签名证书,并且如果他们诱使您进入其网站,则他们现在可以进行中间人攻击。有没有一种方法可以创建根CA,使其只能签署中间CA而不能签署证书?然后,您可以使用名称约束来保护中间CA。
罗宾·齐默尔曼

408

这是@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

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

该文档实际上比上述文档更详细;我在这里总结一下。


3
XXX原始命令中的in应该替换为“认证证书的天数”。默认值为30天。例如,如果您希望您的证书有效期为365天,则-days XXX变为-days 365有关更多信息,请参阅文档
内森·琼斯

感谢您添加文档。该IBM链接上的使用命令来
Red Pea 2015年

313

截至2020年,以下命令可满足您的所有需求,包括SAN:

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:example.net,IP:10.0.0.1
    ) \
  -subj "/CN=example.com"

在OpenSSL≥1.1.1中,可以缩短为:

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:example.net,IP:10.0.0.1"

它创建的证书是

  • 对域example.comexample.net(SAN)有效,
  • 对IP地址10.0.0.1(SAN)也有效,
  • 相对强劲(截至2020年)和
  • 有效期为3650几天(约10年)。

它创建以下文件:

  • 私钥: example.key
  • 证书: example.crt

所有信息都在命令行中提供。有没有交互式输入惹恼你。有没有配置文件,你必须更动。所有必要的步骤都由一个OpenSSL调用执行:从私钥生成到自签名证书。

备注1:加密参数

由于证书是自签名的,需要用户手动接受,因此使用短有效期或弱加密是没有意义的。

将来,您可能想4096为RSA密钥使用更多的位,并使用比强大的哈希算法sha256,但是从2020年开始,这些值是合理的。它们足够强大,同时得到所有现代浏览器的支持。

备注#2:参数“ -nodes

从理论上讲,您可以省略该-nodes参数(表示“无DES加密”),在这种情况下,example.key将使用密码进行加密。但是,这几乎对服务器安装几乎没有用,因为您要么必须将密码也存储在服务器上,要么必须在每次重新启动时手动输入密码。

备注3:另请参见


1
我无法弄清楚应将arg / CN = localhost扩展到C:/ Program Files / Git / CN = localhost究竟是什么原因,所以我只在cmd.exe中运行了整个命令,就可以了。以防万一有人在为此挣扎。
尤里·波兹尼亚克

1
@FranklinYu您确定rsa:2048从现在开始的10年内就足够了吗?因为那是有效期。如前所述,使用短到期或弱加密没有意义。大多数2048位RSA密钥的有效期最长为1-3年。关于OpenSSL 1.1.1,我仍然将sha256保留在其中,因此,如果您想要更强大的哈希,则进行更改更加明确和明显。
vog

1
然后@DaveFerguson不是证书创建的//CN=localhost,而不是/CN=localhost?适当的转义对您有帮助吗?例如,用替换是否/CN=localhost可以"/CN=localhost"彻底解决问题?
vog

4
1000 +1可以创建一个使用新的所需SAN的“单层”,而无需创建带有大量样板的冗长的配置文件。做得好!
约书亚·品特

1
@cautionbug谢谢!我只是将其编辑为答案。现在答案对于Windows / MinGW正确吗?
vog

142

我无法发表评论,因此我将其作为一个单独的答案。我发现了公认的一线回答的一些问题:

  • 单行代码在密钥中包含一个密码短语。
  • 一线使用SHA-1,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

6
我需要github.com/molnarg/node-http2的开发人员证书,这个答案是最好的。
卡帕杰2015年

1
要结合证书,并在单个文件的密钥:cat server.crt server.key >foo-cert.pem。适用于openssl-1.0.2d/demos/ssl/
18446744073709551615

我以这种方式生成的证书仍在使用SHA1。
user169771 2016年

1
Tks,在FreeBSD 10 OpenLDAP 2.4TLS
Thiago Pereira

2
那么key.pem文件呢?
quikchange '16

72

现在,现代浏览器如果缺少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的示例配置


1
在删除导致错误的最后一个参数-extensions'v3_req'后,它为我工作。针对Windows使用OpenSSL。最后,我设法解决了这个问题!谢谢。
CGodo

1
@Kyopaxa你是对的-该参数对于cnf文件的第3行是多余的;更新。
rymo

2
扎实的方法。谢谢。我建议添加-sha256
cherouvim

5
您现在可以在命令行上指定SAN,-extension 'subjectAltName = DNS:dom.ain, DNS:oth.er'请参阅github.com/openssl/openssl/pull/4986
Alexandre DuBreuil

2
看来此选项已被调用-addext
亚历山大·扎鲁布金

67

我建议添加-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的最终实体证书之上的证书?


1
如果它是一个自签名密钥,则无论如何都会产生浏览器错误,所以这并不重要
标记

30
@马克,它很重要,因为SHA-2是更安全
马里斯B.

1
将cert.pem重命名为cert.cer后,在Windows中打开证书,表示指纹算法仍为Sha1,但签名哈希算法为sha256。
犯罪


4
请注意,自签名证书上使用的签名算法与确定它是否可信无关。根CA证书是自签名的。截至2018年5月,仍然有许多SHA-1签名的活动根CA证书。因为证书是否信任自己并不重要,该证书如何验证信任也无关紧要。您可以信任根/自签名证书,可以不信任它。请参阅security.stackexchange.com/questions/91913/…–
安德鲁·亨利

20

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


可在macOS High Siera和Chrome 58上运行
Saqib Omer,

我仍然不确定CN如何影响整体设置?我正在尝试将其作为localhost127.0.0.1:port#与之对应CN的东西运行。
DJ2

@ DJ2我将设置BASE_DOMAIN =“ localhost”
Drakes

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文件中。


2
对于Linux用户,您需要为配置更改该路径。例如,目前Ubuntu的/etc/ssl/openssl.conf作品
词尾

有关不需要您指定openssl.cnf位置的
单行代码

7

我无法发表评论,所以我添加了一个单独的答案。我尝试为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=root organisation
organizationalUnitName=roote department
commonName=root
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

[ v3_req ]
keyUsage=digitalSignature
basicConstraints=CA:true
subjectKeyIdentifier = hash
subjectAltName = @alternate_names

您的子证书的下一个配置文件。

[ 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=FirstName LastName
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

[ 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 0

echo 1 > 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 = supplied
organizationalUnitName = optional
commonName = supplied

您可能会问,为什么如此困难,为什么我们必须再创建一个配置以通过根签名子证书。答案很简单,因为子证书必须具有SAN块-使用者备用名称。如果我们通过“ openssl x509”实用工具对子证书进行签名,则根证书将删除子证书中的SAN字段。因此,我们使用“ openssl ca”而不是“ openssl x509”来避免删除SAN字段。我们创建一个新的配置文件,并告诉它复制所有扩展字段copy_extensions = copy

openssl ca -config config_ca.cnf -out market.crt -in market.csr

该程序会问您两个问题:1.签署证书?说“ Y” 2. 1个证书请求中有1个被认证,提交?说“ Y”

在终端中,您会看到一个带有“数据库”字样的句子,它表示由命令“ touch”创建的文件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 

2
尽管此过程看起来很复杂,但这正是我们对.dev域所需要的,因为该域不支持自签名证书,并且Chrome和Firefox强制使用HSTS。我按照该步骤进行操作,即创建CA,创建证书并用我的CA对其进行签名,最后在浏览器中信任我的CA。谢谢。
bajicdusko

1
先生,您是该死的传奇。我的家庭实验室谢谢您!
antyawn

6

您的常规步骤正确。该命令的语法如下。

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

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

由于这是自签名证书,因此没有CA,您可以放心地忽略该警告并继续进行。如果您想获得可以被公共Internet上的任何人识别的真实证书,请按照以下步骤操作。

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

我在保护连接安全:使用OpenSSL创建安全证书的文章中对此有更多详细信息。


6

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

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

>>更多在这里<<


1
除了SAN以外的所有参数... @vog的答案也涵盖了这一点(并早于此)(尽管其中填写了更完整的“主题”字段...)(也不是一年到期的忠实拥护者)
Gert van den Berg '18

6

一线版2017:

CentOS的:

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'选项。


3

产生金钥

/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可能被拒绝对您的证书文件进行读取访问。如前面的步骤^所述,将我们所有的证书保存为.pem文件,该文件位于/etc/mysql/apparmor默认批准的目录中(或修改apparmor / SELinux以允许访问存储它们的任何位置。)

  • 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(“ require ssl”):

    • SSL协议

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

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

    要进行连接,客户端必须指定--ssl-ca选项以认证服务器证书,并且可以另外指定--ssl-key和--ssl-cert选项。如果未指定--ssl-ca选项和--ssl-capath选项,则客户端不会对服务器证书进行身份验证。


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


-1; 这在很大程度上与所提出的问题有关,并且在弄清楚其引用来自何处也做得不好。
Mark Amery

这显示调配CA,由CA签名的服务器/客户端证书,配置它们以供具有apparmor的主机上的mysqld读取。它举例说明了在同一台计算机上托管ca,服务器和客户端的相当无用的情况,并将该ca的权限公开给mysqld进程很危险。除了在测试环境中测试ssl配置外,此设置实际上没有任何意义。对于运行内部CA,我建议在openssl help.ubuntu.com/community/GnuTLS上使用gnuttls工具链,并在解决mysqld + apparmor案例之前对tls有很好的了解
ThorSummoner

3

如已详细讨论的那样,自签名证书 不受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凭据IN​​I文件的路径时。该脚本所指的是“ 应用程序和API”页面以及该页面上的“令牌/密钥”选项卡。您需要拥有或生成DigitalOcean API的个人访问令牌(读写)-这是一个65个字符的十六进制字符串。然后,需要将此字符串放入运行certbot的Web服务器上的文件中。该文件的第一行可以带有注释(注释以#开头)。第二行是:

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
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.