漫谈加解密(Encryption)& 哈希(Hash)算法

一、Encryption算法和Hash算法的区别

  • 信息论角度:
    • Encryption是可逆的,没有信息熵的改变
    • Hash是不可逆的,Hash一般会导致信息熵减小
  • 应用角度:
    • Encryption常被用来做基于密钥的数据加解密(AES、RSA、ECC)
    • Hash主要被用来做数字签名、数据校验(CRC、SHA、MD5)
  • 小白角度:
    • Encryption就是带密码的保险箱
    • Hash就是榨汁机,有去无回

二、加解密算法分为对称(Symmetric)、非对称(Asymmetry)两大类

  • 对称(Symmetric)加密
    对称加密是最古老的一种加密方式,从最古老的基于查表替换的“凯撒密码”到现代的AES等算法,都是这种类型。其核心特点在于加密、解密的密钥是一样的(或可以互相通过算法变换的)。这种算法很容易理解,就是一把钥匙既能加锁也能开锁。几种常见的对称加密算法:

  • 非对称(Asymmetry)加密
    非对称加密算法,就是加密、解密的密钥分为两组,并且互相不能反推。这种算法在现实中很难有什么事物可以类比。大致就是通过某种算法可以生成一个密钥对k1、k2,用k1加密之后的密文只能用k2解密,反之亦然。
    非对称加密算法从原理上讲常用的有两种:

    • 基于因数分解的算法
      • RSA、DSA是此类算法中的代表,Linux系统的SSH就是基于这两种算法进行文件key auth。前几年一般建议RSA至少要达到1024位密钥才能保证抵御暴力破解,但由于GPU和超级计算机的算力提升,现在密钥长度建议2048位了。
    • 椭圆曲线算法(ECC)
      • 这里说的ECC不是服务器内存上用到的Error-Correcting Code(奇偶校验),而是Elliptic Curve Cryptography。内在原理其实我这种搬砖的程序猿不懂,大致是基于解决椭圆曲线离散对数问题的一种算法-_-|||。但我知道的是这个算法可以用1/6的密钥长度达到比RSA更高的强度。代表算法有ECC、SM2等。
  • 非对称加密算法非常酷,但它有一个致命的缺点:慢。RSA加密的速度大致是AES的1/30左右。所以我们不可能在所有场合都采用这类加密算法。我们的程序猿前辈们就创造了SSL、TLS等加密体系:

三、加密体系

说到要给大家理清几个概念:

TLS的前身是SSL,HTTP + TLS = HTTPS

TLS协议允许C/S模型的应用程序跨网络通讯,旨在防止窃听和篡改的方式进行沟通。 TLS协议的优势在于它是与应用层协议独立无关的。高层的应用层协议(例如:HTTP、FTP、Telnet等等)能透明的建立于TLS协议之上。TLS协议在应用层协议通信之前就已经完成加密算法、通信密钥的协商以及服务器认证工作。在此之后应用层协议所传送的数据都会被加密,从而保证通信的私密性。

TLS协议是可选的,所以如果需要使用就必须配置客户端和服务器,有两种主要方式实现这一目标:一个是使用统一的TLS协议端口号(例如:用于HTTPS的端口443);另一个是客户端请求服务器连接到TLS时使用特定的协议机制 (例如:邮件、新闻协议和STARTTLS)。一旦客户端和服务器都同意使用TLS协议,他们通过使用一个握手过程协商出一个有状态的连接以传输数据[1]。通过握手,客户端和服务器协商各种参数用于建立安全连接:

1. 当客户端连接到支持TLS协议的服务器要求建立安全连接并列出了受支持的密码组合(加密密码算法和加密哈希函数),握手开始。

2. 服务器从该列表中决定加密和散列函数,并通知客户端。

3. 服务器发回其数字证书,此证书通常包含服务器的名称、受信任的证书颁发机构(CA)和服务器的公钥。

4. 客户端确认其颁发的证书的有效性。

5. 为了生成会话密钥用于安全连接,客户端使用服务器的公钥加密随机生成的密钥,并将其发送到服务器,只有服务器才能使用自己的私钥解密。

6. 利用随机数,双方生成用于加密和解密的对称密钥。

7. 这就是 TLS 协议的握手,握手完毕后的连接是安全的,直到连接(被)关闭。如果上述任何一个步骤失败,TLS 握手过程就会失败,并且断开所有的连接。

以上小节摘自:https://zh.wikipedia.org/zh-cn/%E5%82%B3%E8%BC%B8%E5%B1%A4%E5%AE%89%E5%85%A8%E5%8D%94%E8%AD%B0

四、块(Block)加密 & 流(Stream)加密

世界上的数据分为两种:Block and Stream —— auxten

  • Block
    • 块很容易理解,数据就在那里,无论你读或者不读。块的一个显著特征就是支持“随机读写”,你可以对数据Block正向读、倒着读、跳着读、躺着读。磁盘和内存都是这类数据。大多数加密算法对Block的支持是原生的,也就是说Block是大多数加密算法的加密、解密最小单元。
  • Stream
    • 流就像水管一样,打开水龙头,来什么你就收什么。流的一个显著特征就是支持“随机读写”。由于解密的过程会对之前的数据有依赖,对流进行加密难度系数要比块加密要高。流的一个典型场景就是网络数据传输,如:HTTPS、SSH等协议。

五、盐的重要性

之前在这篇文章中提到过,如果单纯的把文件按块去加密,即使采用最强壮的算法也会存在一个很明显的漏洞,这里不再赘述,参见:http://www.zhihu.com/question/22312959/answer/41758072

六、暴力破解(Brute-force)

  • 原理就是穷举密钥去尝试解密,由于GPU的算力提升,量子计算机的兴起,很多算法变得不堪一击。

七、哈希(Hash)

屏幕截图 2015-06-09 20.11.31

哈希算法在很多地方也被叫做摘要算法、散列算法。简单来说就像是给数据录指纹。常用来做数据校验、数据签名。常见算法有MD5、SHA、CRC等。

维基百科中英文版的这篇文章写得比较全面https://en.wikipedia.org/wiki/Hash_function,我就补充一点,关于哈希函数的选用。

工作中发现,很多人对哈希函数的了解仅限于MD5。例如,在做数据库的分库分表的时候,可能需要对hostname做一次哈希再去取模,这里采用MD5就显得过于浪费CPU。要知道MD5平均会将每个Byte进行6.8次运算代入。

如果只是需要利用哈希的离散型,完全可以采用更轻的哈希算法,例如fnv hash,对内存是顺序访问,对CPU cache友好,效率比MD5高出很多。具体参见chongo大神的这篇文章:http://www.isthe.com/chongo/tech/comp/fnv/

文章分类 后端 标签: ,

发表评论

电子邮件地址不会被公开。

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">