天天看点

密钥交换算法(常用)

密钥交换的握手过程中最引人入胜的部分。在TLS中,会话安全性取决于称为主密钥(masteer secret)的48字节共享密钥。密钥交换的目的是计算另一个值,即预主密钥(premaster secret)。这个值是组成主密钥的来源。

TLS支持许多密钥交换算法,能够支持各种证书类型、公钥算法和密钥生成协议。它们之中有一些在TLS协议主规格书中定义,但更多的则是在其他规格说明中定义。

常用的密钥交换算法

dh_anon                 Diffie-Hellman(DH)密钥交换,未经身份验证

dhe_rsa                   临时DH密钥交换,使用RSA身份验证

ecdh_anon             临时椭圆曲线DH(elliptic curve DH,ECDH)密钥交换,未经身份验证

ecdhe_rsa               临时ECDH密钥交换,使用RSA身份验证

ecdhe_ecdsa          临时ECDH密钥交换,使用ECDSA身份验证

krb5                        Kerberos密钥交换

rsa                           RSA密钥交换和身份验证

psk                          预共享密钥(pre-shared key,PSK)密钥交换和身份验证

dhe_psk                  临时DH密钥交换,使用PSK身份验证

rsa_psk                    PSK密钥交换,使用RSA身份验证

srp                           安全远程密码(secure remote password,SRP)密钥交换和身份验证

使用哪一种密钥交换由协商的套件所决定。一旦套件决定下来,两端都能了解按照哪种算法继续操作。实际使用的密钥交换算法主要有以下4种。

  • RSA

RSA是一种标准密钥交换算法,它得到了广泛的支持。但它受到一个问题的严重威胁:它的设计使被动攻击者可以解码所有加密数据,只要她能够访问服务器的私钥。因此RSA密钥交换正慢慢被其他支持前向保密(forward secrecy)的算法所替代。RSA密钥交换是一种密钥传输(key transport)算法,这种算法由客户端生成预主密钥,并以服务器公钥加密传送给服务器。

  • DHE_RSA

临时Diffie-Hellman(ephemeral Diffie-Hellman,DHE)密钥交换是一种构造完备的算法。它的优点是支持前向保密,缺点是执行缓慢。DHE是一种密钥协定算法,进行协商的团体都对密钥生成产生作用,并对公共密钥达成一致。在TLS中,DHE通常与RSA身份验证联合使用。

  • ECDHE_RSA和ECDHE_ECDSA

临时椭圆曲线Diffie-Hellman(ephemeral elliptic curve Diffie-Hellman,ECDHE)密钥交换建立在椭圆曲线加密的基础上。椭圆曲线算法是相对较新的算法。大家认可它执行很快而且提供了前向保密。但是只有较新的客户端才能较好的支持。ECDHE也是一种密钥协定算法,其理论原理与DHE类似。在TLS中,ECDHE可以与RSA或者ECDSA身份验证一起使用。

无论使用哪一种密钥交换,服务器都有机会发送ServerKeyExchange消息率先发话:

struct{
    select (KeyExchangeAlgorithm) {
    case dh_anon:
        ServerDHParams     params;
    case dhe_rsa:
        ServerDHParams     params:
        Signature          params_signature:
    case ecdh_anon:
        ServerECDHParams   params:
    case ecdhe_rsa:
    case ecdhe_ecdsa:
        ServerECDHParams   params;
        Signature          params_signature;
    case rsa:
    case dh_rsa:
        /* 无消息 */
      };
} ServerKeyExchange;      

在上面的消息定义中发现,在某些算法内,服务器不发送任何信息。原因是在这些情况下,所有需要的信息已经通过其他消息得到;不然,服务器就会在此发送其密钥交换的参数。关键的是,服务器也会发送参数的签名用于身份验证。使用签名,客户端得以确认它正在与持有私钥对应证书中的公钥的团体进行通信。

客户端发送ClientKeyExchange消息传送它的密钥交换参数,这个消息总是必须的:

struct{
    select (KeyExchangeAlgorithm) {
    case rsa:
        EncryptedPreMasterSecret;
    case dhe_dss:
    case dhe_rsa:
    case dh_dss:
    case dh_rsa:
    case dh_anon:
        ClientDiffieHellmanPublic;
    case ecdhe:
        ClientECDiffieHellmanPublic;
      } exchange_Keys;
} ClientKeyExchange;      

RSA密钥交换

RSA密钥交换的过程十分直截了当。客户端生成预主密钥(46字节随机数),使用服务器公钥对其加密,将其包含在ClientKeyExchange消息中,最后发送出去。服务器只需要解密这条消息就能取出预主密钥。TLS使用的是RFC 3447定义的RSAES-PKCS1-v1_5加密方案。

因为RSA算法可以同时用于加密和数字签名,所以RSA密钥交换可以按照这种方式工作。其他流行的密钥类型,比如DSA(DSS)和ECDSA,只能用于签名。

RSA密钥交换的简单性也是它最大的弱点。用于加密预主密钥的服务器公钥,一般会保持多年不变。任何能够接触到对应私钥的人都可以恢复预主密钥,并构建相同的主密钥,从而危害到会话安全性。

对目标的攻击并不需要实时进行,强大的对手可以制定长期行动。攻击者会记录所有的加密的流量,耐心等待有朝一日可以得到密钥。比如计算机能力的进步使暴力破解成为可能;也可以通过法律强制力、政治高压、贿赂或强行进入使用该密钥的服务器来取得密钥。只要密钥泄露,就可以解密之前记录的所有流量了。

TLS中其他常见的密钥交换方式都不受这个问题的影响,被称为支持前向保密。使用那些密钥交换时,每个连接使用的主密钥互相独立。泄露的服务器密钥可以用于冒充服务器,但不能用于追溯任何流量。

Diffie-Hellmac密钥交换

Diffie-Hellman(DH)密钥交换时一种密钥协定的协议,它使两个团体在不安全的信道上生成共享密钥成为可能。

以这种方式协商共享密钥时不会受到被动攻击的威胁,但主动攻击者却可以劫持通信信道,冒充对端。这就是DH密钥交换通常与身份验证联合使用的原因。

抛开算法的细节,DH的诀窍是用了一种正向计算简单、逆向计算困难的数学函数,即使交换中某些因子已被知晓,情况也是一样。最恰当的类比示例是混色:如果有两种颜色,那么很容易将其混在一起得到第三种颜色;但是如果只有第三种颜色的话,就很难确定究竟它是由哪两种颜色混合而成的。

DH密钥交换需要6个参数:其中两个(dh_p和dh_g)称为域参数,由服务器选取。协商过程中,客户端和服务器各自生成另外两个参数,相互发送其中一个参数(dh_Ys和dh_Yc)到对端,再经过计算,最终得到共享密钥。

临时Diffie-Hellman(ephemeral Diffie-Hellman,DHE)密钥交换中没有任何参数被重复使用。与之相对,在一些DH密钥交换方式中,某些参数是静态的,并被嵌入到服务器和客户端的证书中。这样的话,密钥交换的结果是一直不变的共享密钥,就无法具备前向保密的能力。

TLS支持静态DH密钥交换,但无人使用。在协商DHE套件时,服务器将其所有参数填入ServerDHParams块并发送:

struct{
    opaque dh_p;
    opaque dh_g;
    opaque dh_Ys;
} ServerDHParams;      

客户端响应并发送其公开参数(dh_Yc):

struct{
    select (PublicValueEncoding) {
    case implicit:
        /* 空的,当客户端公共参数嵌入其客户端时 */
    case explicit:
        opaque dh_Yc;
      } dh_public;
} ClientDiffieHellmanPublic;      

当前使用的DH交换存在以下这些现实问题。

  • DH参数的安全性

DH密钥交换的安全性取决于域参数的质量。服务器发送弱的或者不安全啊的参数,将对会话的安全性造成损害。弱DH参数被用作一种攻击向量。

  • DH参数协商

TLS并没有为客户端提供传递期望使用的DH参数的强度的设施。比如,客户端可能希望避免使用弱参数,抑或可能不支持强参数。因此,选择DHE套件的服务器事实上只能期待DH参数可以被客户端接受。

  • 参数强度不够

以历史角度来说,DH参数很大程度上被忽略了,其安全性也被忽视了。许多库和服务器默认使用弱DH参数,而且经常不提供配置DH参数强度的方法。因此,服务器使用1024位弱参数、768位非安全参数、更有甚至使用512位参数,这些情况都很常见。知道最近,一些平台才开始使用2048位或者更高位数的强参数。

2015年5月披露的Logjam攻击表明,512位的DH参数在使用合适资源的情况下可以被攻击者在很短的时间内成功利用,同时可以估计伤害的攻击者可能利用768位的参数。同样的研究还强调非常厉害的攻击者甚至有可能可以攻破那些被广泛使用的、长度位1024位的标准参数组,从而以被动方式入侵数以百万计的互联网服务器。

这些问题通过对不同强度的域参数定义来进行标准化,或者扩展TLS允许客户端告知其偏好的方法来解决。

椭圆曲线Diffie-Hellman密钥交换

临时椭圆曲线Diffie-Hellman(elliptic curve Diffie-Hellman,ECDH)密钥交换原理与DH相似,但它的核心使用了不同的数学基础。正如名称所示,ECDHE基于椭圆曲线(elliptic curve

,EC)加密。

ECDH密钥交换发生在一条由服务器定义的特定的椭圆曲线上。这条曲线代替了DH中域参数的角色。理论上,ECDH支持静态的密钥交换,但实际使用时,只使用了这种临时的变种(ECDHE)。

密钥交换由服务器发起,它选择一条椭圆曲线和公开参数(EC point)并提交:

struct{
    ECParameters curve_params;
    ECPoint public;
} ServerDHParams;      

服务器可以为密钥交换明确指定一条曲线,但TLS并未使用这个功能。作为替代,在TLS中,服务器通过指定某个名称引用一条可能预先定义好参数的曲线(命名曲线,named curve):

struct{
    ECCurveType curve_type;
    select (curve_type) {
    case eexplicit_prime:
        /* 省略 */
    case explicit_char2:
        /* 省略 */
    case named_curve:
        NamedCurve nnamedcurve:
      };
} ECParameters;      
struct{
    select (PublicValueEncoding) {
    case implicit:
        /* 空的 */
    case explicit:
        ECPoint ecdh_Yc;
     } ecdh_public;
} ClientECDiffieHellmanPublic;      

继续阅读