使用加密算法可以达到以下目的:
在如今的信息安全领域,有各种各样的加密算法凝聚了数学家们的智慧。从宏观上来看,这些加密算法可以归结为三大类:哈希算法、对称加密算法、非对称加密算法。
在加密中,应该保密的仅仅是明文和密钥。也就是说我们通常假设攻击者对加密算法和密文了如指掌,因此加密的安全性应该仅仅依赖于密钥而不是依赖于假设攻击者不知道加密算法。
哈希算法:又称散列算法,把任意长度的输入通过哈希算法转换成固定长度的输出,这个固定长度的输出称为原输入消息的"哈希值"或"散列值"或"消息摘要"。
由于哈希算法的定义域是一个无限集合,而值域是一个有限集合,将无限集合映射到有限集合,每个哈希结果都存在无数个可能的目标文本,因此哈希不是一一映射,是不可逆的。
而加密算法是一一映射,因此理论上来说是可逆的。所以严格意义上哈希算法也不算加密,因为其结果是不可逆的,既然是不可逆的,那么当然不是用来加密的,而是签名。
一个优秀的 hash 算法,将能实现:
正向快速:给出明文和哈希算法,能在有限时间和有限资源内,将任意长度的明文快速计算出哈希值。
逆向困难:给定若干哈希值,在现有计算条件下,有限时间内几乎无法逆推出明文。
雪崩效应:哪怕原始输入信息修改一丁点儿,产生的哈希值也有很大的不同。所以,数据是否被篡改过,是否完整,都可以通过它的哈希值进行检验。
长度一致:长度不一样的信息散列计算后,长度是一致的。
冲突避免:不同的明文,通过散列计算后不会得到相同的哈希值,避免发生哈希冲突。
对简单哈希(Hash)的攻击
对于哈希的攻击,主要有寻找碰撞法和穷举法。
先来说说寻找碰撞法。数据库通常会使用md5或sha-1对用户密码加密存储,从哈希本身的定义可以看出,如果想非法登录,不一定非要得到注册时的密码,只要能得到一个密码的哈希碰撞即可。因此,如果能从哈希值中分析出一个密码的碰撞,则大功告成。
不过对这种攻击大可不必担心,因为目前对于MD5和SHA-1并不存在有效地寻找碰撞方法。虽然我国的数学家王小云教授曾经在国际密码学会议上发布了对于MD5和SHA-1的碰撞寻找改进算法,但这种方法和很多人口中所说的“破解”相去甚远,其理论目前仅具有数学上的意义,她将破解MD5的预期步骤数从280降到了269,虽然从数学上降低了好几个数量级,但2^69对于实际应用来说仍然是一个天文数字,就好比以前需要一亿年,现在需要一万年一样。
不过这并不意味着使用MD5或SHA-1后就万事大吉了,因为还有一种对于哈希的攻击方法——穷举法。通俗来说,就是在一个范围内,如从000000到999999,将其中所有值一个一个用相同的哈希算法计算,然后将结果和目标哈希值比较,如果相同,则这个值就一定是源字串或源字串的一个碰撞,于是就可以用这个值非法登录了。
这种看似笨拙的方法,在现实中爆发的能量却是惊人的,目前几乎所有的MD5破解机或MD5在线破解都是用这种穷举法,但就是这种“笨”方法,却成功破解出很多哈希串。纠其缘由,就是相当一部分口令是非常简单的,如“123456”或“000000”这种口令还有很多人在用,可以看出,穷举法是否能成功很大程度上取决于口令的复杂性。因为穷举法扫描的区间往往是单字符集、规则的区间,或者由字典数据进行组合,因此,如果使用复杂的口令,例如“ASDF#$%op.8930”这种变态级口令,穷举法就很难奏效了。
常见的哈希算法:MD5、SHA1、HMAC
MD5 的全称是 Message-Digest Algorithm 5
(信息-摘要算法),哈希值固定为128 bit长度。
1996年后被证实存在弱点,可以被加以破解,对于需要高度安全性的资料,专家一般建议改用其他算法,如SHA-2。
SHA1 的全称是 Secure Hash Algorithm
(安全哈希算法) ,SHA1 基于 MD5,加密后的数据长度更长,它对长度小于 2 ^ 64 bit的输入,产生长度为 160bit 的散列值。
但SHA-1的安全性在2010年以后已经不被大多数的加密场景所接受。2017年荷兰密码学研究小组CWI和Google正式宣布攻破了SHA-1。建议使用更强大的SHA-2哈希算法。
2001年发布,包括SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。SHA-2目前没有出现明显的弱点,至今尚未出现对SHA-2有效的攻击。
HMAC:全称是Hash-based Message Authentication Code
(哈希运算消息认证码),HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。也就是说HMAC是需要一个密钥的。
HMAC 发送方 和 接收方 都有的 key 进行计算,而没有这把 key 的第三方,则是 无法计算 出正确的 散列值的,这样就可以 防止数据被篡改。
Base64
Base64是一种将二进制流表示为 64 个字符的编码方式。
Base64并不是一种加密方式,明文使用Base64编码后的字符串通过索引表可以直接还原为明文。因此,Base64只能算是一个编码算法,对数据内容进行编码来适合传输。
对称加密算法是当今应用范围最广,使用频率最高的加密算法。它不仅应用于软件行业,在硬件行业同样流行。各种基础设施凡是涉及到安全需求,都会优先考虑对称加密算法。对称加密算法的加密密钥和解密密钥相同,加密产生密文,其长度和明文大致相同,对于大多数对称加密算法,加解密过程互逆。
优点:与非对称加密方法相比,计算量小,速度快,加密效率高,简单易用,适合于对海量数据进行加密处理 。
缺点:秘钥的管理和分发非常困难,不够安全。在数据传送前,发送方和接收方必须商定好秘钥,然后双方都必须要保存好秘钥,如果一方的秘钥被泄露,那么加密信息也就不安全了。
常见对称加密:DES、3DES、AES
DES(Data Encryption Standard,数据加密标准),密钥长度为 64 位,实际密钥只有 56 位。密钥长度太短,现在已经被认为不安全,一般不建议使用 DES 算法。
3DES(Triple DES、DESede,进行了三重DES加密的算法),就是把 DES 算法的执行了三次,每次的密钥都不一样。3DES也是AES提出之前的过度标准。现在AES已经是最广泛使用的对称算法。
AES(Advanced Encryption Standard,高级数据加密标准),AES是最流行的对称加密算法,AES和DES同为对称分组加密算法,都使用相同的密钥加密数据和解密数据。相比于DES算法密钥长度为56位,AES的密钥长度可以为128位、192位和256位,根据加解密密钥长度的不同,AES算法可分为AES-128、AES-192和AES-256三种。当然密钥越长就越安全,速度也就越慢。
AES在理论上是安全的,对于当前电子计算机和量子计算机的运算能力,除非在数学上有重大突破,AES密码算法仍是不可破解的。
1976年以前,所有的加密方法都是使用对称加密,这种加密模式有一个最大弱点:甲方必须把秘钥告诉乙方,否则无法解密。保存和传递密钥,就成了最头疼的问题。
1976年,人们认识到,加密和解密可以使用不同的规则,只要这两种规则之间存在某种对应关系即可,这样就避免了直接传递密钥。这种新的加密模式被称为"非对称加密算法"。
非对称式加密就是加密和解密所使用的不是同一个密钥,通常有两个密钥,称为"公钥"和"私钥", 公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密;如果用私钥对数据进行加密,那么只有用对应的公钥才能解密。
但严格意义上说,只能使用公钥加密,使用私钥来解密。而使用私钥加密更多的起到签名的作用,让公钥解密来验证身份,因为公钥是要传递的,有泄露风险。
1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法。从那时直到现在,RSA算法一直是最广为使用的"非对称加密算法"。毫不夸张地说,只要有计算机网络的地方,就有RSA算法。
这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。
下面解释一下RSA算法的原理,RSA算法并不难,只需要一点数论知识就可以理解。
(1)互质关系
如果两个正整数,除了1以外,没有其他公因子,我们就称这两个数是互质关系(coprime)。比如,15和32没有公因子,所以它们是互质关系。这说明,不是质数也可以构成互质关系。
关于互质关系,不难得到以下结论:
任意两个质数构成互质关系,比如13和61。
一个数是质数,另一个数只要不是前者的倍数,两者就构成互质关系,比如3和10。
如果两个数之中,较大的那个数是质数,则两者构成互质关系,比如97和57。
1和任意一个自然数是都是互质关系,比如1和99。
p是大于1的整数,则p和p-1构成互质关系,比如57和56。
p是大于1的奇数,则p和p-2构成互质关系,比如17和15。
(2)欧拉函数
任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?(比如,在1到8之中,有多少个数与8构成互质关系?)
计算这个值的方法就叫做欧拉函数,以φ(n)表示。在1到8之中,与8形成互质关系的是1、3、5、7,所以 φ(n) = 4。
φ(n)的几种情况:
φ(1) = 1
。因为1与任何数(包括自身)都构成互质关系。φ(n)=n-1
。因为质数与小于它的每一个数,都构成互质关系。比如5与1、2、3、4都构成互质关系。n = p1 × p2
则 φ(n) = φ(p1p2) = φ(p1)φ(p2)
,即积的欧拉函数等于各个因子的欧拉函数之积。比如,φ(56)=φ(8×7)=φ(8)×φ(7)=4×6=24
。(3)欧拉定理
如果两个正整数a和n互质,则n的欧拉函数 φ(n) 可以让下面的等式成立:
也就是说,a的φ(n)次方被n除的余数为1。
(4)模反元素
如果两个正整数a和n互质,那么一定可以找到整数b,使得 ab-1 被n整除,或者说ab被n除的余数是1。
这时,b就叫做a的"模反元素"。
我们通过一个例子,来理解RSA算法。
第一步,随机选择两个不相等的质数p和q。
选择了61和53。(实际应用中,这两个质数越大,就越难破解。)
第二步,计算p和q的乘积n。
把61和53相乘。
n = 61×53 = 3233
n的长度就是密钥长度。3233写成二进制是110010100001,一共有12位,所以这个密钥就是12位。实际应用中,RSA密钥一般是1024位,重要场合则为2048位。
第三步,计算n的欧拉函数φ(n)。
根据公式:
φ(n) = (p-1)(q-1)
算出φ(3233)等于60×52,即3120。
第四步,随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质。
在1到3120之间,随机选择了17。
但是在实际的使用中,通常,如果是真·随机选取的话,在加解密、签名验证的过程中大概会有超过1000次的模乘运算,所以建议公钥的的值选择是3或65537。这样,公钥加密、私钥签名的模乘运算次数可以降低到2次和17次,可以显著的提高在实际应用中RSA算法的效率。
第五步,计算e对于φ(n)的模反元素d。
所谓"模反元素"就是指有一个整数d,可以使得ed被φ(n)除的余数为1。
ed ≡ 1 (mod φ(n))
这个式子等价于
ed - 1 = kφ(n)
已知 e=17, φ(n)=3120,
17d - 3120k = 1
算出一组整数解为 (d,k)=(2753,-15)
第六步,将n和e封装成公钥,n和d封装成私钥。
例子中,n=3233,e=17,d=2753,所以公钥就是 (3233,17),私钥就是(3233, 2753)。实际应用中,公钥和私钥的数据都采用ASN.1格式表达,这里不是重点。
回顾上面的密钥生成步骤,一共出现六个数字:
p
q
n
φ(n)
e
d
这六个数字之中,公钥用到了两个(n和e),其余四个数字都是不公开的。其中最关键的是d,因为n和d组成了私钥,一旦d泄漏,就等于私钥泄漏。
那么,有无可能在已知n和e的情况下,推导出d?
ed ≡1 (mod φ(n))。只有知道e和φ(n),才能算出d。
φ(n)=(p-1)(q-1)。只有知道p和q,才能算出φ(n)。
n=pq。只有将n因数分解,才能算出p和q。
结论:如果n可以被因数分解,d就可以算出,也就意味着私钥被破解。
可是,大整数的因数分解,这是一个公认的数学难题。目前,除了暴力破解,还没有发现别的有效方法。
维基百科这样写道:
"对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。
假如有人找到一种快速因数分解的算法,那么RSA的可靠性就会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA密钥才可能被暴力破解。到目前为止,世界上还没有任何可靠的攻击RSA算法的方式。
只要密钥长度足够长,用RSA加密的信息实际上是不能被解破的。"
12301866845301177551304949
58384962720772853569595334
79219732245215172640050726
36575187452021997864693899
56474942774063845925192557
32630345373154826850791702
61221429134616704292143116
02221240479274737794080665
351419597459856902143413
这是人类已经分解的最大整数,768个二进制位,它等于:
33478071698956898786044169
84821269081770479498371376
85689124313889828837938780
02287614711652531743087737
814467999489
×
36746043666799590428244633
79962795263227915816434308
76426760322838157396665112
79233373417143396810270092
798736308917
有了公钥和密钥,就能进行加密和解密了。
(1)加密要用公钥 (n,e)
假设A要向B发送加密信息m,他就要用B的公钥 (n,e) 对m进行加密。这里需要注意,m必须是整数(字符串可以取ascii值或unicode值),且m必须小于n。
所谓"加密",就是算出下式的c:
m^e ≡ c (mod n)
B的公钥是 (3233, 17),A的m假设是65,那么可以算出下面的等式:
6517 ≡ 2790 (mod 3233)
于是,c等于2790,A就把2790发给了B。
(2)解密要用私钥(n,d)
B拿到A发来的2790以后,就用自己的私钥(3233, 2753) 进行解密。可以证明,下面的等式一定成立:
c^d ≡ m (mod n)
也就是说,c的d次方除以n的余数为m。现在,c等于2790,私钥是(3233, 2753),那么,B算出
27902753 ≡ 65 (mod 3233)
因此,B知道了A加密前的原文就是65。
至此,"加密–解密"的整个过程全部完成。
优点:
缺点:
从上边可以看出,同样安全级别的加密算法,RSA需要更长的密钥。这就使运算速度较慢,较对称密码算法慢几个数量级。且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。
RSA产生密钥很麻烦,受到素数产生技术的限制,加密速度慢,因此,使用RSA只能加密少量数据,大量的数据加密还要靠对称密码算法。实际应用中一般用来加密对称算法的密钥,而密文多用对称加密算法加密传输。
数字签名
数字签名的作用:证明消息是某个特定的人,而不是随随便便一个人发送的(有效性);除此之外,数字签名还能证明消息没有被篡改(完整性)。简单来说,数字签名就是非对称加密的逆应用,用私钥加密消息,用公钥解密消息。
数字签名在发送方:
数字签名验证在接收方:
数字证书
上面的一切都很完美,你用公钥能够解密,说明确实是私钥方发送的,你很放心,但有没有想过,万一这把公钥本身,就被人做了手脚?为了保证“公钥”是可信的,数字证书应运而生。
数字证书一般包含:公钥,证书的数字签名,公钥拥有者的信息。若证书验证成功,这表示该公钥是合法,可信的。
数字证书里有个概念,认证机构(Certification Authority, CA),发送方先把自己的公钥给CA,CA对其进行加密得到加密后的发送方公钥(用的是CA的私钥和CA加密算法),也就是CA的数字证书。
如何生成证书?
如何验证证书?
接收方拿到后,首先使用CA的公钥验证证书的数字签名,验证通过后则可以使用数字证书中的发送方公钥。CA是第三方机构,CA公钥是公开的,通过其他可信的方式提前获取得到的,因此不可能伪造。
因为HTTP在传输数据时使用的是明文是不安全的,为了解决这一隐患网景公司推出了SSL安全套接字协议层,SSL是基于HTTP之下TCP之上的一个协议层,是基于HTTP标准并对TCP传输数据时进行加密,所以HPPTS是HTTP+SSL/TCP的简称。
在SSL 3之后SSL重命名为TLS,是更为安全的升级版 SSL。
SSL/TLS协议基本过程包含四次握手,所以常说的HTTPS的七次握手就是TCP的三次加SSL/TLS的四次。
(1) 客户端发出请求(ClientHello)
首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做ClientHello请求。在这一步,客户端主要向服务器提供以下信息。
(2) 服务器回应(SeverHello)
服务器收到客户端请求后,向客户端发出回应,这叫做SeverHello。服务器的回应包含以下内容。
(3) 客户端回应
客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。如下图
如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息。
一个随机数。该随机数用服务器公钥加密,防止被窃听。
编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。
上面第一项的随机数,是整个握手阶段出现的第三个随机数,又称"pre-master key"
。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。
(4) 服务器的最后回应
服务器收到客户端的第三个随机数pre-master key
之后,计算生成本次会话所用的"会话密钥"。然后,向客户端最后发送下面信息。
编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
服务器握手结束通知,表示服务器的握手阶段已经结束。
至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容。
参考:
RSA算法原理(二)
SSL/TLS协议运行机制的概述