如何使用openssl创build自签名证书?

我将https支持添加到embedded式Linux设备。 我试图通过以下步骤生成自签名证书:

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 

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

这可能不是你正在寻找的网站!
该网站的安全证书是不可信的!

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

你可以用一个命令来做到这一点:

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

如果您不想用密码保护您的私钥,也可以添加-nodes ,否则会提示您input“至less4个字符”的密码。 days参数(365)可以用任何数字replace以影响到期date。 然后,它会提示您input“国家名称”,但您可以按回车键并接受默认值。

自签名证书未经任何第三方validation,除非您先前将其导入浏览器。 如果您需要更多安全性,则应使用由CA签名的证书。

下面是@ diegows的答案中所描述的选项,从文档中有更详细的描述 :

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

PKCS#10证书请求和证书生成工具。

 -x509 

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

 -newkey arg 

这个选项创build一个新的证书请求和一个新的私钥。 争论采取几种forms之一。 rsa:nbits ,其中nbits是位数,生成大小为nbits的RSA密钥。

 -keyout filename 

这给了文件名写新创build的私钥。

 -out filename 

这指定了要写入的输出文件名或默认的标准输出。

 -days n 

当使用-x509选项时,它指定证书所用的天数。 默认是30天。

 -nodes 

如果指定了这个选项,那么如果一个私钥被创build,它将不会被encryption。

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

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

它很容易创build一个自签名证书。 你只需要使用openssl req命令。 创build一个可以被大量客户使用的浏览器和命令行工具,可能会非常棘手。

这很困难,因为浏览器有自己的要求,比IETF更具有限制性。 浏览器使用的要求logging在CA /浏览器论坛中 (请参阅下面的参考资料)。 这些限制出现在两个关键领域:(1)信任锚,(2)DNS名称。

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

有些浏览器并不完全容易导入自签名服务器证书。 事实上,你不能用一些浏览器,比如Android的浏览器。 所以完整的解决scheme就是成为你自己的权威。

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


这可能不是你正在寻找的网站!
该网站的安全证书是不可信的!

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

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

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

第1步 – 创build您自己的权限只是意味着创build一个CA: true的自签名证书CA: true和适当的密钥用法。 这意味着Subject和Issuer是同一个实体,CA在Basic Constraints中被设置为true(它也应该被标记为critical),key的用法是keyCertSigncrlSign (如果使用的是CRL),Subject Key Identifier(SKI )与权限密钥标识符(AKI)相同。

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

第2步到第4步大致上就是您在使用Startcom或CAcert之类的CA获得服务时面向公众服务的服务器。 步骤1和步骤5允许你避开第三方的权力,并作为你自己的权力(谁比你更信任?)。

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

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

W3C的WebAppSec工作组正在着手研究这个问题。 例如,请参阅“ build议:将HTTP标记为不安全” 。


如何使用openssl创build自签名证书?

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

将DNS名称通过configuration文件放置在SAN中,并使用subjectAltName = @alternate_names (无法通过命令行执行)。 然后在configuration文件中有一个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名称放在SAN中,则证书将无法在遵循CA /浏览器论坛准则的浏览器和其他用户代理下进行validation。

相关:浏览器遵循CA /浏览器论坛政策; 而不是IETF的政策。 这是使用OpenSSL(通常在IETF之后)创build的证书有时不能在浏览器(浏览器遵循CA / B)下validation的原因之一。 它们是不同的标准,它们有不同的发行政策和不同的validation要求。


创build一个自签名证书 (注意添加-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 

创build一个签名请求 (注意缺less-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 

configuration文件(通过-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 its 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 (eg 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. Ie, openssl req -x509 ... [ x509_ext ] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer # You only need digitalSignature below. *If* you don't allow # RSA Key transport (ie, 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. Ie, 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中的CN是什么关系。

 # IPv4 localhost # IP.1 = 127.0.0.1 # IPv6 localhost # IP.2 = ::1 

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

  • RFC 5280, Internet X.509公钥基础设施证书和证书撤销列表(CRL)configuration文件
  • RFC 6125: 在传输层安全性(TLS)环境中使用X.509(PKIX)证书在Internet公钥基础结构内表示和validation基于域的应用服务标识
  • RFC 6797,附录A, HTTP严格传输安全性(HSTS)
  • RFC 7469, HTTP的公钥固定扩展
  • CA /浏览器论坛基线要求
  • CA /浏览器论坛扩展validation指南

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

我不能评论,所以会把这个作为一个单独的答案。 我发现了一些接受的单行答案的问题:

  • 单线程包括密钥中的密码。
  • 单线程使用了许多浏览器在控制台中抛出警告的SHA1。

这是一个简化的版本,删除密码,提高安全性,以压制警告,并在评论中包含一个build议,以传入-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 

用你需要的任何域replace“localhost”。 您将需要逐一运行前两个命令,因为openssl会提示input密码。

将两者结合成一个.pem文件:

 cat server.crt server.key > cert.pem 

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

从接受的答案相同的命令行 – @diegows添加了-sha256

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

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

以下命令为有效期为3650天(〜10年)的域example.com创build相对较强的(截至2017年)证书。 它将私钥和证书保存到文件example.keyexample.crt

 openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout example.key -out example.crt -subj "/CN=example.com" -days 3650 

由于这是自签名证书,必须由用户手动接受,因此使用短期过期或弱密码是没有意义的。

将来,您可能希望使用超过4096位的RSA密钥和比sha256更强大的散列algorithm,但是到2017年sha256 ,这些都是理智的值。 它们在所有现代浏览器的支持下都足够强大。

附注:理论上你可以-nodes参数(意思是“不使用DESencryption”),在这种情况下example.key将被用密码encryption。 但是,这对于服务器安装来说几乎没有用处,因为这意味着您必须将密码存储在服务器上,或者必须在每次重新启动时手动input密码。

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

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

  1. 创build一个OpenSSLconfiguration文件(例如: 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 = keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = www.company.com DNS.2 = company.com DNS.3 = company.net 
  2. 创build引用此configuration文件的证书

     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中的示例configuration

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

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

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

由于这是自签名证书,因此不存在CA,您可以放心地忽略警告并继续。 如果你想得到一个真正的证书,将被任何人在公共互联网上辨认,那么程序如下。

  1. 生成一个私人密钥
  2. 使用该私钥来创build一个CSR文件
  3. 将CSR提交给CA(Verisign或其他人)
  4. 在Web服务器上安装从CA获得的证书
  5. 根据证书types将其他证书添加到身份validation链

我在https://bigthinkingapplied.com/secure-the-connection-installing-certificates-on-3-common-web-servers/发表了一篇文章,;

这是我在本地框上使用的脚本来设置自签名证书中的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" 

此脚本还会写入一个信息文件,以便您可以检查新证书并validationSAN是否已正确设置。

  ... 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,那么您可以在configuration文件中引用上面的证书,如下所示:

 <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)服务器以使新证书生效。

生成密钥

我使用/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; 

添加configuration

/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服务器login到: /var/log/mysql/error.log

跟进注意事项:

  • SSL error: Unable to get certificate from '...'

    如果它不在apparmorsconfiguration中,Mysql可能会被拒绝读取您的证书文件 。 正如在前面的步骤^中提到的,将所有证书保存为.pem文件,并将其保存在默认的apparmor允许的/etc/mysql/目录中(或者修改你的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 | +---------------+----------------------------+ 
  • validation到数据库的连接是sslencryption的 :

    validation连接

    login到MySQL实例时,可以发出查询:

     show status like 'Ssl_cipher'; 

    如果您的连接没有encryption,结果将是空的:

     mysql> show status like 'Ssl_cipher'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Ssl_cipher | | +---------------+-------+ 1 row in set (0.00 sec) 

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

     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

    通知服务器仅允许该帐户的SSLencryption连接。

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

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


备用链接:在这里http://www.madirish.net/214冗长的教程;

2017年一class:

 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,而不需要另外的configuration文件。 从这里回答。 这将创build一个包含私钥和证书的.pem文件。 如果需要,可以将它们移动到单独的.pem文件中。

一个class轮FTW。 我喜欢保持简单。 为什么不使用一个包含所有需要的参数的命令? 这就是我喜欢的方式 – 这将创build一个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" 

该单一命令包含您通常为证书详细信息提供的所有答案。 这样你可以设置参数并运行命令,得到你的输出 – 然后去喝咖啡。

>>更多这里<<