HTTPS究竟是个啥玩意儿?

  • 时间:2018-11-26 23:20 作者:简单的老王 来源:简单的老王 阅读:1619
  • 扫一扫,手机访问
摘要:我们现在经常听说谁谁谁密码被盗了,谁谁谁信息又被劫持了。其中有一个起因:绝大部分网站用的是http这个明文协议。你以为很安全的在password框里填了隐藏的密码,他却一字一句明明白白的写到了网络上。于是乎好多网站开始从http迁移到https(至少登录部分)。我也准备做同样的事情,因而抽时间和小伙

我们现在经常听说谁谁谁密码被盗了,谁谁谁信息又被劫持了。其中有一个起因:绝大部分网站用的是http这个明文协议。你以为很安全的在password框里填了隐藏的密码,他却一字一句明明白白的写到了网络上。于是乎好多网站开始从http迁移到https(至少登录部分)。我也准备做同样的事情,因而抽时间和小伙伴tt一起研究了一下https。

HTTPS究竟是个啥玩意儿?

刚开始看https的时候,各种头大。国内网上讲相关的资料尽管一大堆,但是大部分是相互的抄,内容多而乱,且没有把事情讲清楚。后来查阅了少量外文资料(包括rfc、wikipedia等),读了JSSE的源代码以后,基本把这个事情的来龙去脉看懂了大部分,但是涉及到很多很细节的东西还是觉得不是完全懂,如有疏漏和错误,敬请大家指正和原谅 :-)

这篇文章的目标:用尽量简单和有趣的语言,把这个复杂的东东讲述清楚。所以,接下来我打算分成三部分来聊聊我了解的Https:

1、入门篇:主要用浅显的语言讲讲Https是什么东东,以及他大体的工作方式;

2、技术篇:结合抓包工具和源代码,分析Https的通讯流程和细节;

3、理论篇:不是特别深入的聊聊少量跟Https相关的算法。

====入门篇的分割线====

What’s HTTPS

简单的说,https就是给http带了一个安全套,即便别人拿到了信息,也不知道这个里面装的啥。用户端(包括browser、手机app等)和服务器每次发http包的时候,都对这个包加个密,让第三者看到的只是加密后的乱码(我只想对你说:你猜你猜你猜猜猜),到对端以后再解密。

这个安全套,原来是叫SSL(Secure Sockets Layer),最先是Netscape弄出来的,后来哥们儿完蛋了,就慢慢变了名字,叫TLS(Transport Layer Security Protocol)。具体的区别可以去wikipedia搜索TLS,他们之间的更新细节讲述的非常详细(这一点百度百科真的差的有点远~)。

这个安全套跑在TCP的上层,在TCP连接完成后且HTTP启动前,协商少量跟加密相关的工作,完成协商之后,即可以对要发送的http包加密/解密了。

那他究竟协商了些啥呢?其实就是保证安全的几个问题:

1、服务器要证实自己是靠谱的、安全的,不然给一个假网站发加密的密文就跟裸奔没啥区别

2、服务器和用户端通讯需要的加密算法和加密密钥

就跟当年天地会和韦小宝通信一样,先要亮出身份,证实自己,而后再拿出暗语的书信。

ComeOn! How TLS works?

第一步,服务器证实自己是靠谱的。

一个哥们儿XX说他是天地会的。假如你是韦小宝,你会怎样确认他的身份呢?

其中有一种方案可能是这样的:他会说S1是他师傅,假如你知道S1并和他确认了,就ok了。假如不认识,就继续问S1的师傅S2……一直问道陈近南,只需陈近南确认了,那即可以证实他了。看起来如同设计模式里面的责任链 XX -> S1 -> S2 -> … -> ROOT

服务器证实自己也是同样的逻辑,服务器S0有一个证书,说我是谁谁谁,这个证书由上级签发机构S1核准,假如你本地有这个S1的证书,那验证一下即可以了。假如没有,就问S1的签发机构S2。直到根的签发机构。假如本地认证找到了其中任何一级的证书,就认为S0是靠谱的。否则就是不靠谱。S0 -> S1 -> S2 -> … -> Root CA

实际上非常像工商局发的营业执照,你上面有我盖的红坨坨才是靠谱的。

HTTPS究竟是个啥玩意儿?

上图就是淘宝的认证级联关系。

这些靠谱的证书内置在操作系统、jdk等地方(百度或者者谷歌上搜索“https数字证书设置”相关内容即可以看到)。

HTTPS究竟是个啥玩意儿?

此图就是我本机证书列表的一部分。

这个就是基本逻辑,说白了,就是找一个我们都公认靠谱的人来证明你的靠谱。

第二步,协商加密算法+密钥。

加密和摘要算法有很多,常见的比方RSA、AES、DES、MD5、SHA等等。

大家把他们这样来分:

1、加密/解密算法:能加密同时能反解的,就是加解密算法。按照加解密的密钥能否一样,又分为对称和非对称算法。比方对称加密算法:AES、DES;非对称加密算法:RSA。

2、摘要算法:就是只用来做摘要、签名、验证防止被别人篡改,基本不能反解(有可能可以通过碰撞暴力破解)。比方:MD5、SHA。

那服务器和用户端接下来就协商一下,我们要用什么加密解密算法和密钥防止别人看见,用什么摘要算法,防止别人篡改。

一般来讲,对称加密算法效率会比非对称高,所以通常选择对称加密的AES较多。双方通过某种方式协商出一个密钥,后面就通过这个密钥和加密算法进行加解密。

用户端发送一个:“地振高冈,一派溪山千古秀”

服务端回复一个:“门朝大海,三河合水万年流”

整个过程大体就是这样,后面双方就开始发HTTP的加密包,对方解包得到对应的HTTP数据。

世界一下就清晰了,对吗?

No No No 其实还是很复杂滴…… 假如要想理解详细的技术内容,就让我带着你继续往下看(你敢不敢跟我来)

===技术篇的分割线===

工欲善其事,必先利其器

为了做详细的分析,我做了几个准备工作:

1、装了一个wireshark,用来抓取网络包

2、写了一个java程序,打开debug运行(java -Djavax.net.debug=all TestHttps),用来看交互细节

import java.net.URL;

import java.net.URLConnection;

public class TestHttps

{

public static void main(String[] args) throws Exception

{

final URL url = new URL("https://www.taobao.com");

final URLConnection conn = url.openConnection();

conn.connect();

}

}

3、找到openjdk源代码:http://grepcode.com/

通过前两个工作可以看到网络交互的过程和详细的数据包,第三个可以用来分析整个流程的代码。

(注:以下涉及到代码的分析,都是基于JDK8进行的,假如由于版本起因,相关函数和代码行数对接不上,请大家查找对应版本的代码)

好了,准备工作做好了,我们开始吧!

抓个包,先看看门道

先给taobao同学发个请求吧:curl https://www.taobao.com,看到整个交互过程大体是这样的(我把tcp三次握手,ACK包等无关的数据包都过滤掉了,只剩TLS相关的数据包):

HTTPS究竟是个啥玩意儿?

上图有几个交互数据都合并到一个TCP包进行发送了,比方漂蓝的那一行(No = 49)的TCP包实际上包含了三个TLS包(Certificate、Server Key Exchange、Server Hello Done),下面分析的时候,我就把这个包开展。

ClientServer
Client Hello ->

<- Server Hello

<- Certificate

<- Server Key Exchange

<- Server Hello Done
Client Key Exchange ->
Change Cipher Spec ->
Encrypted Handshake Message ->

<- Change Cipher Spec

<- Encrypted Handshake Message
Application Data ->

<- Application Data
Encrypted Alert ->

上面抓的包一律开展就是这样的效果。怎样样,是不是差不多也看了个大概?我来翻译翻译吧。

ClientServer
Client Hello你好!

Server Hello嗯,你好!

Certificate我的证书给你,验证我吧

Server Key Exchange这是我给你的加密密钥相关的东东

Server Hello Done好,我说完了
Client Key Exchange这是我给你的加密密钥相关的东东
Change Cipher Spec准备转换成密文了哦
Encrypted Handshake Message%……&amp;*4 (密文思密达)

Change Cipher Spec我也转换密文了

Encrypted Handshake Message#%&amp;……* (密文思密达)
Application Data%&amp;¥&amp;%*……(HTTP密文数据)

Application Data**……&amp;%(HTTP密文数据)
Encrypted Alert警告(实际就是说完了,拜拜~)

看起来是不是很简单呢?

这实际上就是文章一开始,我说的要处理的两个大问题:

1、认证server端的靠谱性

2、交换加密算法和密钥

具体每个包里面都发了哪些数据?server端靠谱性是如何来证实的?加密算法和密钥是怎样交换的?接下来让我逐个给你道来。

具体的交互流程和代码的实现

HTTPS究竟是个啥玩意儿?

我们就按命令一一来分析一下。

C:Client Hello

HTTPS究竟是个啥玩意儿?

可以看到发送了很多数据,但是最关键的几个数据:

1、TLS的版本

2、随机数:这个是用来生成最后加密密钥的影响因子之一,包含两部分:时间戳(4-Bytes)和随机数(28-Bytes)

3、session-id:用来表明一次会话,第一次建立没有。假如以前建立过,可以直接带过去。

4、加密算法套装列表:用户端支持的加密-签名算法的列表,让服务器去选择。

5、压缩算法:似乎一般都不用

6、扩展字段:比方密码交换算法的参数、请求主机的名字等等

这一段的java实现,是在sun.security.ssl.HandshakeMessage.ClientHello里面:

HTTPS究竟是个啥玩意儿?

S:Server Hello

当服务器收到用户端的问候以后,立即做出了响应:

HTTPS究竟是个啥玩意儿?

大体内容和用户端差不多,只是把加密算法的套装列表换成了服务器选择支持的具体算法。

通过这一步,用户端和服务器就完成了加密和签名算法的交换。这里的TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256拆分开看就是:TLS协议,用ECDH密钥交换算法交换对称加密密钥相关的参数,用RSA算法做签名,最后使用AES_128_CBC做内容的对称加密,SHA256做摘要。

具体实现在:sun.security.ssl.HandshakeMessage.ServerHello

HTTPS究竟是个啥玩意儿?

S:Certificate

这一步很关键,是服务器给用户端展现证书的时候。

HTTPS究竟是个啥玩意儿?

证书是一个链,从最底层一直到最顶层,表示谁谁谁给我认证的。翻译过来就是文章一开始给大家看到的那个东东:

HTTPS究竟是个啥玩意儿?

证书一般采用X.509标准,后面我会详细来讲述证书格式和如何级联认证。X509证书具体实现在:sun.security.x509.X509CertImpl

Certificate消息的实现代码在:sun.security.ssl.HandshakeMessage.CertificateMsg 里面

HTTPS究竟是个啥玩意儿?

S:Server Key Exchange

这个消息是用来发送密钥交换算法相关参数和数据的。这里要提前提一下,就是根据密钥交换算法的不同,传递的参数也是不同的。

常用的密钥交换算法:RSA、DH(Diffie-Hellman)、ECDH(Elliptic curve Diffie–Hellman)

后面会详细来讲这几个算法的某几个,现在就不详细走这个分支,只是知道他们可以交换密钥,有参数要传递就可。

(这里不得不感叹一句,老外对基础科学的研究真的是太深入了,这些算法十分的巧妙。希望有一天中国人也能对基础科学做出更多的贡献~)

HTTPS究竟是个啥玩意儿?

可以看到这里用到的是ECDH算法,交换了少量参数,对数据做了签名,防止劫持者篡改。

在Java里,这个消息有多个实现,分别代表RSA、DH、ECDH算法,对应的类分别是:

sun.security.ssl.HandshakeMessage.ServerKeyExchange

sun.security.ssl.HandshakeMessage.RSA_ServerKeyExchange

sun.security.ssl.HandshakeMessage.DH_ServerKeyExchange

sun.security.ssl.HandshakeMessage.ECDH_ServerKeyExchange

HTTPS究竟是个啥玩意儿?

以下是ECDH的实现:

HTTPS究竟是个啥玩意儿?

S:Server Hello Done

Server要表达的信息基本表达完了,把主持人话筒交给用户端:

HTTPS究竟是个啥玩意儿?

对应的实现:sun.security.ssl.HandshakeMessage.ServerHelloDone

HTTPS究竟是个啥玩意儿?

C:Client Key Exchange

这是用户端对Server Key Exchange的回应,用于交换密钥需要的参数。和服务器一样,不同的密钥交换算法实现是不一样的,因而需要的参数也是有差异的。

HTTPS究竟是个啥玩意儿?

这里用的是ECDH交换算法。

Java的实现也对应的多个,分别是:

sun.security.ssl.RSAClientKeyExchange

sun.security.ssl.DHClientKeyExchange

sun.security.ssl.ECDHClientKeyExchange

以下是ECDH的具体实现:

HTTPS究竟是个啥玩意儿?

好了,经过以上的步骤,Server-Client已经将服务器认证的相关工作做完了,密文函数&amp;密钥交换需要的参数也都相互传递了。剩下的,就是各自用一个叫做PRF(Pseudo-Random Function)的算法去生成加密密钥,具体的这个函数是一个对多因子屡次迭代摘要运算等的实现,这里姑且就当做是一个很简单的随机运算函数吧,比方:key = rand_c + rand_s + C。

到这一步,用户端和服务器就完成了密钥相关的交换

有了这个密钥,接下来,用户端和服务器就开始切换交流语言了(用密文开始说悄悄话),他们会各自发一个命令,说明自己已经准备好,开始切换语言了。

C:Change Cipher Spec

用户端切换成密文模式

HTTPS究竟是个啥玩意儿?

这个在Java里的实现在:sun.security.ssl.Handshaker

HTTPS究竟是个啥玩意儿?

C:Finished(Encrypted Handshake Message)

这个包表明握手已经完成,并且对之前发过的数据进行加密发送给对方做校验,防止被篡改。同时也验证一下,加密算法、密钥工作能否正常。

HTTPS究竟是个啥玩意儿?

具体代码在:sun.security.ssl.HandshakeMessage.Finished

HTTPS究竟是个啥玩意儿?

在收到这两个消息以后,服务器也发出同样的消息,即:

S:Change Cipher Spec

S:Finished(Encrypted Handshake Message)

嘘~~~(此地长出一口气) 至此,整个身份验证、加密/解密算法&amp;密钥的交换都已经结束,剩余的,就是进行正常的HTTP请求以及对请求数据的加密/解密。

以上这些步骤,都是对于使用ECDH密钥交换算法、没有session、不要求验证用户端有效性的情况。对于有session的、或者者要求验证用户端有效性、或者者使用其余密钥交换算法的,请求会有不一样,具体的可以看看实现代码,里面都非常详细也容易阅读,具体代码在:

sun.security.ssl.ClientHandshaker

sun.security.ssl.ServerHandshaker

里面有一个processMessage函数,是用switch...case写的相关的状态机。

看看,为了做安全的HTTP请求,需要额外付出多少的代价,来来回回需要多出多少次数据交换。

好了,假如还想理解其余更多更详细的东东,就继续跟我往下走,否则,在这里即可以return了 ^o^

===有点难度的理论分割线===

接下来准备聊聊关于x509证书&amp;证书验证、加解密、签名、密钥交换、随机的少量算法。因为我自己对这部分没有专门的研究,只是借这次机会看了少量资料,所以理解的不是非常深入,可能只能涉及少量皮毛,大家多多体谅和指正。

1、关于X.509证书&amp;证书验证

X.509就是一个数字证书的标准,就像工商营业执照一样,证实你这个网站是合法的。详细的可以参见wikipedia和RFC:

https://en.wikipedia.org/wiki/X.509

http://www.ietf.org/rfc/rfc2459.txt

在TLS中使用到了这样一个证书来进行有效性的认证。由于不是专业研究这个的机构,我们就不深入去研究这个标准,而是看看他的数据格式和如何进行验证。

证书的模样

我们先看看wireshark抓到的包长什么样:

HTTPS究竟是个啥玩意儿?

再看看Java的API文档给出的比较详细的定义:

http://docs.oracle.com/javase/8/docs/api/java/security/cert/X509Certificate.html

HTTPS究竟是个啥玩意儿?

HTTPS究竟是个啥玩意儿?

可以看出来,整体分为证书和对证书的签名两大部分。

证书包含:版本、序号、证书的签名算法、签发者、主题(被签发者)、有效期等的信息。

为了方便阅读,我们直接用chrome来查看证书:

HTTPS究竟是个啥玩意儿?

可以看到非常详细的信息,包括:被签发者的基本信息、签发者的基本信息,加密信息和签名。我们假如自己用openssl做证书的话,都会要求相关项的填写。有兴趣的同学可以自己做一个证书试试手 ^_^

证书的验证

当TLS协议验证一个网站能否有效的时候,Server会给出一个X509的证书链。用户端收到这个证书链以后,对证书链进行验证,所做的工作如下:

1、用最底端(证书链第一个)的证书,去验证请求的主机和证书里的能否是一致

2、逐次验证证书链里每张证书的合法性,直到找到一张证书在系统中存在:这一步又包含每张证书能否在不信任名单里、检查签名算法、检查时间能否过期、检查证书的发布者和证书链的上一级能否匹配、证书链的签名检查

以上检查中,大多是按字节比照,相比照较简单,相关代码参见以下几个函数的实现:

sun.security.ssl.X509TrustManagerImpl.checkTrusted

sun.security.validator.SimpleValidator.engineValidate

sun.security.x509.X509CertImpl.verify

sun.security.x509.X509CertImpl.checkValidity

不过,其中证书链的签名检查是一个非常有意思的算法,这个算法我着实研究了一阵儿,还写了一个简单的程序去试验,在这里略微详细讲述一下。

我们得到了一个证书链,将他扩开展成为一个层级关系:

HTTPS究竟是个啥玩意儿?

对于每一级的证书,都是由上一级用私钥对证书的sha摘要值进行签名(Root一般由自己签发),签名一般使用RSA算法。验证的时候,用上一级的公钥对签名进行解密,复原对应的摘要值。如下图:

HTTPS究竟是个啥玩意儿?

这里先提前最最最简单的插入一下RSA算法。RSA是非对称加密,有一个公钥(模数和指数)和一个私钥。M代表明文消息,C代表密文,n代表公钥模数,e代表公钥指数,d代表私钥。

假如我们用公钥对明文M加密,私钥解密,则是为了传递信息,对消息进行加密;

假如我们用私钥对明文M加密,公钥解密,则是为了保证消息是我签发的,没有伪造和篡改。

这里,我们详情后一种(即防篡改和伪造)。

签名加密:C = (M ^ d) mod n

签名解密:M = (C ^ e) mod n

先请不要问我为什么,后面会单独讲,哈哈哈(是不是很贱)~

好,回归正题,上一级认证机构用私钥(d)对下一级的证书的SHA数字签名(M) 进行RSA加密得到密文(C)。而第三方只需用上一级的公钥(e, n)对这个加密进行复原,并能得到相关的SHA数字签名(M),即可以认为是经过上一级认证过的(由于只有他才能签的出来)。

Come on,我们来实践一下吧:

下图淘宝上一级证书的公钥(这些机构就卖证书即可以赚翻了):n(图中的256字节公共密钥)和 e(图中的指数)

HTTPS究竟是个啥玩意儿?

我们写一个程序来验证一下:

HTTPS究竟是个啥玩意儿?

由于要用大数计算,所以用到了Java的大数类(这是用的最直接暴力的算法,其实还可以有很多优化,比方O(n) -> O(lgn),先取模再乘等等)。

最后输出的结果如下:

1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420bedfc063c41b62e0438bc8c0fff669de1926b5accfb487bf3fa98b8ff216d650

其中1fff...ff00是PKCS #1 v1.5 标准的前导补位,详见:http://tools.ietf.org/html/rfc2313#page-9

接下来 303130…0420 是SHA-256摘要算法的标识,详见:http://tools.ietf.org/html/rfc3447#page-43

剩余部分正好32Bytes,是整个证书的SHA-256摘要。

是真的吗?确认那个32Bytes就是SHA-256的摘要么?来吧,我们写一个程序验证一下:

HTTPS究竟是个啥玩意儿?

这个程序大致的意思,就是截获X509证书的验证,输出对应的证书信息。并用SHA-256对整个证书做摘要。得到的信息输出如下:

======================

cert-count:

3

subject:

CN=*.tmall.com, O="Alibaba (China) Technology Co., Ltd.", L=HangZhou, ST=ZheJiang, C=CN

cert-sign:

3ec0c71903a19be74dca101a01347ac1464c97e6e5be6d3c6677d599938a13b0db7faf2603660d4aec7056c53381b5d24c2bc0217eb78fb734874714025a0f99259c5b765c26cacff0b3c20adc9b57ea7ca63ae6a2c990837473f72c19b1d29ec575f7d7f34041a2eb744ded2dff4a2e2181979dc12f1e7511464d23d1a40b82a683df4a64d84599df0ac5999abb8946d36481cf3159b6f1e07155cf0e8125b17aba962f642e0817a896fd6c83e9e7a9aeaebfcc4adaae4df834cfeebbc95342a731f7252caa2a97796b148fd35a336476b6c23feef94d012dbfe310da3ea372043d1a396580efa7201f0f405401dff00ecd86e0dcd2f0d824b596175cb07b3d

sha-256:

bedfc063c41b62e0438bc8c0fff669de1926b5accfb487bf3fa98b8ff216d650

======================

这个证书签名以及对证书做的SHA-256摘要,和我们之前所得到的结果一样一样的~~

好了,到此为止,X509证书的格式和验证基本上也讲了一个大概了,真是非常不容易啊(为了写文章,肚子已经饿的咕咕叫了)~

2.关于RSA算法

仔细想想,RSA算法在哪些地方被用到了呢?

1、证书签名的时候(上面刚刚做了验证,对吧)

2、密钥交换

HTTPS究竟是个啥玩意儿?

为了防止信息被截获篡改,需要对密钥交换的参数做签名。

所以,RSA算法是一个非常关键的加解密算法。那我们就来简单聊聊吧~

(最近看RSA,越看越觉得这个算法很有意思~)

注:为了在文本上打印方便,以下采用 ^ 这个符号作为乘方的运算符,即2^4代表2的4次方。

来看看他的定义吧,老复杂了!

1、选两个超级大的素数:p 和 q

2、把他们乘起来:n = p * q

3、而后把p-1和q-1也乘起来:m = (p - 1) * (q - 1)

4、再找一个和m互质的数:e -> gcd(e, m) = 1

5、最后,找一个d,满足:(e * d) mod m = 1

6、而后公钥就是(n, e)的组合,私钥就是(n, d)的组合

……

我的妈,这么复杂,人都要疯了,是不是?

为什么要搞这么复杂呢?

其实用到了几个原理或者者定理或者者…… 他们分别是:

1、大数分解难题

2、费马小定理

3、中国剩余定理

4、扩展欧几里德算法

是不是被吓蒙了呢?哈哈哈,因为这一篇是讲Https的,所以就不详细讲这几个原理,简单表述一下(就算是简单,也要说很多,也要码很多的字……)。

首先,RSA建立的一个基本准则就是大数分解,假如没有这个准则,就扯淡了。

我们给两个素数,比方 5 和 11。我们能很容易求出他们的乘积:5 * 11 = 55

当然,在这个规模下,我们也很容易将 55 分解成 5 * 11。

但是,假如这两个素数很大呢,比方10的几百次方。我们还是很容易求出他们的乘积。不过,你再想分解他,就不容易咯~

其次,著名的费马同学,发明了很多很多定理,其中比较著名的就是费马大小定理,小定理是这么说的:对于一个素数n和任意的正整数a,( a ^ ( n - 1 ) ) mod n = 1

我们来试试,比方 n = 5,a = 4, 那么 a ^ ( n - 1 ) = 4 ^ ( 5 - 1 ) = 256,256 mod 5 = 1

很神奇吧!网上可以搜一搜详细的证实。

这个公式演化一下,即可以得到a的n次方和a分别对n取模,结果是一样的:( a ^ n ) ≡ a (mod n)

比方上面的那个例子:( 4 ^ 5 ) mod 5 = 4 ; 4 mod 5 = 4

那就是说假如n是一个素数,任意一个数的i次方模n,都会呈现n-1个数的循环周期(不肯定是最短的周期),比方:

4的1,2,3,4,5,6……次方模5的余数:4 1 4 1 4 1……

假如n是两个素数p和q的乘积,那么这个周期会呈现 (p -1) * (q - 1)这么长。也就是说,a 和 a的(p - 1) * (q - 1) + 1次方模n,得到的结果是一样的。特别的,假如a < n,那么这个余数是不是就是a了呢?!

哈哈哈,绕了那么大一个弯子,最后的意思就是说,我只需知道 ( a ^ ( (p - 1) * (q - 1) + 1) ) mod n的余数,实际上就是知道了a,对吧!

那我只需变个花样儿即可以。 我先让m = (p - 1) * (q - 1) ,而后找一个和m互质的数e,再求出一个d,让 e * d = k * m + 1。这样,我给一个数字 T (其中T < n),计算出 C=(T ^ e) mod n, 我拿着C做一个(C ^ d ) mod n,于是乎,神奇的一幕发生了:(C ^ d) mod n = ( (T ^ e) ^ d ) mod n = ( T ^ (e * d) ) mod n = ( T ^ (k * m + 1) ) mod n = T mod n,由于 T < n ,所以结果就为T!!!

举个例子,我们让p = 5, q = 7,推算出来 n = 5 * 7 = 35, m = (5 - 1) * (7 - 1) = 24

我们找一个e,比如是11,那么肯定可以找到一个d = 35,e * d = 11 * 35 = 385,

( e * d ) mod m = 385 mod 24 = 1

我们选一个数字T = 18, 计算 C = (T ^ e) mod n = 2

而后 计算 (C ^ d) mod n = 18 = T

以上就是RSA的原理,是不是要清楚一点了呢?

现在还有一个问题没有解答,就是我们是怎样找出d来的,实际上就是要解一个方程:

( e * x ) mod m = 1 等价于 e * x + m * y = 1,其中x就是d。

这个就是中国剩余定理里面讲到的东东,具体实现的时候,用扩展辗转相除法(这就是扩展欧拉算法)做个迭代就出来了。

补充一点,RSA涉及到指数运算,效率会比较低。实际上有很多优化的方法,比方O(n) -> O(lgn),先取模再乘,降维到p和q等等,就不在这里细开展了。

3.最后简单聊一个密钥交换的DH算法

我们在之前提到,TLS要做的事情就是两个:身份校验 &amp; 加密算法和密钥协商。

身份校验我们前面已经比较详细的讲述过了。加密算法的协商我们之前也在流程中讲述过。剩下关于密钥交换和协商,我们之前轻描淡写的聊了下。下面略微详细的讲述一下。

在密钥交换的过程中,会用到一个PRF的函数,是”Pseudo-Random Function”这个的简称,中间计算过程比较复杂,有兴趣的同学可以在网上搜索查阅(因为偷懒,我没有详细深入这个函数 ^_^)。

整个密钥的生成大体如下:

master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random)

具体代码可以参见:

HTTPS究竟是个啥玩意儿?

笼统上来讲,就是 server和client 根据Hello时的两个随机数 加上 用户端产生的pre_master_secret来产生一个master_secret,最后由这个东东生成需要的MAC(Message Authentication Code)、key等等加密需要东东。

那其中就有一个关键问题,用户端的pre_master_secret怎样样告诉服务器的?

我们可以用之前讲过的RSA算法,用户端通过服务器公钥将这个值加密后传递给服务器,服务器再去解密。也可以通过一个叫做DH(Diffie-Hellman)的算法。维基百科对这个算法讲的十分详细。

我就简单翻译一下:

有两个哥们儿,Alice和Bob,他们想交换数据,于是乎也不知道怎样就想出了一个牛逼的算法:

1、取模数 p = 23,底数 g = 5

2、而后Alice想了一个整数a = 6,发送给Bob一个数:A = (g ^ a) mod p = (5 ^ 6) % 23 = 8

3、同理,Bob想了一个整数b = 15,发送给Alice一个数:B = (g ^ b) mod p = (5 ^ 15) % 23 = 19

4、Alice拿着Bob给的B = 19,计算了一个数:s = (B ^ a) mod p = (19 ^ 6) % 23 = 2

5、Bob也用同样的方法,算了一下 : s = (A ^ b) mod p = (8 ^ 15) % 23 = 2

就这样,在不泄露a、b的情况下,他们两都得到了一个一样的数。就这样,数据交换了。。。

其实理论基础就是: A ^ b ≡ (g ^ a) ^ b ≡ g ^ (a * b) ≡ (g ^ b) ^ a ≡ B ^ a (mod p)

更详细的说明,可以看维基百科的解释。

后来又有一个改进的算法ECDH,这里就不详细讲述了(偷懒了,以后有机会再补~)

====总结的分割线====

好了,断断续续的抽大家睡觉的时间,把这篇文章写完了(总算没有当太监)。个人觉得把HTTPS整个的流程、交互的过程做了一个大体的理解。有一部分做的深入些,还有很多算法看了一个一知半解,越是深入却发现不懂或者者不理解的越多。剩余还有几个点因为篇幅和时间的起因没有讲到,比方:如何访篡改、如何防回放攻击、如何做PRF、交互里面有些扩展参数等,后面准备再抽时间把这些补全。

因为之前主要是聚焦在常规算法和互联网技术架构方面,对信息相关的科学理解不是那么深入。后面准备把信息论、加解密算法的相关东西系统性的看下,完了之后分享出来。有兴趣的同学可以关注我的微信:simplemain

作为一个码工,就想安安静静做做技术。春天来了,可以有更多的时间听着柔美的轻音乐写更多的东西了。下面这张照片是我2012年4月在山东济南拍的春天,4年时间过去了,又把他翻出来,感受一下当年的春意盎然。Hello, World!

HTTPS究竟是个啥玩意儿?

附:部分参考资料

https://en.wikipedia.org/wiki/Transport_Layer_Security

http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html

http://www-brs.ub.ruhr-uni-bochum.de/netahtml/HSS/Diss/MeyerChristopher/diss.pdf

http://grepcode.com/snapshot/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/

http://drops.wooyun.org/tips/11232

http://tools.ietf.org/html/rfc3447#page-43

http://netsecurity.51cto.com/art/201505/476337_all.htm

x509:

http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/java/security/cert/X509Certificate.html

RSA:

http://blog.csdn.net/starryheavens/article/details/8536238

https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29

Diffie-Hellman:

https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange

http://my.oschina.net/u/1382972/blog/330456

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】在Qt中如何设置窗体的背景图片(2025-10-29 20:27)
【系统环境|】无声无名 | 杨·罗威斯终身回顾展(2025-10-29 20:26)
【系统环境|】从零开始学Qt(22):QSS详解(3)- 盒子模型(2025-10-29 20:25)
【系统环境|】Quarkus vs Spring Boot 集成 RabbitMQ 谁更香?(2025-10-29 20:24)
【系统环境|】RabbitMQ相关概念及代码示例(2025-10-29 20:24)
【系统环境|】Spring Boot + RabbitMQ:轻松掌握五种基本工作模式(2025-10-29 20:23)
【系统环境|】一篇文章带你彻底玩转-RabbitMQ(2025-10-29 20:22)
【系统环境|】私有云平台搭建——史上最详细(2025-10-29 20:21)
【系统环境|】RabbitMQ最全详解(万字图文总结)(2025-10-29 20:20)
【系统环境|】.Net/C#全网最火RabbitMQ操作【强烈推荐】(2025-10-29 20:20)
手机二维码手机访问领取大礼包
返回顶部