看了那么多谍战片,比如说伪装者,黎明之前,潜伏,风筝等等,吸引我们的除了精彩的打斗环节,另一个就是破译密码。密码对人们总有一种独特的诱惑力,在谍战中有趣的密码经常让人事后会拍案叫绝,那么今天咱们就来聊聊这神秘的加密与通讯吧。
本篇文章阅读大约需要15分钟,看完一定会让你受益匪浅!所谓大神,除了技术水平高,化繁为简也是一流,很深奥的东西也可以做到通俗易懂!话不多说,进入正文吧:
知乎上有一篇介绍网络安全的文章,其中关于HTTP/HTTPS以及密码保存的相关内容甚是有趣,文中谈到登录过程中一定要使用HTTPS而不能使用HTTP,否则中间人攻击将很容易取得用户的密码。其实这个说法并非完全正确,密码的安全性并不能因为使用了HTTPS就高枕无忧,也并非使用了HTTP就不安全。
什么是加密?
加密是将一种信息表达变成另外一种信息的表达方式。一个生动的例子就是在外地,你和老乡交谈时用普通话表达“我爱香菜”和用方言表达”我爱香菜”是一个意思,但是其他人恐怕会听不懂方言。
另一种就是映射关系了,就像下面这张对应表,实际上你可以叫它映射表,就是把一串数据对应某种关系变成另外一串数据。如图所示:
假设我们将没有加密过的信息叫明文(A),加密后的信息叫密文(C),设B为加密方式,那么加密的过程就可以写成类似A•B=C,当然解密过程就是
你的钥匙安全么?
假如我们有五个数字要告诉对方,分别是1、2、3、4、5,加密就是将每个数字乘以2,于是对方就收到了密文2、4、6、8、10,对方只需要将每个数字除以2就能取得明文1、2、3、4、5。
在这个过程中,2作为整个加密过程中最关键的数字,可以说是整个加密解密的钥匙,你就需要好好保存了,一旦让别人知道了你的密钥,你的加密将会形同虚设。
假如你需要和一个不认识的人进行加密通讯,你如何保证你的钥匙能交给你的接头人呢?当面交易不管是在密码还是网购都属于一个比较靠谱的方式,但是如果你想通过信件的方式,就要经过一堆不知名的邮差邮局,最终到你的接头人手中。
但是你会担心中间有没有人把你的钥匙给拷贝了一份,你无法保证中间人会不会出卖你,然而你却不得不把自己手中的钥匙交给他们,否则你的接头人就无法使用它来和你进行加密通讯了。
尽管这种方式和我们实际说的密码学多少有点不一样,但是它确实给了我们一些提示,例如设明文为A,密钥为B,密文为C,是否存在一种加密函数使得:
A•B=C
C•D=A
简单来说就是加密的密钥和解密的密钥不一样,这样我们就不用担心密钥被泄漏。在现实中有点像这么一个过程:
1、首先准备一个带锁的箱子,用钥匙把这个箱子打开(公钥);
2、把这个箱子交给邮递员,同时箱子里附上一个字条,上面写着:请接头人想一个我们之间的通讯加密方式,然后把密钥也放在箱子里锁上寄回给我;(通过公钥加密)
3、当这个锁上的箱子再次回到你手中时,用钥匙打开箱子,取得密钥和加密方式;(私钥解密)
4、之后就可以用这个加密方式和密钥进行通讯了。
上面这个办法完美地避免了中间人看到你和接头人密钥,毕竟在交回来时,它可是锁在箱子里面的,只要你发现收回来时这个箱子有什么不对劲,你立即可以编辑短信“有内鬼,终止交易”。
虽然最后放在数学中这个方式有点不同,但在思路上却是大同小异,你也许已经发现了在高中的阶段,要计算
要简单的多,当代的不对称密钥技术(公钥加密),大多都用上了这种信息不对等的理念,也就是正推容易逆推难。
谈到公钥加密,就不得不聊聊目前相当有名的RSA和ECC了,相对于ECC,RSA理解起来就容易的多,RSA加密简单来说利用了大数质因数分解的数学难题:
比如现在你可以随便挑选两个素数,例如59、83,然后将它们乘起来59*83=4897,即使是一个小学生也能在十几秒内算出来,但是如果我只告诉你4897这个数,然后让你做因数分解,八成你需要一个一个去试数了。
假如这两个素数挑选的都非常大,那么就算是超级计算机上场,恐怕也得算到世界末日了。但幸运的是,理解RSA加密并不复杂,即使是在这短短的篇幅中,也很容易将RSA的原理给讲清楚。
因此上式最终变为了x%n=x,RSA得证,要破解RSA,那么关键就是找到这个d了,我们看看d是怎么来的,首先从点3我们知道,要知道d首先要先知道k,而k=(p-1)(q-1)也就是需要知道p和q了,我们公布的只有一个e和n,按照不成文的钦定就算e是65537,也就是说我们必须通过n倒推出p和q,那么问题就变成了这个大数因数分解的世纪难题了。
RSA已经流行了多年,很多时候这套理论就会被爆些大新闻让人感觉其安全性已经摇摇欲坠,但是最终RSA仍然屹立不倒,也许在之后的某一天量子计算机诞生或者哪个大神真正找到了某个快速大数的质因数分解的方法,RSA也算真正完成它的历史使命了。
公钥加密技术有许多优点,但其缺点也一样很明显。大多的公钥加密算法其性能开销基本都比密钥对称加密大得多,因此他们一般都不用于加密大量的数据。
在实际使用中,它们大多被用于交换其它更加经济快速的加密密钥对,或者被设计与数字签名,如果你想进一步了解RSA,可以在互联网上查找相关资料。
HTTP/HTTPS
看到小标题你可能会犯嘀咕,刚说完密码怎么突然就跳到HTTP/HTTPS上来了呢,一个非常直观的理解就是,HTTP就是你用明文来写情书,HTTPS就是你的情书加密了,实际上后者就是前者加密后的产物。
那么什么是HTTP呢?你可以打开一个网站如果你用的是chrome,那么按下F12,你可以看到有一堆文字:
这段文字就是符合HTTP规范的的文字(当然HTTP协议相关的细节信息已经省略了),你可以管它叫网站源代码,或者简单一点来说就是这段文字经过解析后变成了你所看到的网页,当然,这个源代码可以在互联网上传输,就像你把情书交给了一个不靠谱的邮递员一样,这个邮递员可能已经被你的情敌收买了,把你的信件拆开来添油加醋地加一点东西然后再神不知鬼不觉地封回去。
这样足够给你造成一些情感危机了,但HTTPS能够很好的避免这一堆问题,因为这段文字被加密了,如果不知道解密手段的话,即使添加了一些东西解密后也会变成一堆意义不明的数据,收信方也很容易察觉出问题,因此HTTPS显然在防篡改方面比HTTP要安全。
那么HTTPS是否就一定比HTTP安全呢?HTTP是否一定就不安全呢?就像知乎文章的作者所说,不管怎么样一定要使用HTTPS做密码的登录框,不然密码就会被泄漏。
其实这句话就有点像屠龙宝刀如果给一个菜鸟的话,恐怕真到约架时也会被砍的娘都不认识,假如把一根树枝给独孤求败这种人物,就算是在多人一起上也是被扁的哇哇叫,打铁还需自身硬,如果自身都不够硬,真要干起架来,哪怕是再好的武器也于事无补。要理解HTTPS为什么安全?安全在哪里?我们就得去深入探究。
HTTPS和中间人攻击
有关于HTTPS的传输流程是怎么样的,可以看到HTTPS比HTTP就多了一个字母S,这个S代表着SSL(Secure Socket Layer)的意思,也就是安全传输层。
首先SSL层先使用公钥加密技术交换密钥对(比如RSA,ECC….),之后再使用AES DES或者更经济点的RC4进行加密通讯,看上去这个交递箱子的方案似乎没有什么问题,但我们回到那个交递箱子的过程:
1、首先准备一个带锁的箱子,用钥匙把这个箱子打开(公钥);
2、把这个箱子交给邮递员,同时箱子里附上一个字条,上面写着:请接头人想一个我们之间的通讯加密方式,然后把密钥也放在箱子里锁上寄回给我;(通过公钥加密)
3、当这个锁上的箱子再次回到你手中时,用钥匙打开箱子,取得密钥和加密方式;(私钥解密)
4、之后就可以用这个加密方式和密钥进行通讯了。
我们做一个假设,假设这个邮递员准备了一个和你一模一样的箱子,然后伪装成你的接头人和你通讯,再用这个伪造的箱子和你真正的接头人进行通讯,那么你还能保证你的通讯是安全的么?
恐怕这个时候,即使是公钥加密技术也无能为力了,我们能做的只是尽量提醒接头人,比如在箱子上盖个印章条形码,并方方正正地写上“此箱子版权所有,仿冒必究,请到xx正品店进行专柜验证”,然后祈祷你的接头人会好好地验证这个箱子的真伪,但鉴于你和接头人从未谋面,恐怕他也并不知道你会不会给他寄个“带有防伪标签的箱子”。
这个过程几乎和SSL的理念一样,每个HTTPS的站点需要向一个可信的第三方CA(数字证书的颁发机构)申请一个证书来向每一个浏览你网站的人证明你的信息,但浏览你网站的人可能根本无法意识到,你的网站是否进行过防伪了,这种中间人攻击的手段又叫SSL剥离攻击,其原理图如下:
如何避免中间人攻击?
如果你的网络流量出入口真被某些居心叵测的破坏分子控制的话,你能做的就是尽量祈祷这个家伙的技术水平不够,搭建一个SSL剥离的攻击方案也许就是一个黑wifi,一次ARP劫持和几个脚本的事情。
实际上避免攻击的准则除了选择一个可以信赖的网络服务商,更多的工作需要在自己设计的代码中去实现而不是盲目地相信某种通用的手段(当然不是说HTTPS不好用,有条件当然还是最好用上),一个最基本的理念是,如果攻击你的成本远远大于攻击成功取得的价值成本,就能够很大程度的避免自己被一些别有用心的大佬而不是吃的太饱的大佬摆上一道,这也就是为什么我们学习密码学的原因。
如果你能将那些更加复杂的公钥加密技术设计在你的通讯体系中,设计的程序能够利用这些知识去验证收到数据的真伪(比如验证可信CA颁发的签名证书)那么攻击者就需要花费更大的代价去剥离你的验证部分,或者根本就不可能在偶然的一次通讯劫持中完成这类攻击。
但遗憾的是在代码通用化程度如此高的今天,尽管很多软件运用了完善的加密体系,最大程度地保证了通讯的安全,但大部分因为开发成本或者是其它的关系,开发人员并没有好好的给自己充个电,认为使用现有的安全架构就能够一劳永逸去避免一堆可能带来的问题。
例如这个登录的验证问题,处理起来远远不是弄个证书整个HTTPS就能够解决的,但不论是出于开发平台还是出于开发成本或者是开发员的技术水平,绝大多数的网站在保证安全这块都还有很长的路要走。
除了开发人员,最后是写给用户的安全建议:
1、请在信任的网络中下载程序或流量网页;
2、如果你链接了一个不信任的网络,请不要浏览不带有效签名的网站;
3、不要下载没有有效签名的软件,如果你信得过这个没有签名的软件,也要在信任网络中下载;
4、了解密码安全的一些知识;
5、找个靠谱的码农朋友。
散列函数(hash)
散列函数俗称hash函数。在开始科普关于hash函数之前,首先谈谈大约五六年前CSDN数据库泄漏的事件,尽管我们无法猜测csdn到底出于什么目的将用户的密码进行明文存储,但这个事件无疑在圈内掀起了轩然大波,无数无辜躺枪的码农程序猿忙着修改自己的账户密码,避免被某些别有用心之徒用撞库的手段给自己造成损失。
倘若csdn不使用明文记录用户的密码信息,而将这个密码用某种不可逆的手段编码成其它的数据,至少不会造成如此巨大的损失。
hash函数到底是什么呢?按照百度百科的说法,就是指通过散列算法,变换成固定长度的输出,该输出就是散列值。说的太专业了?没关系,除法求余数总会吧,看下面的式子:y=x%99
这是一个很简单的求余运算,x表示输入的某个整数值,y表示输出的值,显然不管x取多少,y的结果必定在0-99,如果你知道y的值,那么能不能求出x的值呢?很遗憾也许你能找出很多个符合这个条件的x值,但你恐怕永远不能确定原始的x值是哪一个了。
整数求余运算是一个非常简单的散列运算函数,或者通俗点叫hash函数,但这是一个不合格的hash函数,因为我们可以非常容易地通过输出y求得多个x的可能解,并且x和y在一定的范围内存在线性关系,而理想的hash函数是正着算容易,倒着算难,同时输入的轻微变动也将导致输出极大的不同。
那么这就很有意思了,假如我们在数据库保存密码时,使用适当的hash函数对其进行编码,那么就能够避免我们的密码明文被泄漏了,说到这里必须要提一下当今赫赫有名的几个hash函数,比如MD5,SHA256。
这就安全了么?
当明文的密码使用MD5或者是SHA256后,想要再逆向为明文是不大可能的,但这还不足以让你高枕无忧,毕竟不久前刚报出个大新闻MD5被破解了!
当然被破解这种标题党的行为在学术上来说极为不准确,准确来说是MD5被找到了一种能够快速找到碰撞的办法,那么碰撞是什么呢?我们回到之前的y=x%99,如果我们知道y的值是1,那么x的值是多少呢?显然x的值可以是100,可以是199,可以是298….
如果我们用求余法作为密码的hash函数,那么我们输入199,298…哪怕我们的原始密码是100,也会被当做是正确的密码,也就是说,199,298是100对于该hash函数的碰撞结果。
这可就要命了,明明黑客输入的密码和我们输入的密码不一样,系统还是将它当做了一个正确的密码让他登录了,这简直就是密码系统的灾难,既然MD5不再安全了,那么就放弃MD5专用SHA256吧。
然而还是太天真了,我们忽略了一个最基本的事实,如果明文的密码长度不够,那么不管加密的手段如何的高明,我们也能通过穷举的方式进行破解,比如你的密码是一个三位数的数字,那么我只需要把100-999都尝试一遍,就可以知道正确的结果了,也许用人脑这个办法有点难,但是在计算机当中,完成这个穷举连1秒都不用。
实际上确实也有人这么干了,他们购买了大容量的存储设备,收集大量常用明文密码进行hash函数计算,同时他们建立了快速的查询机制,只要你的密码长度不够或者使用了一些常用的密码,那么hash函数对你明文密码的保护机制将很可能不再有效,而这种方法在网上有个比较漂亮的名字叫彩虹表。
给密码加约束
为了避免彩虹表的危机,我们必须对密码加一系列的约束,比如我们可以规定密码的长度,一定要大小写组合的8位以上,16位以下,然后在密码的结尾加上一段我们自己想出来的随机的值增加输入长度,以避免常规计算的的彩虹表对我们的密码进行暴力破解。这是一种非常流行的做法,用专业的术语来说就是加盐(salt),那段随机的值就是我们所说的盐值,这个效果的确非常有效。
如今已经证明不安全的MD5在寻找碰撞不是那么的快的时候,只要这个salt足够长,的确能够在一定程度上缓解这次的危机问题,但不管如何,我们仍然应该摒弃那些不再安全的hash函数,使用目前相对安全的hash函数。同时在设计通讯架构时,永远不要相信当前的密码手段是永恒不破的,毕竟这就和明天我会不会中个亿元大奖然后走向人生巅峰一样,谁又说得清呢?
你或许感兴趣的,更多内容请到i春秋官方公众号查看!
来源:freebuf.com 2018-12-27 17:57:50 by: i春秋学院
请登录后发表评论
注册