花了数小时阅读了如潮的好评,Bob最终迫不及待为他购买的托斯卡纳全脂牛奶点击了“进行结算”,然后……
哇!刚刚发生了什么?
在点击按钮过后的220毫秒时间内,发生了一系列有趣的事情,火狐浏览器(Firefox)不仅改变了地址栏颜色,而且在浏览器的右下角出现了一个小锁头的标志。在我最喜欢的互联网工具Wireshark的帮助下,我们可以通过一个经过略微调整的用于debug的火狐浏览器来探究这一过程。
根据RFC 2818标准(译者注:RFC 2818为HTTP Over TLS-网络协议),火狐浏览器自动通过连接Amazon.com的443端口来响应HTTPS请求。
很多人会把HTTPS和网景公司(Netscape)于上世纪九十年代中期创建的SSL(安全套接层)联系起来。事实上,随着时间的推移,这两者之间的关系也慢慢淡化。随着网景公司渐渐的失去市场份额,SSL的维护工作移交给了Internet工程任务组(IETF)。由网景公司发布的第一个版本被重新命名为TLS 1.0(安全传输层协议 1.0),并于1999年1月正式发布。考虑到TLS已经发布了将近10年,如今已经很难再见到真正的SSL通信了。
客户端问候(Client Hello)
TLS将全部的通信以不同方式包裹为“记录”(Records)。我们可以看到,从浏览器发出的第一个字节为0×16(十进制的22),它表示了这是一个“握手”记录。
接下来的两个字节是0×0301,它表示了这是一条版本为3.1的记录,同时也向我们表明了TLS1.0实际上是基于SSL3.1构建而来的。
整个握手记录被拆分为数条信息,其中第一条就是我们的客户端问候(Client Hello),即0×01。在客户端问候中,有几个需要着重注意的地方:
随机数:
在客户端问候中,有四个字节以Unix时间格式记录了客户端的协调世界时间(UTC)。协调世界时间是从1970年1月1日开始到当前时刻所经历的秒数。在这个例子中,0x4a2f07ca就是协调世界时间。在他后面有28字节的随机数,在后面的过程中我们会用到这个随机数。
SID(Session ID):
在这里,SID是一个空值(Null)。如果我们在几秒钟之前就登陆过了Amazon.com,我们有可能会恢复之前的会话,从而避免一个完整的握手过程。
密文族(Cipher Suites):
密文族是浏览器所支持的加密算法的清单。整个密文族是由推荐的加密算法“TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA”和33种其他加密算法所组成。别担心其他的加密算法会出现问题,我们一会儿就会发现Amazon也没有使用推荐的加密算法。
Server_name扩展:
通过这种方式,我们能够告诉Amazon.com:浏览器正在试图访问https://www.amazon.com。这确实方便了很多,因为我们的TLS握手时间发生在HTTP通信之前,而HTTP请求会包含一个“Host头”,从而使那些为了节约成本而将数百个网站域名解析到一个IP地址上的网络托管商能够分辨出一个网络请求对应的是哪个网站。传统意义上的SSL同样要求一个网站请求对应一个IP地址,但是Server_name扩展则允许服务器对浏览器的请求授予相对应的证书。如果没有其他的请求,Server_name扩展应该允许浏览器访问这个IPV4地址一周左右的时间。
服务器问候(Server Hello)
Amazon.com回复的握手记录由两个比较大的包组成(2551字节)。记录中包含了0×0301的版本信息,意味着Amazon同意我们使用TLS1.0访问的请求。这条记录包含了三条有趣的子信息:
1.服务器问候信息(Server Hello)(2):
我们得到了服务器的以Unix时间格式记录的UTC和28字节的随机数。
32字节的SID,在我们想要重新连接到Amazon.com的时候可以避免一整套握手过程。
在我们所提供的34个加密族中,Amazon挑选了“TLS_RSA_WITH_RC4_128_MD5”(0×0004)。这就意味着Amazon会使用RSA公钥加密算法来区分证书签名和交换密钥,通过RC4加密算法来加密数据,利用Md5来校验信息。我们之后会深入的研究这一部分内容。我个人认为,Amazon选择这一密码组是有其自身的原因的。在我们所提供的密码族中,这一加密组的加密方式是CPU占用最低的,这就允许Amazon的每台服务器接受更多的连接。当然了,也许还有一个原因是,Amazon是在向这三种加密算法的发明者Ron Rivest(罗恩·李·维斯特)致敬。
2.证书信息(11):
这段巨大的信息共有2464字节,其证书允许客户端在Amazon服务器上进行认证。这个证书其实并没有什么奇特之处,你能通过浏览器浏览它的大部分内容。
3.服务器问候结束信息(14):
这是一个零字节信息,用于告诉客户端整个“问候”过程已经结束,并且表明服务器不会再向客户端询问证书。
校验证书
此时,浏览器已经知道是否应该信任Amazon.com。在这个例子中,浏览器通过证书确认网站是否受信,它会检查 Amazon.com 的证书,并且确认当前的时间是在“最早时间”2008年8月26日之后,在“最晚时间”2009年8月27日之前。浏览器还会确认证书所携带的公共密钥已被授权用于交换密钥。
为什么我们要信任这个证书?
证书中所包含的签名是一串非常长的大端格式的数字:
任何人都可以向我们发送这些字节,但我们为什么要信任这个签名?为了解释这个问题,我们首先要回顾一些重要的数学知识:
RSA加密算法的基础介绍
人人常常会问,编程和数学之间有什么联系?证书就为数学在编程领域的应用提供了一个实际的例子。Amazon的服务器告诉我们需要使用RSA算法来校验证书签名。什么又是RSA算法呢?RSA算法是由麻省理工(MIT)的Ron Rivest、Adi Shamirh和Len Adleman(RSA命名各取了三人名字中的首字母)三人于上世纪70年代创建的。三位天才的学者结合了2000多年数学史上的精华,发明了这种简洁高效的算法:
选取两个较大的初值p和q,相乘得n;n = p*q 接下来选取一个较小的数作为加密指数e,d作为解密指数是e的倒数。在加密的过程中,n和e是公开信息,解密密钥d则是最高机密。至于p和q,你可以将他们公开,也可以作为机密保管。但是一定要记住,e和d是互为倒数的两个数。
假设你现在有一段信息M(转换成数字),将其加密只需要进行运算:C ≡ Me (mod n)
这个公式表示M的e次幂,mod n表示除以n取余数。当这段密文的接受者知道解密指数d的时候就可以将密文进行还原:Cd ≡ (Me)d ≡ Me*d ≡ M1 ≡ M (mod n)
有趣的是,解密指数d的持有者还可以将信息M进行用解密指数d进行加密:Md ≡ S (mod n)
加密者将S、M、e、n公开之后,任何人都可以获得这段信息的原文:Se ≡ (Md)e ≡ Md*e ≡ Me*d ≡ M1 ≡ M (mod n)
如同RSA的公共密钥加密算法经常被称之为非对称算法,因为加密密钥(在我们的例子中为e)和解密密钥(在我们的例子中是d)并不对称。取余运算的过程也不像我们平常接触的运算(诸如对数运算)那样简单。RSA加密算法的神奇之处在于你可以非常快速的进行数据的加密运算,即 ,但是如果没有解密密码d,你将很难破解出密码,即运算 将不可能实现。正如我们所看到的,通过对n进行因式分解而得到p和q,再推断出解密密钥d的过程难于上青天。
签名验证
在使用RSA加密算法的时候,最重要的一条就是要确保任何涉及到的数字都要足够复杂才能保证不被现有的计算方法所破解。这些数字要多复杂呢?Amazon.com的服务器是利用“VeriSign Class 3 Secure Server CA”来对证书