ssh的相关总结ssh登陆的过程非对称加密RSA登陆过程免密登陆linux相关文件及操作公钥与秘钥的保存格式用密码加密密码可行性彩虹表预计算的哈希链集(Precomputed hash chains)R函数的问题彩虹表的问题彩虹表的防御是否需要预先获取常用的密码HTTPS中的S参考资料
问题起源: 在使用git时有两种方式一种ssh方式,一种https的方式。且在之前clone同事的simhash的代码时,出现了ssh的public key没有上传到服务器导致clone失败的丢人事情。
重点在于理解一下几个过程
- 使用
ssh username@hostname
这个命令时背后的整个工作流程。
- git中要使用ssh方式时需要做的事情
- https里面的s的含义以及和http的区别。
- ssh 使用到了RSA 非对称加密算法
- ssh 里面将自己的公钥放到服务端文件里面,是为了实现
免密
登陆。不放在服务端,则还是需要每次登陆时填写密码,但整个通讯过程也同样是安全的。
secure shell
。登陆任何一个系统,都需要提供用户名和密码。问题在于涉及网络传输时(tcp),如何保证用户输入的用户名和密码不被人窃取: 只能对信息进行加密。如果用户发送给服务端的信息是加密的,那么外界即使获取到这些信息,也无非是一串01而无法还原为真实的信息。当加密后的信息到达服务端时,服务端进行解密。问题是服务端如何进行解密?加密在用户端、解密在服务端,是否需要用户端将解密的方式传输给服务端?如果这么做,这些信息又已经暴露。非对称加密RSA
RSA算法是非对称的加密算法。非对称指的是加密和解密时用的密码不一样。数学上看着推导来难度并不大,但看过后一周就会忘记内容,所以我还是将其看成黑盒。抓住相关重点即可。
密文=(明文^e) mod (n)
明文=(密文^d) mod (n)
其中(e,n) 和 (d, n) 是两个大整数、互质。其中一个用做公钥,另外一个用做秘钥(两个地位是一样的)
且想要从(e, n) 推导出(d, n) 涉及到大整数的质数分解。难度很大。这里的难度也是RSA安全性的保证。
上面的明文、密文其实都是一个数字。毕竟这是两个数学公式。要求明文、密文的值不能大于n.
一般由于安全性考虑,n为1024位长。所以明文密文都不会比这个长度长。因此实际的加密过程:
1. 要么将长文本分成几段分段加密。
2. 要么结合一种对称加密算法,将对称加密算法的密码使用公钥加密后进行加密(这个明显更加靠谱)
?
登陆过程
有了非对称加密的基础知识后,来看整个登陆过程。
- 用户发起请求,表示自己需要登陆
ssh username@remotehost
这里的信息是username
,其实这一步还不需要。
- 服务端获取到信息后,将自己的公钥发送给客户端(第一次时,系统会问是否信任该公钥)。客户端输入自己的密码,程序会自动使用公钥将密码加密,加密后发送给服务端。服务端使用私钥进行解密并且认证用户密码是否正确。
自己点评: 一般来说,服务端是不会存储用户的明文密码。因此服务端在进行解密后,还需要进行固定的加密工作比如: 加盐后MD5。然后在于数据库中的内容比对。
- 认证通过后,客户端可以正常与服务端通讯。所有通讯内容使用服务端的公钥进行加密。
上面的登陆以及通讯是足够安全的。问题在于需要每次用户输入密码。为了免密登陆:
- 用户将自己的公钥储存在服务端。(一般是登陆后自己去服务端对应目录下添加自己的公钥)
- 后续登陆时: 服务器发送一段随机的字符串,ssh程序自动使用用户的秘钥进行加密后发送给服务端,服务端使用用户已经储存的公钥进行解密后与原字符串比对,如果一致则用户自动认证成功。
- 用户的公钥与秘钥文件地址为:
cd ~/.ssh/
其中id_rsa
为私钥id_rsa.pub
为公钥。该目录下的known_hosts
就是每个服务器的公钥。
- 如果该目录下没有相关文件,则说明用户没有生成过公钥私钥。使用
ssh-keygen
进行生成。
- 【SSH的总结】需要将自己的公钥复制到远程服务器上,使用
ssh-copy-id user@host
或者直接复制公钥内容黏贴在远程的~/.ssh/authorized_keys
里边
由RSA算法知道,公钥和私钥就是两个大整数而已。但实际在
~/.ssh/id_rsa
中看到的确不是这个样子的。简单来说,文件里面的内容是使用了ASN.1格式
且用了特定的编码后产生的。反正我个人是将这些格式和编码当成黑盒来处理的。之所以需要进行编码,是因为二进制的内容无法再文本中显示。因此最后使用了base64编码将其可视化。用密码加密密码可行性
ssh其实主要解决的是在传输过程中信息不安全的问题。而加密后需要将解密的方式告诉对方,于是循环陷入了对解密方式的加密….
如果直接使用用户本身的密码,对信息进行对称加密。到服务端在使用用户的密码进行解密。因为密码本身在客户端、服务端都存在,因此不需要传输
解密方式
本身。想法是好的。这里不谈这种方式的破解难度,只说实际存在的问题。实际上,服务端是不会有用户的密码的原文。服务端保存的是经过加盐后的MD5(可能有更多复杂的变换)的值。因此服务端是无法进行解密的...
彩虹表 由于RSA的强大,想暴力的从公钥推出秘钥基本是不可能的(大整数的质数分解)。因此最自然的破解想法是,将常见的密码收集起来,然后使用相同的算法,算法一个结果值。然后一个
Map<结果值,原值>
的映射即可。这算是最朴素的方法,问题是空间开销大。一行记录对应一个结果。预计算的哈希链集(Precomputed hash chains)
不能明文表示密码基本上所有人都知道。因此数据库中的内容一般为加密后的密码。而加密的方式也是使用成熟的方案。比如MD5, SHA256。这些加密函数一般都包含了Hash的内容。从原文到密文的转换函数统一定义为H。最理想的情况是找到逆函数R。能从密文转换为原文。但实际上这个R函数是不存在的,最基本的理由是H函数的原文为无穷,而H函数的密文内容为有限多(比如256个比特的内容)。
虽然R函数不可能存在。但定义一个R函数,能将值域转换为原域的内容。比如给定任何一个256比特的串,能使用R函数获得一个长度为8位且只包含
[0-9][A-z][+=-]
的字符串。(很多网站要求固定长度密码,字符要求也是有限制的)。在有了H、R之后。随机选择一个明文,然后进行明文-》H密文-》R明文-》H密文-》R明文-….-》R明文的反复计算,形成一条链(重复次数为K)。而在数据库中,只需要保存首尾节点
Map<末明文,首明文>
即可。这是一条记录。当我们知道一个密文后。首先使用R函数得到一个明文。如果明文本身在保存的Map中,则获取到首节点的明文。重复上面的计算,看看其对应的明文内容。如果使用R函数得到的明文不在Map里面,则在进行一次H-R运算。直到一共进行了K次后得知该明文一定不在整个Map覆盖的内容中。
一个哈希链,你想情况下相当于保存了k个键值对。因此空间节省了1/k.
R函数的问题
R函数的问题是可能的碰撞,如果两个不同的密文经过R后得到相同的明文。则两条链上的内容会从某一个节点后完全一致,因此保存的有效键值对是不足nk的。
为了解决这个问题,彩虹表出现了。彩虹表的做法是在每一步采用不同的R函数。及时在某个地方R后的值一样,由于处于节点的位置不一样,下一次使用的R函数也会不一样,因此后面节点的内容又不一样了,避免了从一个节点后所有的内容重复的问题。
真是由于不同的节点处采取不同的R函数,如果彩虹每一个层次颜色不一样,因此才被称为彩虹表。
彩虹表的问题
由于每一个节点使用的R函数都不一样。因此不能像最开始一样将密文依次进行k此R-H之后判定明文不在库中。因为这里的R不固定。做法只能是假设: 明文位置为K-1处,使用Rk进行一次R-H运算,看看Map中是否包含。不包含则假设在K-2处,先使用R(k-2)-H-R(k-1)-H后结果是否在Map中。依次这么进行。
计算会比只是用一个R跟费事。但这算是一个经典的时间-空间的trade_off了。
彩虹表的防御
由于彩虹表是针对特定的H有效的。因此:
- 加盐。各个系统的加盐方式不一样,导致即使你破解了密文对应的原文,也无法从原文破解出原始密码。
加盐: 假设字符串为'ab'.加盐的意思是在某个位置加入某个随机的字符串。比如在开头和末尾加盐后为'randomheadabrandomend'
- 对常用的加密方式进行组合和重复。比如H=1000次的MD5.或者H=SHA256(MD5(SHA156(原文)))
回到开头,最朴素的思路中,需要用到常用的密码,然后将密码进行H运算后的结果也保存下来。
但其实不管是哈希链,还是彩虹表,都是不需要预先获取常用的密码。因为不断的进行H-R-H的运算过程中是可以不断得到随机的明文的。
HTTPS中的S 这里的s表示的是secure。http通信采用的是明文传输,因此没有安全性可言。比如被运营商强制加入广告-这个非常常见而且无奈。
https简单来说,就是对通讯过程中的内容加密。这里内容比较多,都可以单独写一篇文章了。
这个主题相关的参考文章有: Diffie-Hellman密码交换是如何运作的
阮一峰-SSL/TLS协议运行机制的概述RAS-DH-handshake
HTTPS篇之SSL握手过程详解
里面的内容都能理解。但dh秘钥交换相对于RSA秘钥交换的好处是什么?RAS-DH-handshake这篇文章中说了理由,最开始没细想,后面仔细琢磨一下,发现非常有道理。假设服务器的:私钥被盗走了。(最开始觉得没道理也主要是觉得私钥都被盗走了,还管什么安全问题)。私钥被盗走的情况下,如果黑客之前记录了之前所有的通讯记录(虽然被加密了,不知道内容),这个时候如果之前的内容时基于RSA的话,由于pre-master-key采用的公钥加密,此时可以解密,于是虽然每次会话采用的pre-master-key都不一样,但全部可以被解密,之前的所有记录都不安全,并且后续所有的记录也将是不安全的。但如果采用的DH交换算法,即使获取了私钥,也没有用。因为DH使用到的pre-master-key是计算出来的,而计算的依据并没有暴露在通讯过程中,是保存在通讯时候客户端、服务端的内存中的。并且后面的通话,黑客还是无法获取通讯内容,因为你无法获取到服务端内存中的值。
参考资料 SSH原理与运用(一):远程登录 可以说阮一峰的内容已经非常完善了
解读RSA公钥私钥储存格式
什么是彩虹表 非常非常精彩的说明