现代密码学程序猿补完计划

起点

最近空闲时间都在研究Google开源项目Tink的源码,发现很多密码学相关概念似懂非懂,直接导致越看越蒙圈。在通过谷歌度娘恶补基础知识的过程中,发现密码学理论艰深,概念繁多。写这篇文章就是希望把关键点记录下来,一来可以加深印象,留着以后温故而知新;二来也许可以给有同样需求的朋友一点捷径。

这篇文章注定会很长,因为我会尽量把每个概念或名词都附上详细解释,而我又不想分开来写。本文是我在翻阅了很多网络文章后,加入自己的理解后整理而成。所有出处和参考资料都在文章结尾,侵删!

本人水平有限,错误难免,如果您发现错误,请务必指出,非常感谢!

密码学的方法论

密码学和软件开发不同,软件开发是工程,是手艺,造轮子是写代码的一大乐趣。开发过程中常常要做出多方面的权衡(例如CAP),难有明确的对错。

密码学就不一样了。密码学是科学,不是工程,有严格的技术规范,严禁没有经过学术训练者随意创造。要有严谨的理论建模,严密的数学证明。少有需要权衡的地方,正确就是正确,错误就是错误。

密码学有很多陷阱,设计密码学协议或者软件,是极其容易出错的高风险专业活动,单纯的码农背景是做不了的。本着不作死就不会死的伟大理念,首先推荐读者尽可能使用 TLS 这种标准化、开源、使用广泛、久经考验、高性能协议。

经过几十年的军备竞赛式发展,已经发展出大量巧妙而狡猾的攻击方法,我们使用的算法,都是在所有已知攻击方法下都无法攻破的,由于大多数码农并没有精力去了解最前沿的攻击方法,我们也就没有能力去评价一个加密算法,更没有能力自己发明算法。所以最好跟着业界的主流技术走,肯定不会有大错。

现在搞现代密码学研究的主要都是数学家,在这领域里,以一个码农的知识背景,已经很难理解最前沿的东西,连正确使用加密算法都是要谨慎谨慎再谨慎。一个码农,能了解密码学基本概念,跟进密码学的最新应用趋势,并正确配置部署TLS这种协议,就很不错了。

本文也只是整理一些粗浅的密码学常识,读完这篇文章,并不能使你具有设计足够安全的密码学能力。

上面提到过的密码学算法很难被正确地使用,各种细节非常容易出错。 例如:

  • 大多数码农都听说过aes,可是你又了解多少细节呢,比如:aes应该用哪种模式?应该用哪种padding?IV/nonce应该取多少bit?IV/nonce应该怎么生成? key size应该选多大?key应该怎么生成?应不应该加MAC?MAC算法的选择?MAC和加密应该怎么组合?
  • 大多数知道RSA的码农分不清 RSASSA-PKCS1-v1_5 、RSAES-OAEP 和 RSASSA-PSS?
  • 更多错误参见 stackoverflow问答,强烈推荐仔细阅读

有没有被这一连串的问题弄懵逼?点开 stackoverflow 之后更是不知所云,备受打击?没关系,下面跟我一起来完成这个补完计划吧。

下文我提到的每个算法都是当前安全的,哪些过时或被破解的不在本文讨论范围内

在各种适用场景下,你应该使用的现代密码学算法:

加密数据

适用场景:需要避免把明文数据在网络上传输的时候。
推荐选择:(1) 首选NaCl,或者libsodium。使用crypto_secretbox() 或 crypto_secretbox_open() 函数 ;(2) Chacha20-Poly1305算法;(3) AES-GCM 算法;

以上3种算法,都是AEAD类的算法,目前来看是最好的选择。
并且,我们还应该:

  • 避免AES-ECB
  • 避免AES-CTR
  • 避免64bit块大小的块加密算法
  • 避免OFB模式
  • 不要使用RC4,RC4已经被攻破

我们先看看 AES-ECB 和 AES-CTR 存在什么问题,再看 AES-GCM 是怎么解决的。

  1. Electronic Codebook Book (ECB)
    电码本模式,将整个明文进行分组,分组长度可为128,256,或512bits,然后对每个小组进行加密。
    现代密码学程序猿补完计划_第1张图片
    ECB.png

    可以看出,明文中重复的排列会反映在密文中。并且,当密文被篡改时,解密后对应的明文分组也会出错,且解密者察觉不到密文被篡改了。也就是说,ECB不能提供对密文的完整性校验。
    因此,在任何情况下都不推荐使用ECB模式。

Ek
使用秘钥k对输入做对称加密运算

  1. CounTeR (CTR)
    计数器模式,我们不再对密文进行加密,而是对一个逐次累加的计数器进行加密,用加密后的比特序列与明文分组进行 XOR 得到密文。过程如下图:
    现代密码学程序猿补完计划_第2张图片
    CTR.png

    该模式下,每次与明文分组进行XOR的比特序列是不同的,因此,计数器模式解决了ECB模式中,相同的明文会得到相同的密文的问题。
    但CTR仍然不能提供密文消息完整性校验的功能。
    有的人可能会想到,如果将密文的hash值随密文一起发送,密文接收者对收到的密文计算hash值,与收到的hash值进行比对,这样是否就能校验消息的完整性呢?
    再仔细想想,就能发现这其中的漏洞。当篡改者截获原始的密文消息时,先篡改密文,而后计算篡改后的密文hash, 替换掉原始消息中的密文hash。这样,消息接收者仍然没有办法发现对源密文的篡改。
    可见,使用单向散列函数计算hash值仍然不能解决消息完整性校验的问题。

XOR
异或,英文为exclusive OR。是一个数学运算符,应用于逻辑运算。数学符号为“⊕”,计算机符号为“xor”。
异或也叫半加运算,其运算法则相当于不带进位的二进制加法。
运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1)。

  1. MAC (Message Authentication Code)
    想要校验消息的完整性,必须引入另一个概念:消息验证码。消息验证码是一种与秘钥相关的单项散列函数。
    密文的收发双方需要提前共享一个秘钥,例如当韩梅梅向李雷发送消息m时,不仅仅发送消息m,还要发送一个由MAC函数计算得到的MAC值。李雷会用自己的密钥对收到的消息m再次进行MAC计算,并判断这个值与收到的MAC值是否相等,如果不匹配则说明可能消息m被篡改了。由于窃听者不知道秘钥,所以不能为篡改后的消息计算出正确的MAC值。

  2. GMAC (Galois message authentication code mode)
    伽罗瓦消息验证码,GMAC就是利用伽罗华域(Galois Field,GF,有限域)乘法运算来计算消息的MAC值。假设秘钥长度为128bits, 当密文大于128bits时,需要将密文按128bits进行分组。流程如下图:


    现代密码学程序猿补完计划_第3张图片
    GMAC.png

Mh
将输入与秘钥h在有限域GF(2^128)上做乘法

  1. GCM (Galois/Counter Mode)
    AES-GCM中的G就是指GMAC,C就是指CTR。是一种AEAD,是目前TLS的主力算法,互联网上https流量的大部分依赖使用AES-GCM。
    GCM可以提供对消息的加密和完整性校验,另外,它还可以提供附加消息的完整性校验。在实际应用场景中,有些信息是我们不需要保密,但信息的接收者需要确认它的真实性的,例如源IP、源端口、目的IP和IV等等。因此,我们可以将这一部分作为附加消息加入到MAC值的计算当中。
    现代密码学程序猿补完计划_第4张图片
    GCM.png

AEAD
在通常的密码学应用中,Confidentiality (保密) 用加密实现,Message authentication (消息认证) 用MAC实现。这两种算法的配合方式,引发了很多安全漏洞,过去曾经有3种方法:

  1. Encrypt-and-MAC
  2. MAC-then-Encrypt
  3. Encrypt-then-MAC

后来发现,1和2都是有安全问题,所以2008年起,逐渐提出了“用一个算法在内部同时实现cipher+MAC”的idea,称为 AEAD(Authenticated encryption with additional data)。 在这种概念里,cipher+MAC 被 一个AEAD算法替换。Authenticated encryption

我们再看看另外几个推荐的加密库
NaCl
NaCl 是密码学学术权威 Daniel J. Bernstein教授设计的一个密码学算法库,2008年发开始公布。NaCl的特点是:api简洁而易用,高性能,高安全性,主要用于网络通信、加密、解密、签名等,NaCl提供了构建高层密码学工具的核心功能。目前仅有C和Python版。

libsodium
libsodium 是对NaCl库的一个分支,进一步改进接口易用性,和可移植性。网站看上去清爽多了,还提供了GitHub地址

ChaCha20-poly1305
是一种AEAD,提出者是Daniel J. Bernstein教授。由 ChaCha20流密码 和 Poly1305消息认证码( MAC )结合的一种应用在互联网安全协议中的认证加密算法,由Google公司率先在Andriod移动平台中的Chrome中代替 RC4 使用。由于其算法精简、安全性强、兼容性强等特点,目前Google致力于全面将其在移动端推广。

对称签名

适用场景:安全加固一个API,各种开放API的调用方认证
如果你需要对一个API做认证( authenticating ),但是不需要做加密( encrypting ),记得千万不要自己发明算法,你自己发明的MAC算法基本都有安全漏洞,如果不信,请Google一下 “长度扩展攻击” 长度扩展攻击 ,Flickr的漏洞案例

同时,必须要注意的是,要使用一个常数时间字符串对比算法(这个地方和码农的常识完全相反,请务必留意)

此外,应该

  • 避免自行设计的“带密码的hash”结构,你的设计基本都是有安全漏洞;
  • 避免HMAC-MD5,避免HMAC-SHA1,使用HMAC-SHA256, HMAC-SHA512等;
  • 避免复杂的多项式MAC;
  • 避免加密hash值的结构;
  • 避免CRC;

未完待续……

你可能感兴趣的:(现代密码学程序猿补完计划)