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

时间:2012-04-16 14:14:42

标签: ssl openssl certificate ssl-certificate x509certificate

我正在为嵌入式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时遇到了一些错误:

  

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

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

18 个答案:

答案 0 :(得分:1772)

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

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

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

days参数(365)可以替换为任何数字以影响到期日期。然后它会提示您输入“国家/地区名称”等内容,但您只需按 Enter 并接受默认设置。

添加-subj '/CN=localhost'以取消有关证书内容的问题(将localhost替换为您想要的域名。)

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

答案 1 :(得分:452)

  

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

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

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

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

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

如果没有成为您自己的权限,您必须获得正确的DNS名称,以便为证书提供最大的成功机会。但我鼓励你成为自己的权威。很容易成为你自己的权威,它会回避所有信任问题(谁比你自己更信任?)。


  

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

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

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

  1. 创建自己的权限(即成为CA
  2. 为服务器创建证书签名请求(CSR)
  3. 使用您的CA密钥对服务器的CSR进行签名
  4. 在服务器上安装服务器证书
  5. 在客户端上安装CA证书
  6. 第1步 - 创建自己的权限只是意味着创建一个带有CA: true和正确密钥用法的自签名证书。这意味着 Subject Issuer 是同一个实体,CA在 Basic Constraints 中设置为true(它也应该标记为关键),密钥用法为keyCertSigncrlSign(如果您使用的是CRL),主题密钥标识符(SKI)与授权密钥标识符相同(AKI)。

    要成为您自己的证书颁发机构,请参阅Stack Overflow上的* How do you sign a certificate signing request with your certification authority?。然后,将您的CA导入浏览器使用的Trust Store。

    当您获得StartcomCAcert等CA的服务时,步骤2 - 4大致就是面向公众服务器的操作。步骤1和5允许您避免第三方权限,并充当您自己的权限(谁比您自己更信任?)。

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

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

    W3C的WebAppSec工作组正在开始研究这个问题。例如,请参阅Proposal: Marking HTTP As Non-Secure


      

    如何使用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
    # DNS.7       = 127.0.0.1
    
    # IPv6 localhost
    # DNS.8     = ::1
    

    将DNS名称放在SAN而不是CN中非常重要,因为 IETF和CA /浏览器论坛都指定了这种做法。它们还指定不推荐使用CN中的DNS名称(但不禁止)。 如果您在CN中添加了DNS名称,则必须包含在CA / B策略下的SAN中。因此,您无法避免使用主题备用名称。

    如果您没有在DNS中放置DNS名称,则证书将无法在遵循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 may complain a 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地址。

答案 2 :(得分:386)

以下@diegows's answer中详细介绍的the documentation中描述的选项:

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

PKCS#10证书申请和证书生成实用程序。

-x509
     

此选项输出自签名证书而不是证书请求。   这通常用于生成测试证书或自签名根CA.

-newkey arg
     

此选项会创建新的证书申请和新的私钥。争论   采取几种形式之一。 rsa:nbits ,其中 nbits 是位数,   生成RSA密钥 nbits

-keyout filename
     

这给出了将新创建的私钥写入的文件名。

-out filename
     

默认情况下,它指定要写入的输出文件名或标准输出。

-days n
     

当使用 -x509 选项时,它指定要进行认证的天数   证书。默认值为30天。

-nodes
     

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

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

答案 3 :(得分:204)

自2019年起,以下命令可满足您的所有需求,包括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),
  • 相对较强(截至2019年)和
  • 有效期为3650天(〜10年)。

它会创建以下文件:

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

所有信息均在命令行中提供。没有讨厌的交互式输入。配置文件没有搞乱。所有必要的步骤都由这个单一的OpenSSL调用执行:从私钥生成到自签名证书。

备注#1:加密参数

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

将来,您可能希望使用超过4096位的RSA密钥和强于sha256的哈希算法,但是从2019年开始,这些是理智的值。它们足够强大,同时得到所有现代浏览器的支持。

备注#2:参数“-nodes

理论上你可以省略-nodes参数(这意味着“没有DES加密”),在这种情况下example.key将使用密码加密。但是,这对于服务器安装几乎没有用,因为您还必须将密码存储在服务器上,或者您必须在每次重新启动时手动输入密码。

备注#3:MinGW

在MinGW bash的Windows上,您应该在命令前添加MSYS_NO_PATHCONV=1

MSYS_NO_PATHCONV=1 openssl ...

或者,在普通cmd.exe Windows命令提示符下运行该命令。

备注#4:另见

答案 4 :(得分:127)

我无法发表评论,所以我将此作为一个单独的答案。我在接受的单行答案中发现了一些问题:

  • 单行内容包含密钥中的密码。
  • 单行使用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

答案 5 :(得分:71)

如果缺少SAN(主题备用名称),现代浏览器现在会为其他结构良好的自签名证书抛出安全性错误。 OpenSSL没有提供指定此 的命令行方式,因此许多开发人员的教程和书签突然过时了。

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

  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
    
  3. 来自https://support.citrix.com/article/CTX135602

    的配置示例

答案 6 :(得分:66)

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

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

  

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

Google Security blog中的更多信息。

更新于2018年5月。正如评论中所提到的那样,使用SHA-2不会为自签名证书添加任何安全性。但我仍然建议使用它作为不使用过时/不安全的加密哈希函数的好习惯。 Why is it fine for certificates above the end-entity certificate to be SHA-1 based? 中提供了完整的说明。

答案 7 :(得分:16)

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

答案 8 :(得分:10)

我无法发表评论,所以我添加了一个单独的答案。 我尝试为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-证书签名请求。因为这样的想法是通过根签署子证书并获得正确的证书

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

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

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

程序询问您2个问题:

  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 

答案 9 :(得分:9)

2017 one-liner:

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,而没有其他配置文件。 它来自答案here

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

答案 10 :(得分:6)

您的一般程序正确无误。该命令的语法如下。

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

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

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

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

    我在 Securing the Connection: Creating a Security Certificate with OpenSSL

    的帖子中有关于此的详细信息

答案 11 :(得分: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"

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

>> More here <<

答案 12 :(得分: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 '...'

    MySQL might be denied read access to your certificate file if it is not in apparmors configuration。如前面步骤中所述^,将所有证书保存为.pem目录中的/etc/mysql/文件,默认情况下由apparmor批准(或修改您的apparmor / SELinux以允许访问存储它们的任何位置。 )

  • SSL error: Unable to get private key

    Your MySQL server version may not support the default rsa:2048 format

    使用以下代码将生成的rsa:2048转换为普通rsa

    openssl rsa -in server-key.pem -out server-key.pem
    openssl rsa -in client-key.pem -out client-key.pem
    
  • Check if local server supports 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  |
    +---------------+----------------------------+
    
  • Verifying a connection to the database is SSL encrypted

      

    验证连接

         

    登录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)
    
  • Require ssl for specific user's connection(&#39;要求ssl&#39;):

      
        
    • SSL
    •   
         

    告知服务器仅允许该帐户使用SSL加密连接。

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

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

备用链接: Secure PHP Connections to MySQL with SSL 中的冗长教程。

答案 13 :(得分:3)

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"))

答案 14 :(得分:2)

self-signed certificates are not trusted for the Internet已详细讨论。您可以add your self-signed certificate to many but not all browsers。或者,您可以become your own certificate authority

不希望从证书颁发机构获得签名证书的主要原因是成本– Symantec charges between $995 - $1,999 per year for certificates -- just for a certificate intended for internal network, Symantec charges $399 per year。如果您正在处理信用卡付款或为一家高利润公司的利润中心工作,那么这一成本很容易得到证明。对于一个人正在互联网上创建的个人项目,或者对于以最低预算运行的非营利组织,或者如果一个人在组织的成本中心内工作,许多人买不起,成本中心总是尽力而为更少。

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

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

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

请注意,某些说明不太正确,并且花了点时间和Google才弄清楚。这是我第一次花费相当多的时间,但是现在我想我可以在几分钟内完成。

对于DigitalOcean,我遇到的一个难题是当系统提示我输入指向DigitalOcean凭据IN​​I文件的路径时。脚本所指的是Applications & API页面和该页面上的Tokens / Key选项卡。您需要具有或生成DigitalOcean API的个人访问令牌(读写)-这是一个65个字符的十六进制字符串。然后,需要将此字符串放入运行certbot的Web服务器上的文件中。该文件的第一行可以带有注释(注释以#开头)。第二行是:

<td align="right" colspan="4">${item.rate?string.currency}</td>

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

请注意,公钥证书(也称为身份证书或SSL证书)已过期,需要更新。因此,您将需要定期(重复)更新证书。 certbot文档涵盖renewing certificates

我的计划是编写一个脚本,以使用openssl命令获取证书的到期日期,并在30天或更短的时间内触发证书更新直到到期。然后,我将该脚本添加到cron并每天运行一次。

以下是读取证书的到期日期的命令:

dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff

答案 15 :(得分:1)

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

Java keytool创建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
来自GnuTLS的

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

答案 16 :(得分:0)

此处提供了使用OpenSSL的RSAECDSA的自签名证书和证书链创建脚本。

答案 17 :(得分:0)

这对我有用

openssl req -x509 -nodes -subj '/CN=localhost'  -newkey rsa:4096 -keyout ./sslcert/key.pem -out ./sslcert/cert.pem -days 365

server.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`);