当前位置: 首页 > 知识库问答 >
问题:

如何使用OpenSSL生成自签名SSL证书?[已关闭]

姬念
2023-03-14

我们不允许对堆栈溢出提出有关专业服务器或网络相关基础设施管理的问题。您可以编辑问题,使其位于堆栈溢出主题上。

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

这工作,但我得到一些错误,例如,谷歌Chrome:

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

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

共有3个答案

廖臻
2023-03-14

截至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调用执行的:从私钥生成到自签名证书。

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

将来,您可能希望使用超过4096位的RSA密钥和比sha256强的哈希算法,但截至2022年,这些都是正常值。它们足够强大,同时受到所有现代浏览器的支持。

理论上,您可以省略-节点参数(这意味着“无DES加密”),在这种情况下,请参见示例。密钥将使用密码加密。但是,这对于服务器安装几乎没有任何用处,因为您要么必须在服务器上存储密码,要么必须在每次重新启动时手动输入密码。

  • 在命令行上直接向openssl提供subjectAltName
  • 如何通过命令行向SSL证书添加多个电子邮件地址
  • 有关MSYS\u NO\u PATHCONV的详细信息

锺伟志
2023-03-14

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

创建自签名证书很容易。您只需使用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)相同。

要成为您自己的证书颁发机构,请参阅*如何与您的证书颁发机构签署证书签名请求?在Stack Overflow上。然后,将您的CA导入浏览器使用的信任存储。

当您使用Startcom或CAcert等CA的服务时,步骤2-4大致是您现在为面向公共的服务器所做的。步骤1和5允许您避免第三方权威,并充当您自己的权威(谁比您自己更值得信任?)。

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

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

W3C的WebAppSec工作组正在开始研究这个问题。例如,请参见建议:将HTTP标记为不安全

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

下面的命令和配置文件创建自签名证书(它还显示了如何创建签名请求)。它们在一个方面与其他答案不同:用于自签名证书的DNS名称位于使用者备用名称(SAN)中,而不是通用名称(CN)。

DNS名称通过配置文件放置在SAN中,其行为subjectAltName=@alternate\u names(无法通过命令行执行)。然后在配置文件中有一个alternate\u 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名称已弃用(但未被禁止)。如果在CN中放置DNS名称,则必须根据CA/B策略将其包括在SAN中。因此,您无法避免使用Subject备用名称。

如果不在SAN中放置DNS名称,则证书将无法在遵循CA/浏览器论坛指南的浏览器和其他用户代理下验证。

相关:浏览器遵循CA/Browser Forum策略;而不是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

配置文件(通过配置选项传递)

[ 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\u CERT\u Common\u Name\u invalid)。我不确定SAN中的IP地址与此实例中的CN之间的关系。

# IPv4 localhost
# IP.1       = 127.0.0.1

# IPv6 localhost
# IP.2     = ::1

关于X.509/PKIX证书中DNS名称的处理,还有其他规则。有关规则,请参阅这些文件:

  • RFC 5280,Internet X.509公钥基础设施证书和证书吊销列表(CRL)配置文件

列出了RFC 6797和RFC 7469,因为它们比其他RFC和CA/B文档更具限制性。RFC 6797和7469也不允许IP地址。

陆飞龙
2023-03-14

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

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

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

您可以用任何数字替换天数参数(365),以影响到期日期。然后,它会提示您输入“Country Name”之类的内容,但您只需点击Enter并接受默认值即可。

添加sub“/CN=localhost”以抑制有关证书内容的问题(用所需域替换localhost)。

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

 类似资料:
  • 我是不是漏掉了什么?这是构建自签名证书的正确方法吗?

  • 我正在为嵌入式Linux设备添加HTTPS支持。我尝试通过以下步骤生成自签名证书: 这是可行的,但我得到一些错误,例如,谷歌Chrome:

  • 我想在JettyDistribution-9.2.9.v20150224上配置SSL 并将ssl和https模块配置为start.ini,Jetty工作正常。 但是,从keystore中提取的证书不能被浏览器信任。所以我想使用Openssl创建自签名证书 我的Openssl版本是0.9.8,我通过以下步骤生成keystore: 但是,这个TrustStore.KeyStore不能工作。Http工作

  • 本文档提供使用 openssl 生成自签名证书的一个示例,用户也可以根据自己的需求生成符合要求的证书和密钥。 假设实例集群拓扑如下: Name Host IP Services node1 172.16.10.11 DM-master1 node2 172.16.10.12 DM-master2 node3 172.16.10.13 DM-master3 node4 172.16.10.14 DM

  • 问题:由于“无法联系服务器”,用户无法登录移动应用程序 调试消息:“类型错误: 网络请求失败” 尝试修复:重新启动服务器,验证数据库正在运行并且没有任何更改,重新启动服务器正在运行的VM,我使用postman检查了api。当我运行一个简单的POST请求时,收到以下消息: 连接到时出错https://app.something.com/api/Accounts/5076/sometest?filte

  • 问题内容: 我需要在运行时生成自签名证书,对其进行签名并导入到Java密钥库中。我可以通过以下方式从命令行使用“ keytool”和“ openssl”来做到这一点: 当然,我可以使用keytool和openssl二进制文件来交付我的应用程序,并从Java执行上述命令,但是我正在寻找一种更干净的方法,该方法允许我使用纯Java来完成上述所有操作。 我可以使用任何库吗? 问题答案: 使用Bouncy