本文是关于SSL/TLS的 CipherSuite 的信息摘录,翻译。如有疑问,欢迎指出。
CipherSuite 这个名词目前没看到有好的中文翻译,个人觉得翻译成“加密算法套件”比较合适。Cipher泛指是密码学的加密算法,例如 aes, rsa, ecdh 等。 tls是由各类基础算法,作为原语组合而成。 一个CipherSuite是4个算法的组合:
TLS Cipher Suite 在 iana 集中注册,每一个CipherSuite分配有 一个2字节的数字用来标识 : 可以在 iana的网页查看: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 0x00,0x2F TLS_RSA_WITH_AES_128_CBC_SHA Y [RFC5246] 0x00,0x30 TLS_DH_DSS_WITH_AES_128_CBC_SHA Y [RFC5246] 0x00,0x31 TLS_DH_RSA_WITH_AES_128_CBC_SHA Y [RFC5246] 0x00,0x32 TLS_DHE_DSS_WITH_AES_128_CBC_SHA Y [RFC5246] 0x00,0x33 TLS_DHE_RSA_WITH_AES_128_CBC_SHA Y [RFC5246] 0x00,0x34 TLS_DH_anon_WITH_AES_128_CBC_SHA Y [RFC5246] 0x00,0x35 TLS_RSA_WITH_AES_256_CBC_SHA Y [RFC5246] 0x00,0x36 TLS_DH_DSS_WITH_AES_256_CBC_SHA Y [RFC5246] 0x00,0x37 TLS_DH_RSA_WITH_AES_256_CBC_SHA Y [RFC5246] 0x00,0x38 TLS_DHE_DSS_WITH_AES_256_CBC_SHA Y [RFC5246] 0x00,0x39 TLS_DHE_RSA_WITH_AES_256_CBC_SHA Y [RFC5246] 0x00,0x3A TLS_DH_anon_WITH_AES_256_CBC_SHA Y [RFC5246] 0x00,0x3B TLS_RSA_WITH_NULL_SHA256 Y [RFC5246] 0x00,0x3C TLS_RSA_WITH_AES_128_CBC_SHA256 Y [RFC5246] 0x00,0x3D TLS_RSA_WITH_AES_256_CBC_SHA256 Y [RFC5246] 0x00,0x3E TLS_DH_DSS_WITH_AES_128_CBC_SHA256 Y [RFC5246] 0x00,0x3F TLS_DH_RSA_WITH_AES_128_CBC_SHA256 Y [RFC5246] |
---|
例如其中的:
1 | 0x00,0x37 TLS_DH_RSA_WITH_AES_256_CBC_SHA Y [RFC5246] |
---|
这一条, 0x00,0x37 这个 value 就是 TLS_DH_RSA_WITH_AES_256_CBC_SHA 这个 Cipher Suite的数字,rfc5246 定义了这个CipherSuite的具体实现。
tls/ssl 一共出过 5个版本:ssl2/ssl3/tls1.0/tls1.1/tls1.2 ,ssl2/ssl3这两个版本漏洞太多,请务必禁用。
tls1.2,当前(2015年)最新的tls协议,定义在:rfc5246
tls协议的实现有多种,如openssl, gnutls, nss, libressl, cyassl, polarssl, botan等等。
openssl的代码算是其中最混乱的,但是也是最久经考验的。 ( 请参见此打脸文: http://blog.csdn.net/dog250/article/details/24552307 )
个人觉得polarssl和botan的架构最清晰,代码风格清新可爱,便于学习理解协议(但是不建议在生产环境下用,例如polarssl功能尚有欠缺)。
说说openssl,openssl 实现了以上列表中的大部分( 摒弃了不安全的一些CipherSuite)。
openssl 支持的 cipher 列表,可以用 openssl ciphers -V | column -t 命令查看 输出如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 0xC0,0x30 - ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD 0xC0,0x2C - ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD 0xC0,0x28 - ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 0xC0,0x24 - ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 0xC0,0x14 - ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 0xC0,0x0A - ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1 0x00,0xA5 - DH-DSS-AES256-GCM-SHA384 TLSv1.2 Kx=DH/DSS Au=DH Enc=AESGCM(256) Mac=AEAD 0x00,0xA1 - DH-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH/RSA Au=DH Enc=AESGCM(256) Mac=AEAD 0x00,0x9F - DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD 0x00,0x6B - DHE-RSA-AES256-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(256) Mac=SHA256 0x00,0x69 - DH-RSA-AES256-SHA256 TLSv1.2 Kx=DH/RSA Au=DH Enc=AES(256) Mac=SHA256 0x00,0x68 - DH-DSS-AES256-SHA256 TLSv1.2 Kx=DH/DSS Au=DH Enc=AES(256) Mac=SHA256 0x00,0x39 - DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1 0x00,0x37 - DH-RSA-AES256-SHA SSLv3 Kx=DH/RSA Au=DH Enc=AES(256) Mac=SHA1 |
---|
每一行里:
例如:
1 | 0xC0,0x23 - ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256 |
---|
这一行,表示:
一个CipherSuite,在 openssl 库里用这个结构体表示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* used to hold info on the particular ciphers used */ struct ssl_cipher_st { int valid; const char *name; /* text name */ unsigned long id; /* id, 4 bytes, first is version */ /* * changed in 0.9.9: these four used to be portions of a single value * 'algorithms' */ unsigned long algorithm_mkey; /* key exchange algorithm */ unsigned long algorithm_auth; /* server authentication */ unsigned long algorithm_enc; /* symmetric encryption */ unsigned long algorithm_mac; /* symmetric authentication */ unsigned long algorithm_ssl; /* (major) protocol version */ unsigned long algo_strength; /* strength and export flags */ unsigned long algorithm2; /* Extra flags */ int strength_bits; /* Number of bits really used */ int alg_bits; /* Number of bits for algorithm */ }; |
---|
以上4个算法,对应其中的下面四行:
1 2 3 4 | unsigned long algorithm_mkey; /* key exchange algorithm */ unsigned long algorithm_auth; /* server authentication */ unsigned long algorithm_enc; /* symmetric encryption */ unsigned long algorithm_mac; /* symmetric authentication */ |
---|
在浏览器里面,可以这样查看当前使用的CipherSuite: Firefox下打开gmail,点击地址栏左侧锁图标
在tls中,选择CipherSuite的方法是通过cipher list
格式和用法见:https://www.openssl.org/docs/apps/ciphers.html
nginx里面的配置项是 cipher_list
cipher list 的格式是:
一个cipher list 包含一个或者多个由冒号分隔的cipher string( 逗号和空格也可以接受但不常用)。
一个cipher string可以是下列形式之一:
(1).可以由单个cipher suite构成,例如 RC4-SHA。
(2).它可以表示含有某个特定算法的cipher列表,或者一种特定类型的cipher suite。例如, SHA1表示所有使用摘要算法SHA1的cipher suite, SSLV3表示所有SSL V3算法。
(3).cipher suite的列表,可以使用加号+ 合并到一个单一的cipher string里面。这被作为一个逻辑且操作。例如,SHA1+DES表示所有包含了 SHA,并且包含了DES的算法。
(4).每一个cipher string可以在前面加上字符 !,-,或者+
如果加了!,那么这种cipher永久从列表里面删除,就算后边显式添加进来也不行。
如果加了-,那么cipher中的一些或者全部可以在后面的选项里面加回来。
如果加了+,那么cipher被移动到列表的最后,这个选项不增加任何cipher,只是把匹配的cipher移动到最后。
如果没有上述字符,那么字符串被解析成一个cipher list,追加到当前配置列表的后面。如果cipher list 中的某些cipher已经存在了,就忽略该cipher。
(5).另外,cipher string @STRENGTH 可以用在任何点,用来把当前cipher list按照加密算法key长度排序。
当前建议的配置参数可以看看mozilla的这个文档:https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations
随着密码学的发展,硬件性能的提高,加密和破解的不断对抗博弈,常用的算法也在不断进化,旧的算法被破解,新的算法诞生。
CipherSuite的当前流行趋势:
authentication (认证)算法 :常见的有 RSA/DSA/ECDSA 3种,目前最主流的是人民群众喜闻乐见,妇孺皆知的RSA ( 2048 bit及以上), (ECDSA 是新兴趋势,例如gmail,facebook都在迁移到ECDSA,当然目前用的还不多,DSA 由于只能提供1024bit,已经没啥人敢用)。
加密算法:主流趋势是使用 aes,128/256 bit都可以,加密模式的趋势是使用gcm,cbc由于被发现有 BEAST 攻击等,比较难以正确使用,至于ecb模式,请勿使用。加密算法 还有RC4(不建议使用),3DES(不建议使用),Camellia(貌似日本人搞的) ,DES(已经被淘汰)等,
message authentication code (消息认证码 简称MAC)算法 ,主流有 sha256,sha384,sha1,等。tls中使用了HMAC模式,而不是原始的 sha256,sha1等。google已经在淘汰MD5了。(gcm是一种特殊的称为aead的加密模式,不需要配合MAC。)
key exchange(密钥交换)算法:主流有两种:DH和ECDH,自从斯诺登爆料了NSA的https破解方案以后,现在的 key exchange(密钥交换)算法,普遍流行 PFS,把DH, ECDH变成 DHE,ECDHE 。
mozilla目前推荐的 cipher list:
1 | ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK |
---|
mozilla的优先级选择考虑:
1.ECDHE+AESGCM最先选,目前没有已知漏洞。
2.PFS ciphersuite优先,其中ECDHE优先于DHE
3.SHA256优先于SHA1。完全禁用MD5。
4.AES 128优先于AES 256。这个问题有一些讨论。
5.在向后兼容模式中,AES优先于3DES。
6.完全禁止RC4。3DES只用于兼容老版本。
cloudflare的ssl cipher list配置:
https://github.com/cloudflare/sslconfig/blob/master/conf
google的一篇文章解释当前cipher suite的流行趋势 http://googleonlinesecurity.blogspot.com.au/2013/11/a-roster-of-tls-cipher-suites-weaknesses.html
google在密码学方面的最新进展可以在这个博客追踪:http://googleonlinesecurity.blogspot.com/