密码系统常识

如今,无论是程序员还是普通人都直接或间接的接触到密码系统,并且密码系统发展到今天,已经相当复杂。本文主要概括密码系统的作用以及使其发挥作用的工具。 想了解密码系统的历史可以参考 密码故事 ,想学习基于OpenSSL的网络安全,可以参考 Network Security with OpenSSL

1 密码系统的作用

1.1 加密

加密保证了数据的安全,就算加密的数据本身被窃取(无论是通过侵入主机复制数据,还是通过窃听网络数据传输),在密钥不丢失的情况下,无法从加密的数据中获取原始数据。这是加密系统最古老的应用,有对称加密和非对称加密。

现代密码系统的一大原则是,数据安全不依赖于加密算法,而是依赖于密钥。算法都是公开的,但是只要密钥不丢失,数据就是安全的。所以密钥的妥善保存和安全传输至关重要。

1.2 完整性

数据的完整性指“数据接受方”收到的数据就是“数据发送方”发送的数据,数据在传送过程中没有被篡改。这通常依赖于一个单向函数,可以根据数据计算出一个“摘要”,不同数据计算出的“摘要”不同,并且根据“摘要”无法还原原来的数据。

常见的“摘要”算法,有CRC32,MD5,SHA1,SHA256等。值得注意的是,CRC32的冲突率很高(不同数据生成相同“摘要”几率很高),MD5也不十分靠谱,通过巧妙构造数据,两份不同的数据可以生成相同“摘要”

需要注意的是,如果传输信道不安全,那么攻击者既然可以攻击(伪造)数据,那么也可以攻击(伪造)“摘要”,所以要确“摘要”(传输)安全。

1.3 认证

加密系统可以用于身份认证

1.4 防抵赖

用于确认某条消息的确是某人发送的,该人没法抵赖说这个消息不是他发送的,别人也不能伪造他发送这样的消息。

2 常见的网络攻击

密码系统的上述作用和常见的网络攻击是对应的。

2.1 窃听(被动攻击)

数据加密了,就算数据被窃听,数据也不会丢失。

2.2 篡改

窃听者可以篡改窃听到的数据,如果提前知道消息”摘要“,那么可以知道数据被篡改了。

2.3 电子欺骗

攻击者伪装成某个真实的用户

2.4 劫持(中间人攻击)

劫持连接,用自己的数据,替换掉用户的数据。

2.5 重放攻击

攻击者截获传输的数据,然后用传输的数据“伪装”成真正的用户,发起请求。

3 加密系统算法

3.1 对称加密

对称加密的特点是,加密密钥和解密密钥是同一个。对称加密速度快,但是密钥传输比较麻烦。双方需要安全的途径传送密钥。对称加密的安全性取决于加密算法和密钥长度,某些算法具有更好的安全性(加解密也更慢)。在加密算法确定的情况下,密钥越长,安全性越高。另外,密钥的有效期也很重要,如果密钥使用时间很长,就算不能解密数据,在有大量加密数据的情况下,通过分析加密数据,也可能获取重要信息。所以,最安全的情况是,每次数据交互都使用不同的密钥。

常见的算法有,DES,3DES,AES,RC4等。

3.2 公钥加密(非对称加密)

其实叫非对称加密更合适,它的特点是加密密钥和解密密钥不一样。之所以叫公钥加密,是因为通常使用公钥加密,私钥解密。但是使用私钥加密,公钥解密也是完全可以的。私钥持有人保存好自己的私钥,公开自己的公钥。耳熟能详的是RSA算法,它的主要作用:

3.2.1 加解密

通常不会直接用它来加解密数据,因为太慢了,非常非常慢。而是用它来加密“对称加密密钥。当有人想要和“私钥”持有人通信时,会先生成一个“对称加密密钥”,并用“私钥”对应的“公钥”(这个是公开的)加密“对称加密密钥”,用对称加密密钥加密数据。“私钥”持有人先解密“对称加密密钥”,然后再用“对称加密密钥”解密数据。

这里,非对称加密主要解决“对称加密密钥”的安全传输问题。听起来美好,但是还有一个问题没有解决。上面说了“公钥”是公开的,任何人都可以获得,那么如何保证获得的“公钥”是“私钥”对应的公钥呢?有人做中间人攻击,用它的“公钥”代替真正的公钥,那么它还是可以解密传输的数据。

这涉及到4的问题。

3.2.2 数据签名

“私钥”持有人可以用“私钥”做数据签名,收到数据的人,用相应的“公钥”对签名做认证,确定数据的确是“私钥”持有人发送的,“私钥”持有人也没法抵赖数据是它发送的。因为只有他的“私钥”才能生成这样的签名

因为非对称加密很慢,所以不会对原始数据做签名,而是生成原始数据的“摘要”,对“摘要”做。

考虑一个场景,授权中心用”私钥“签名token,放到Cookie里面,然后其它系统就可以用它的”公钥“验证token签名。如果验证通过,说明token是授权中心签发的,证明已经被授权,因为其它人没有”私钥“,没办法签发这样的token。

3.3 哈希函数和消息认证码

哈希函数是单向函数,用于计算“摘要”。“摘要”可以用于保证消息的完整性,但是“摘要”的可靠性是个问题。一种解决办法是,通信双方约定一个“密码”,对数据+“密码”做摘要。这样保证“摘要”不会被中间人伪造。HMAC是常见的算法。

哈希函数和消息认证码,在密码存储和用户认证场合用的很多。

利用哈希函数的单向性,可以计算密码的哈希值,然后存储该哈希值,避免存放真正的密码,这样即使密码文件被盗,也不会丢失真正的密码。这对于长度较短的密码并不适用,因为现在的CPU/GPU很强劲,遍历所有密码生成密码表并不困难,和现在用的密码文件比对,还是可以找出密码。选择比较耗时的哈希函数和长的密码是稳妥的方法。

借助HTTPS或者SSL,直接传输用户名/密码到服务器端做认证,通常不会有什么安全隐患。但是如果是HTTP或者TCP,则传输明文密码,有密码泄漏的危险。此时可以借助HMAC。通过传送HMAC(对请求做HMAC),而不是密码,然后再服务端用相同的规则计算HMAC,如果HMAC的值相同,则说明密码正确。HMAC可以防止密码泄漏,但不能防止重放攻击。使用HTTPS或者SSL仍是最稳妥的办法。

3.3.1 哈希不是加密

我们经常听到用MD5加密一下,或者我们存的是加密后的值。这种表述并不正确。凡是有加密,必然有解密,MD5是哈希函数,不可逆,所以没办法用MD5加密。所以"MD5加密"密码然后传输,丝毫不会增加安全性,此时知道MD5后的密码和知道密码是等效的。

4 信任链

上文提到针对“公钥”的中间人攻击,如何确认看到的“公钥”是正确的公钥,没有被攻击者篡改呢?不借助第三方,仅靠非对称加密算法本身,无法解决这个问题,假设有某个机构(CA),私钥持有人和公钥使用者都信任它。那么私钥持有人可以让CA给他的公钥做签名(利用CA的私钥)。公钥使用者可以验证签名(利用CA的公钥)的正确性,确保收到的“公钥”是正确的。

可是如何获取CA的公钥呢?这相当于又回到了起点,我们没法确认得到的CA的公钥就是CA的公钥。我们只能选择信任,把CA的公钥内置到系统中,就像浏览器做的那样。

5 密钥的安全性

上面说的安全,全部集中在传输层面(无论是网络,还是电话)。如果私钥(或者对称密钥)被窃取(假设黑客入侵了存放密钥的系统),怎么办?作为一种选择,可以给密钥设置一个密码,这个密码只能记在脑海里。就算“密钥”被窃取,不知到密码也没用。密码必须够复杂,以应对暴力破解。密码带来的坏处是系统启动比较麻烦,系统启动时必须手动输入密码。记住,这个密码只能保存在脑子里,这是安全的起点。现实情况时,很多时候这个密码为空,为了使用,部署方便。

6 其它攻击

密码系统主要预防网络攻击,所以HTTPS不是万精油。针对XSS,SQL注入,钓鱼网站,社交攻击等攻击方式,还需要服务提供方和用户都留神。

Author: root

Created: 2016-03-09 三 12:22

Emacs 24.4.1 (Org mode 8.2.10)

Validate