密码技术简介(三)
Contents
SSL/TLS
使用 SSL/TLS 可以对通信对象进行认证,还可以确保通信内容的机密性。
严格来说,SSL(Secure Socket Layer)和 TLS(Transport Layer Security)是不同的,TLS 相当于 SSL 的后续版本。
SSL 是网景公司于 1994 年设计的协议,并在该公司的 Web 浏览器 Netscape Navigator 中进行了实现,随后很多 Web 浏览器都采用该协议,使其成为了事实上的行业标准。SSL 于 1995 年发布 3.0 版本,2014 年,SSL 3.0 协议被发现存在可能导致 POODLE 攻击的安全漏洞(CVE-2014-3566),因此 SSL 3.0 已不再安全。 TLS 是 IETF 在 SSL 3.0 的基础上设计的协议,1999 年作为 RFC 2246 发布的 TLS 1.0,实际上相当于 SSL 3.1。2006 年,TLS 1.1以 RFC 4346 的形式发布,增加了针对 CBC攻 击的对策,加入了 AES 对称密码算法。TLS 1.2 中新增了对 GCM、CCM 认证加密的支持,还新增了 HMAC-SHA256,并删除了 IDEA 和 DES,将伪随机函数改为基于 SHA-256 来实现。
用 SSL 或 TLS 作为对通信进行加密的协议,在此之上承载 HTTP,两种协议的叠加,就可以实现对 HTTP 通信(请求和响应)的加密,防止窃听。
通过网站传递信用卡号等私密信息需要解决的问题:
- 传递过程中不被窃听(机密性)
- 可以用对称密码,用伪随机数生成器生成密钥,密钥配送用公钥密码或者 Diffie-Hellman 密钥交换。
- 传递过程中不被篡改(完整性,或者叫数据认证)
- 使用消息认证码。
- 确认通信对方的 Web 服务器是真正的通信对象(对象认证)
- 使用证书。
SSL/TLS 就是将上述所需要的工具组合起来的框架。
SSL/TLS 也可以保护其它协议,如发送邮件时使用的 SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)和接收邮件时使用的POP3(Post Office Protocol,邮局协议)。
SSL/TLS 中使用的对称密码、公钥密码、数字签名、单向散列函数等技术,都是可以像插件一样进行替换。
实际进行对话的客户端和服务器必须使用相同的密码技术才能进行通信,因此如果选择过于自由,就难以确保整体的兼容性。为此 SSL/TLS 规定了一些密码技术的推荐组合,称为密码套件(cipher suite)。
使用 TLS 进行通信
TLS 协议由 TLS 记录协议(TLS record protocol)和 TLS 握手协议(TLS handshake protocol)两层协议叠加而成。
位于底层的 TLS 记录协议负责使用对称密码对消息进行加密。TLS 记录协议中使用了对称密码和消息认证码,具体的算法和共享密钥通过握手协议在服务器和客户端之间协商决定。
TLS 记录协议负责消息的压缩、加密以及数据的认证:
- 消息被分割成多个较短的片段(fragment),然后分别对每个片段进行压缩。压缩算法需要与通信对象协商决定。
- 经过压缩的片段会被加上消息认证码。用于识别出篡改。与此同时,为了防止重放攻击,在计算消息认证码时,还附上了片段的编号。单向散列函数的算法以及消息认证码所使用的共享密钥都需要与通信对象协商决定。
- 经过压缩的片段再加上消息认证码会一起通过对称密码进行加密。加密使用 CBC 模式,CBC 模式的初始化向量(IV)通过主密码(master secret)生成。对称密码的算法以及共享密钥需要与通信对象协商决定。
- 加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头(header)就是最终的报文数据。数据类型为 TLS 记录协议所承载的 4 个子协议中的一个。
位于上层的 TLS 握手协议负责除加密以外的其他操作,具体是生成共享密钥以及交换证书。“握手”是服务器和客户端在进行加密通信前交换必要信息的过程。
由于握手协议中的信息交换是在没有加密(明文)的情况下进行的,这一协议中所收发的所有数据都可能被窃听者窃昕,因此在这一过程中必须使用公钥密码或者 Diffie-Hellman 密钥交换。
握手协议又分为 4 个子协议:
- 握手协议
- 负责在客户端和服务器之间协商决定密码算法和共享密钥;基于证书的认证操作也在此完成。
- 服务器和客户端之间通过握手协议协商一致之后,就会相互发出信号来切换密码,负责发出信号的就是密码规格变更协议。
- 密码规格变更协议(change cipher spec protocol)
- 用于密码切换的同步,负责向通信对象传达变更密码规格的信号。
- 加密通信开始之后,客户端和服务器也可以通过重新握手来再次改变密码套件。
- 当过程中发生错误时,会通过警告协议传达给对方。
- 警告协议(alert protocol)
- 负责在发生错误时将错误传达给对方。当握手协议的过程中出现异常,或者发生消息认证码错误、压缩数据无法解压缩等问题时,会使用此协议。
- 如果没有发生错误,则会使用应用数据协议进行通信。
- 应用数据协议
- 将 TLS 上承载的应用数据传达给通信对象。
握手协议示例:
- 客户端 ClientHello 消息:“我能够理解的密码套件有 RSA/3DES 或 DSS/AES,请问我们使用哪种套件来通信?”
- 消息内容:可用 TLS 版本号,当前时间,客户端$$随机数_{1}$$,会话 ID,可用密码套件清单,可用压缩方式清单。
- 当前时间在基本的 TLS 中不会用到,上层协议中可能会用到。
- 当前客户端和服务器需要重新使用之前的会话时需要使用会话 ID。
- 消息内容:可用 TLS 版本号,当前时间,客户端$$随机数_{1}$$,会话 ID,可用密码套件清单,可用压缩方式清单。
- 服务器 ServerHello 消息:“我们用 RSA/3DES 通信吧。”
- 消息内容:使用的 TLS 版本号,当前时间,服务器$$随机数_{2}$$(用于生成“会话密钥”),会话 ID,使用的密码套件,使用的压缩方式。
- 服务器随机数必须与客户端随机数无关。
- 消息内容:使用的 TLS 版本号,当前时间,服务器$$随机数_{2}$$(用于生成“会话密钥”),会话 ID,使用的密码套件,使用的压缩方式。
- 服务器 Certificate 消息:“这是我的证书。”
- 服务器将证书清单发送给客户端。证书清单是一组 X.509v3 证书,首先发送的是服务器(发送方)的证书,然后会按顺序发送对服务器证书签名的认证机构的证书。客户端会对服务器发送过来的证书进行验证。
-
如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。
-
- 当以匿名方式通信时,不发送证书清单。
- 服务器将证书清单发送给客户端。证书清单是一组 X.509v3 证书,首先发送的是服务器(发送方)的证书,然后会按顺序发送对服务器证书签名的认证机构的证书。客户端会对服务器发送过来的证书进行验证。
- 服务器 ServerKeyExchange 消息:“我们用这些信息来进行密钥交换吧。”
- 当 Certificate 消息不足以满足需求时,服务器会通过 ServerKeyExchange 消息向客户端发送一些必要信息,具体发送的信息内容会根据所使用的密码套件而有所不同。
- 当 Certificate 消息足以满足需求时,不会发送 ServerKeyExchange 消息。
- 服务器 CertificateRequest 消息:“对了,请给我看一下你的证书吧。”
- 用于服务器向客户端请求证书以进行客户端认证。
- 消息内容:服务器能够理解的证书类型清单,服务器能够理解的认证机构名称清单。
- 当不使用客户端认证时,不会发送 CertificateRequest 消息。
- 服务器 ServerHelloDone 消息:“问候到此结束。”
- 表示从 ServerHello 开始的一系列消息的结束。
- 客户端 Certificate 消息:“这是我的证书。”
- 收到步骤 5 的 CertificateRequest 消息后,客户端会将自己的证书同 Certificate 消息一起发送给服务器。服务器读取客启端的证书并进行验证。
-
金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供 USB 密钥,里面就包含了一张客户端证书。
-
- 当服务器没有发送 CertificateRequest 消息时,客户端不会发送 Certificate 消息。
- 收到步骤 5 的 CertificateRequest 消息后,客户端会将自己的证书同 Certificate 消息一起发送给服务器。服务器读取客启端的证书并进行验证。
- 客户端 ClientKeyExchange 消息:“这是经过加密的预备主密码。”
- 预备主密码(pre-master secret)是由客户端生成的$$随机数_{3}$$,之后会被用作生成主密码的种子,这个值会在使用服务器的公钥进行加密后发送给服务器。
- 当密码套件中包含 RSA 时,会随 ClientKeyExchange 消息一起发送经过加密的预备主密码;当密码套件中包含 Diffie-Hellman 密钥交换时,会随 ClientKeyExchange 消息一起发送 Diffie-Hellman 的公开值。
- 根据预备主密码和之前交换的两个随机数,服务器和客户端会计算出相同的主密码,然后再根据主密码生成密钥素材:对称密码密钥(会话密钥),消息认证码的密钥,对称密码 CBC 模式中使用的初始化向量 IV。
- 主密码是 TLS 客户端和服务器之间协商出来的一个秘密的数值,TLS 密码通信的机密性和数据的认证全部依靠此数值。
- 主密码是一个 48 字节(384 比特)的数值,客户端和服务器根据预备主密码、客户端随机数、服务器随机数计算主密码。客户端随机数和服务器随机数的作用相当于防止攻击者事先计算出密钥的盐。
- 过程中需要使用基于密码套件中定义的单项散列函数实现的伪随机函数,用于生成预备主密码、初始化向量、根据主密码生成密钥。
- 预备主密码(pre-master secret)是由客户端生成的$$随机数_{3}$$,之后会被用作生成主密码的种子,这个值会在使用服务器的公钥进行加密后发送给服务器。
- 客户端 CertificateVerify 消息:“我确实是客户端证书的持有者本人。”
- 目的是向服务器证明自己的确持有客户端证书的私钥。客户端会计算“主密码”和“握手协议中传送的消息”的散列值,并加上自己的数字签名后发送给服务器。
- 客户端只有在服务器发送 CertificateRequest 消息时才会发送 CertificateVerify 消息。
- 客户端 ChangeCipherSpec 消息:“好,现在我要切换密码了。”
- ChangeCipherSpec 消息并不是握手协议的消息,而是密码规格变更协议的消息。在 ChangeCipherSpec 消息之前,客户端和服务器之间已经交换了所有关于密码套件的信息,因此在收到这一消息时,客户端和服务器会同时切换密码。
- 客户端 Finished 消息:“握手协议到此结束。”
- 由于已经完成了密码切换,因此 Finished 消息是使用切换后的密码套件来发送的。
- 实际负责加密操作的是 TLS 记录协议。
- Finished 消息的内容是固定的,因此服务器可以将收到的密文解密来确认所收到的 Finished 消息是否正确,这样就可以确认握手协议是否正常结束、密码套件的切换是否正确。
- 服务器 ChangeCipherSpec 消息:“好,现在我要切换密码了。”
- 服务器 Finished 消息:“握手协议到此结束。”
- 切换至应用数据协议进行加密通信。
握手协议完成了下列操作:
- 客户端获得了服务器的合法公钥,完成了服务器认证
- 服务器获得了客户端的合法公钥,完成了客户端认证(当需要客户端认证时)
- 客户端和服务器生成了加密通信中使用的共享密钥
- 客户端和服务器生成了消息认证码中的使用共享密钥
主密码是 TLS 客户端和服务器之间协商出来的一个秘密数值,TLS 密码通信的机密性和数据的认证全部依靠这个数值。
握手阶段全部结束后,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过会用"会话密钥"加密内容。
每一次会话(session,想想 sessionStorage),客户端和服务器端都生成一个"会话密钥"(session key),用它来加密信息。由于"会话密钥"是对称加密,所以运算速度非常快,而服务器公钥只用于加密"会话密钥"本身,这样就减少了加密运算的消耗时间。
对 SSL/TLS 的攻击
针对 SSL/TLS 中使用的各个密码技术的攻击,会直接成为对 SSL/TLS 的攻击。
SSL/TLS 作为框架不依赖于某种特定的密码技术,当发现某种具体的密码技术存在弱点时,只需更换成其它方案即可。
2014 年发现的心脏出血(HeartBleed)漏洞,并不是 SSL/TLS 协议本身的漏洞,而是 OpenSSL 这一实现上的漏洞。由于 OpenSSL 在 TLS 心跳扩展功能中对于请求的数据大小没有进行检查,从而导致误将内存中与该请求无关的信息返回给请求者,攻击者通过访问使用了包含该漏洞的 OpenSSL 的服务器,就可以在一定范围内窃取服务器上的信息。
SSL 3.0 中对 CBC 模式加密时的分组填充操作没有进行严格的规定,而且填充数据的完整性没有受到消息认证码的保护,POODLE 攻击正是利用了这一漏洞来窃取秘密信息的。POODLE 攻击的本质就是对 CBC 模式的填充提示攻击,更严重的问题是,在某些条件下,攻击者可以将通信协议的版本从 TLS 强制降级到 SSL 3.0。要有效抵御 POODLE攻击, 必须禁用 SSL 3.0。
FREAK 是 FactoringRSA Export Keys(出口级 RSA 密钥质因数分解)的缩写,其攻击方法是强制 SSL/TLS 服务器使用一种名为 RSA Export Suites 的强度较低的密码套件。要实现 FREA K攻击,除了需要 SSL/TLS 服务器具有该漏洞,同时还需要用户的 Web 浏览器(HTTP 客户端)接受使用 RSA Export Suites 来进行通信。
FREAK 攻击也是一种中间人攻击,当浏览器与 Web 服务器协商 SSL/TLS 的密码套件时(此时的通信内容还没有被加密),攻击者介入其中,强制双方使用 RSA Export Suites。如果浏览器和 Web 服务器双方都具备该漏洞,那么它们便会按照攻击者的指示开始使用 RSA Export Suites 进行通信。通常情况下,在密码套件确定之后,双方的通信就开始加密,这时攻击者原本应该无法窃听其中的内容,然而由于 RSA Export Suites 的强度非常低,攻击者可以暴力破解共享密钥,从而能够对本应安全传输的数据进行解密。
美国曾经将密码算法和软件作为武器来看待,因此历史上一度禁止将“高强度密码软件”出口到国外(密码产品出口管制),直到 20 世纪 90 年代后半期这一政策才有所缓和。RSA Export Suites 就是一种配合当时的环境而故意弱化的密码套件。RSA Export Suites 中使用了 512 比特的 RSA 和 40 比特的 DES,这一组合在当时还勉强够用,到了现在绝不应该再使用了。目前全世界还有很多 Web 服务器允许使用 RSA Export Suites,OpenSSL 等 SSL/TLS 工具包在实现上也没有禁用 RSA Export Suites,使得 FREAK 攻击成为了可能。
对伪随机数生成器的攻击:1995 年发现的 Netscape Navigator 浏览器的一个 bug 存在于伪随机数生成器中,SSL 中使用的伪随机数生成器的种子都在时间和进程编号等可预测的范围内,因此所得到的密钥范围实际上非常小。
利用证书的时间差进行攻击:SSL/TLS 中,客户端会使用服务器证书对服务器进行认证。在此过程中,客户端需要使用合法认证机构的公钥对证书所附带的数字签名进行验证,验证证书需要使用最新的 CRL,而 Web 浏览器如果没有获取最新的 CRL,即便使用 SSL/TLS 也无法保证通信的安全。
区块链(比特币)
一个区块由若干条交易和一个区块头组成。
区块头保存了上一个区块的区块头的散列值;保存了本区块所有交易的整体散列值;保存了 nonce
、时间戳等信息。
比特币中使用的数字签名算法为椭圆曲线 DSA,其中使用的椭圆曲线方程是 $$x^3$$ = $$y^3$$ + 7。
要向区块链添加新区块,矿工需要生成合法的区块头,区块头的前面若干比特必须是 0。
previousBlockHeaderHash = Hash(previousBlockHead + nonce)
previousBlockHeaderHash
存于当前的区块头中。
Diffie-Hellman Key Exchange (Agreement)
通信双方仅交换一些可以公开的信息,通过计算生成处一个相同的共享密钥。
有限域的离散对数问题的复杂度是支撑 Diffie-Hellman 密钥交换算法的基础。
非椭圆曲线的 Diffie-Hellman 密钥交换利用的是以 p 为模,已知 G 和 $$G^x$$ mod p 求 x 的复杂度(有限域上的离散对数问题);椭圆曲线 Diffie-Hellman 密钥交换利用 的是在椭圆曲线上,已知 G 和 xG 求 x 的复杂度(椭圆曲线上的离散对数问题)。
References