RSA与ECC比较。 使用包装在Docker映像中的certbot和acme.sh客户端颁发LetsEncrypt证书。 Nginx设置
目录
- RSA与ECC比较。 为什么您可能需要ECDSA证书?
- 如何使用
openssl
生成RSA和EC密钥/ CSR。 - 什么是LetsEncrypt CA ? 如何以自动方式发布免费的域验证证书?
- 如何在仍然使用certbot和acme.sh客户端的情况下通过Docker映像生成RSA和/或ECDSA证书?
- 如何为RSA / ECDSA混合设置配置和测试Nginx?
RSA与ECC比较
RSA是最流行的公共密钥加密算法。 带有RSA密钥的证书是黄金标准,也是当前Internet PKI 安全性的体现 。 这是一种古老且经过考验的技术 ,从安全角度来看,这非常重要。 椭圆曲线密码术是当前RSA标准上公钥密码术的另一种方法。
RSA算法可用于加密和数字签名,而ECC仅可用于签名。
密钥的安全性取决于其大小和算法。 一些算法比其他算法更容易破解。 破解RSA密钥需要考虑两个大数的乘积。 破解ECC密钥需要找到椭圆曲线上各点之间的离散对数,到目前为止,尚无进展。
对于相同的安全级别,算法需要不同的密钥大小。 ECC可以使用较小的密钥。 这是密钥大小比较表:
+----------------------+-----------------+--------------------+
| Symmetric Key length | RSA key length | ECC key length |
+----------------------+---------- ------+--------------------+
| 80 | 1024 | 160 |
| 112 | 2048 | 224 |
| 128 | 3072 | 256 |
| 192 | 7680 | 384 |
| 256 | 15360 | 512 |
+----------------------+-----------------+--------------------+
例如,256位ECC密钥等效于RSA 3072位密钥,可提供128位安全性:
较小的密钥用于生成签名的计算量较小,因为数学涉及较小的数字。 但是,尽管ECC在签名生成方面更快,但在签名验证方面却比RSA慢。 让我们使用openssl作为基准测试工具来进行测量:
$ openssl speed ecdsap256 rsa2048
sign/s verify/s
rsa 2048 bits 679.0 23489.0
256 bit ecdsa (nistp256) 15581.9 6211.7
较小的ECC公钥意味着较小的证书大小-传递的数据更少,下载更快,TLS握手更快 。
如果需要更高的安全性,则RSA无法很好地扩展-您必须增加RSA模数的速度远远快于ECDSA曲线的大小。 1024位RSA密钥已过时,而2048是当前的标准大小。 如果您需要走的更远,您将陷入困境。 首先,如果CA不提供4096位RSA密钥链,则用2048个RSA中介对您自己的4096位RSA密钥进行签名是没有意义的。 其次,请注意,每将RSA私钥加倍,TLS握手性能就会下降大约6到7倍。 因此,如果需要更高的安全性,请选择ECC。
尽管ECC有一些好处,但也有一些缺点。 该技术还没有像RSA那样成熟和经过测试。 并且存在兼容性问题,但是似乎可以在大多数操作系统和现代浏览器上使用。 请查看这些资源以获取ECC兼容性详细信息 。
那里有很多椭圆曲线。 主要浏览器最受欢迎和支持的是P-256,P-384,P-521,x25519。 虽然P-256和P-384是NIST Suite B算法的一部分,但P-521和x25519不是。 谷歌浏览器下降支持了P-521曲线 , 同样是怎么回事就NSS / Firefox浏览器。 为了最大化与现有浏览器和服务器的互操作性,请prime256v1
P-256 prime256v1
和P-384 secp384r1
曲线。
要查看所有可用ECC曲线的列表,OpenSSL库支持:
openssl ecparam -list_curves
要查看浏览器支持的曲线,请使用SSL Labs客户端测试 。
最后,ECDSA证书的优缺点:
- (+)较小的密钥和证书大小, 更快的TLS握手
- (+)从服务器角度看性能更好 ,需要更少的CPU和内存
- (+)更强大的算法,更难破解
- (+)在需要更高安全性时可以更好地扩展
- (-)不像RSA那样成熟且经过时间检验,与RSA相比,ECC相对较新
- (-)缺乏兼容性,缺乏广泛的支持。
- (-)ECC更快并且可以生成签名,但是签名验证的计算量大,并且比RSA慢
您无需仅在RSA和ECC之间进行选择。 您可以设置混合配置,首先提供ECDSA证书,对不支持的客户端回退到RSA证书。
使用openssl生成RSA和ECC密钥/ CSR
通常,在将请求发送到CA颁发证书之前,您需要生成私钥和CSR(证书签名请求)。 使用openssl
工具超级简单。
生成给定长度的RSA密钥:
openssl genrsa -out example.key 2048
生成具有给定曲线的EC密钥:
openssl ecparam -genkey -name secp384r1 | openssl ec -out ec.key
根据给定主题信息从现有私钥生成CSR:
openssl req -new -key example.key -out example.csr -subj "/CN=example.com" -sha256
或者,您可以在一个命令中结合创建密钥和CSR:
openssl req -nodes -newkey rsa:2048 -keyout example.key -out example.csr -sha256
LetsEncrypt CA
如果要试验ECDSA和RSA证书,最好的选择是使用LetsEncrypt证书颁发机构 ,它可以自动生成免费的域验证证书。
为了获得证书,您需要证明域的所有权。
通常,此过程需要人工完成:生成具有相关主题信息和公用名的私钥和CSR(证书签名请求),将CSR发送给CA,最后使用选定的质询方法证明域的所有权:
- 电子邮件 ; CA发送带有验证链接的电子邮件,该地址为[email protected]等地址之一。 您需要点击链接以完成验证。
- http; 您需要下载带有特制令牌的文件,然后将其上传到您的域根文件夹,因此可以通过URI http://example.com/.well-known/pki-validation访问该文件
- dns; 您必须在域的DNS配置中创建特殊的CNAME记录
LetsEncrypt通过使用可以使用ACME协议 (自动证书管理环境)的客户端来自动执行此过程。 客户端通常在您的Web主机上运行,并与LetsEncrypt CA或其他兼容ACME的服务器通信。 客户端从服务器接收唯一令牌,从中生成密钥,启动侦听端口80的独立Web服务器,并在特殊URI(例如http://example.com/.well-known/acme-challenge)上提供密钥。 如果使用DNS质询方法,则客户端可以根据DNS服务器/提供程序自动将CNAME记录添加到您的DNS配置中。 然后,LetsEncrypt CA向您的域发出HTTP或DNS请求,以检索从令牌派生的密钥。 成功的响应证明了域所有权,并且CA颁发了所请求的证书。
您不需要自己生成私钥和CSR,这是由Web主机上的客户端软件处理的。 请注意,私钥永远不会在CA服务器上生成/泄露,而只能存储在Web主机上。 客户端通常提供某种方式来通过客户端调整某些设置,例如密钥长度,主题备用名称,或者如果您需要进一步的自定义,则可以回退到提供自定义CSR以获得更大的灵活性和控制力。
请注意,Lets Encrypt的证书仅有效90天。 这是为了鼓励用户自动执行证书颁发和更新过程。
速率限制和登台服务器
请注意,LetsEncrypt CA生产服务器设置了严格的速率限制 :
- 每个注册域的证书(每周20个)
- 每个证书最多100个备用名称
- 每周5份证书的重复证书限制
在尝试进行试验时,很可能会遇到后一种情况,因此最好使用宽松的限制来使用LetsEncrypt过渡环境 。
暂存环境中间证书(“ 伪LE中间X1 ”)是由浏览器/客户端信任存储中不存在的根证书颁发的,因此您可能希望在测试时将“伪LE根X1”添加为受信任的证书。
使用Docker映像生成LetsEncrypt证书
ACME客户有很多: certbot , acme.sh , lego 等 。 我不会在这里深入介绍客户的具体信息-无论如何,文档会更好地解释。
就个人而言,我发现完成工作的更简便快捷的方法是通过某些Docker映像颁发证书。 这适用于懒惰的人,以及那些不想花很多时间来研究LetsEncrypt和分析文档的人。
我准备了一个:Docker Hub和Github link上的asamoshkin / letsencrypt-certgen 。 该Docker映像提供了一个简单的单一入口点,用于从LetsEncrypt CA获取和管理SSL证书。 它封装了两个流行的ACME客户端: certbot和acme.sh ,它们分别用于获取RSA和/或ECDSA证书。 我们两者都需要,因为certbot无法发布ECDSA证书(更正确的是,只能通过自定义CSR颁发证书,但是您将失去续签,吊销和进一步管理此类证书的能力)。
这是为单个域foobbz.site
同时颁发ECDSA(prime256v1曲线)和RSA(2048)证书的foobbz.site
docker run \
-v /var/ssl:/var/ssl \
-p 80:80 \
-e DOMAINS=foobbz.site \
--rm \
asamoshkin/letsencrypt-certgen issue
要求是在服务器上运行此映像,该映像已针对要获取证书的域进行配置(DNS A记录指向该域)。 服务器的端口80应该由防火墙打开,以便LetsEncrypt CA服务器可以执行验证挑战。
完成后,证书,密钥和相关文件将存储在/var/ssl/$domain_common_name
路径中,该路径位于您之前装入容器的/var/ssl
卷中。
# tree /var/ssl
/var/ssl
└── foobbz.site
├── certs
│ ├── cert.ecc.pem
│ ├── cert.rsa.pem
│ ├── chain.ecc.pem
│ ├── chain.rsa.pem
│ ├── fullchain.ecc.pem
│ └── fullchain.rsa.pem
└── private
├── privkey.ecc.pem
└── privkey.rsa.pem
所有文件均以PEM格式编码:
-
cert.rsa.pem
,cert.ecc.pem
生成的证书(RSA或ECDSA) -
chain.[type].pem
中间CA证书链(例如,假LE中间X1) -
fullchain.[type].pem
与任何中间CA证书捆绑在一起的证书。 这适用于Nginx指令ssl_certificate
,该指令需要捆绑包,而不是叶证书。 -
privkey.[type].pem
私钥文件
您不仅限于单个域的单个证书。 您可以使用SAN(X.509主题备用名称扩展名)为多个域颁发多个证书,或为多个域颁发单个证书。 您可以选择仅使用自定义密钥长度或椭圆曲线生成ECDSA或RSA证书。
首先,准备一个包含域列表的文件。 每行代表要发行的单个证书。 每行中的名字是通用名称,而后面用逗号分隔的名称是证书替代名称(SAN)。
# cat /root/domains.txt
foobbz.site,www.foobbz.site,web.foobbz.site
foobbz2.site,www.foobbz.site
运行命令仅对foobbz.site
和foobbz2.site
域颁发两个ECDSA“ secp384r1”证书(无RSA证书):
docker run \
-v /var/ssl:/var/ssl \
-v /root/domains.txt:/etc/domains.txt \
-p 80:80 \
-e RSA_ENABLED=0 \
-e ECDSA_KEY_LENGTH=ec-384 \
-e DOMAINS=/etc/domains.txt \
--rm \
asamoshkin/letsencrypt-certgen issue
该映像的主要用例是触发一个命令来颁发证书,但是您也可以通过使用同一映像更新,吊销或删除它们来进一步管理证书。
您可以在构建时,在Nginx / Apache启动之前的运行时临时使用此映像,也可以在cron作业中运行该映像以定期更新证书。 这个想法是,LetsEncrypt的东西被封装在一个容器中,并且您不需要污染Nginx / Apache容器。
更完整的功能列表:
- 自动颁发和管理LetsEncrypt SSL证书
- 为1..N域生成DV证书,支持多域SAN(主题备用名称)证书
- 生成具有可配置密钥参数的RSA和/或ECDSA证书:RSA密钥长度(2048、3072、4096)和EC密钥的椭圆曲线(prime256v1,secp384r1)
- 选择DV质询验证方法:独立或webroot
- 在证书即将到期或强制续订时续订证书
- 通过联系LetsEncrypt CA吊销证书
- 使用LetsEncrypt临时服务器或生产服务器
有关更多详细信息和示例,请在Github上查看samoshkin / docker-letsencrypt-certgen 。 您也可以仅签出源代码以了解如何使用certbot和acme.sh客户端。
用于RSA / ECDSA混合设置的Nginx配置
生成证书后,就可以配置Web服务器了。 Nginx允许混合使用并行RSA和ECDSA证书,并将在TLS握手期间根据商定的密码套件为一个或另一个服务。
server {
listen 443 ssl default_server ;
server_name foobbz.site www.foobbz.site ;
# RSA certificates
ssl_certificate /var/ssl/foobbz.site/certs/fullchain.rsa.pem ;
ssl_certificate_key /var/ssl/foobbz.site/private/privkey.rsa.pem ;
# ECDSA certificates
ssl_certificate /var/ssl/foobbz.site/certs/fullchain.ecc.pem ;
ssl_certificate_key /var/ssl/foobbz.site/private/privkey.ecc.pem ;
# Other directives
}
另外,您还需要通过正确地排序密码套件(请注意,带有“ ECDSA”的套件首先出现,然后带有“ aRSA”的套件先行)来告诉Nginx首选ECDSA而不是RSA进行身份验证:
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:DHE+AESGCM:DHE:!RSA!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED";
就是这样,现在启动您的Nginx,让我们使用openssl作为TLS客户端并提取证书来测试我们的配置。 或者,您可以使用Qualys SSL Labs服务器测试来查看证书。
$ openssl s_client -host foobbz.site -port 443 -cipher ECDHE-ECDSA-AES128-GCM-SHA256 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' | openssl x509 -noout -text
查看公钥,我们可以确保提供ECDSA证书。
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:47:ee:86:9f:c9:5a:81:16:89:38:f7:5b:9d:ba:
6b:8b:d2:aa:8e:1e:54:67:f7:f1:44:84:5f:10:df:
7f:df:16:f4:2f:d6:c1:78:b8:71:68:e9:ee:78:82:
fc:2e:ae:96:e9:a3:b7:26:c0:ed:41:39:2a:48:f9:
0f:28:10:4e:15
ASN1 OID: prime256v1
NIST CURVE: P-256
请注意,叶子ECDSA证书仍由LetsEncrypt的RSA证书链(让我们的加密颁发机构X3,DST根CA X3)签名。 LetsEncrypt不使用专用的EC证书进行签名以构建完整的EC链。
0 s:/CN=foobbz.site
i:/C=US/O=Let’s Encrypt/CN=Let’s Encrypt Authority X3
1 s:/C=US/O=Let’s Encrypt/CN=Let’s Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
现在,让我们使用另一个密码套件(ECDHE-RSA-AES128-GCM-SHA256)测试RSA配置。
openssl s_client -host foobbz.site -port 443 -cipher ECDHE-RSA-AES128-GCM-SHA256 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' | openssl x509 -noout -text
我们得到2048位RSA公钥。 顺便说一下,请注意它们之间的长度差异。
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:ea:cb:5e:22:dd:93:fe:63:21:c4:bd:b9:07:78:
fc:ef:66:38:7a:19:bf:68:58:39:16:86:ee:f6:2c:
18:68:9c:32:c0:5b:a4:76:e8:e0:40:0e:6d:29:7c:
bc:04:67:b4:1b:05:e8:72:53:24:dc:4f:a6:3d:48:
41:2e:83:99:fa:13:20:88:b8:e5:5d:34:57:01:c6:
eb:fc:c1:67:e8:e4:ec:58:2c:a2:ce:51:ea:99:c0:
bb:de:61:8a:40:76:80:50:48:25:c6:7f:0e:a4:a6:
61:e7:25:67:b1:74:ee:1f:f1:75:e8:76:a0:c5:5d:
9c:40:48:8b:d3:95:e1:27:d2:d6:ca:14:e4:39:ac:
4d:0d:35:23:89:db:4b:ef:60:84:0b:4d:15:76:0e:
3c:f5:52:1c:20:ce:d8:03:25:22:7a:37:84:fb:d2:
1b:00:ff:31:69:55:65:7d:42:d1:31:99:0c:d6:29:
41:36:06:bf:0d:ab:31:1a:e6:b0:6a:76:67:2c:7b:
c0:5b:34:55:49:e2:4c:d9:e4:40:99:1c:c1:1d:6a:
88:c1:53:af:ee:ab:b5:2e:e6:76:ff:1c:33:e2:ca:
7e:d7:93:e6:23:df:cd:78:a6:39:f4:04:a2:44:d0:
a6:cc:f1:51:2f:5d:dc:5e:ea:ff:57:d7:f1:82:d4:
48:11
Exponent: 65537 (0x10001)
就是这样了。 感谢您阅读这篇文章。
编辑#1
Reddit用户wuunderbar指出 ,Docker容器没有足够的熵来生成密钥材料。 我知道的一种解决方案是将/dev/urandom
从主机安装到容器的/dev/random
中。 请参阅此StackOverflow答案 。
docker run -v /dev/urandom:/dev/random ...
资源资源
asamoshkin / letsencrypt-certgen — Docker集线器— https://hub.docker.com/r/asamoshkin/letsencrypt-certgen/
samoshkin / docker-letsencrypt-certgen:使用certbot和acme.sh客户端以自动方式从LetsEncrypt CA生成,续订,吊销RSA和/或ECDSA SSL证书— https://github.com/samoshkin/docker-letsencrypt-certgen
椭圆曲线密码术(ECC证书)| DigiCert.com — https://www.digicert.com/ecc.htm
ECC — https://support.globalsign.com/customer/portal/articles/1994347-ecc
ECC兼容性— https://support.globalsign.com/customer/portal/articles/1995283-ecc-compatibility
ECDSA:更好的互联网的数字签名算法— https://blog.cloudflare.com/ecdsa-the-digital-signature-algorithm-of-a-better-internet/
让我们加密-免费的SSL / TLS证书-https: //letsencrypt.org/
Certbot- https: //certbot.eff.org/
ZeroSSL:免费SSL- https ://zerossl.com/
Neilpang / acme.sh:实现ACME客户端协议的纯Unix shell脚本-https: //github.com/Neilpang/acme.sh
RSA和ECDSA性能| securitypitfalls — https://securitypitfalls.wordpress.com/2014/10/06/rsa-and-ecdsa-performance/
测试ECDSA证书— https://scotthelme.co.uk/ecdsa-certificates/
From: https://hackernoon.com/rsa-and-ecdsa-hybrid-nginx-setup-with-letsencrypt-certificates-ee422695d7d3