本文介绍目前现代密码学的最先进技术, 前半部分主要翻译自 《Cryptographic Right Answers》,附上收集的资料,和byron个人的理解。
密码学理论艰深,概念繁多,本人知识水平有限,错误难免,如果您发现错误,请务必指出,非常感谢!
按照优先级,应该选择:
(1) 首选 NaCl库,或者libsodium库,使用里面的crypto_secretbox()/crypto_secretbox_open() 函数 (2) Chacha20-Poly1305 算法 (3) AES-GCM 算法
适用场景:当你需要避免把明文数据在网络上传输的时候。
以上3种算法,都是AEAD类的算法,AEAD是2015年最好的选择。 其中的(2)和(3)在结构上类似:一个流加密模式的算法,配合一个多项式结构的MAC。 (2)是一个流加密算法,配合一个为通用cpu优化的MAC算法, 对密码学库的实现者来说,Poly1305也比GCM更容易安全地实现。 AES-GCM是工业标准(TLS目前主要用的就是AES-GCM),现代CPU通常都有专门为AES-GCM设计的硬件指令,但是在没有硬件指令支持的CPU上(比如32位的arm),(3)性能低于(2)。
此外,应该
选择使用256bit长度的密钥
适用场景:只要你在使用密码学,你就应该注意对称密钥长度
请记住:不要把对称加密(如AES)的key长度,和非对称加密(如RSA)的key长度搞混淆了,对称加密的key通常比非对称加密的key短多了。
下表对比了相同安全程度时,不同算法的密钥长度,单位:bit
Symmetric | ECC | DH/DSA/RSA |
---|---|---|
80 | 163 | 1024 |
112 | 233 | 2048 |
128 | 283 | 3072 |
192 | 409 | 7680 |
256 | 571 | 15360 |
此外,应该
应该选择 HMAC 类的算法
适用场景:安全加固一个API,如各种开放API的调用方认证
如果对一个API,你需要做认证(authenticating),但是不需要做加密(encrypting),记得千万不要自己发明算法,你自己发明的MAC算法基本都有安全漏洞,如果不信,请Google一下 “长度扩展攻击” 长度扩展攻击 Flickr的漏洞案例
同时,必须要注意的是,要使用一个常数时间字符串对比算法(这个地方和码农的常识完全相反,请务必留意)
此外,应该
应该选择SHA2类的算法:: SHA-256, SHA-384, SHA-512, SHA-512/256
优先使用 SHA-512/256,SHA-512/256这个算法把 SHA-512 的512bit输出截短到256bit,避开了length extension 攻击。 同时,目前SHA-2是很安全可靠的,你不需要升级到SHA-3.
此外,应该
应该使用256 bit的随机值
一定要使用 /dev/urandom,请认准这个
此外,应该
按照优先级顺序,选择:
此外,应该
应该使用NaCl库
适用场景:当你需要加密消息,发给陌生人,并且对方异步接收消息,做离线解密时。这是一个很窄的应用案例,这种用法有个名字叫电子信封(digital envelope),典型比如gpg加密文件后发送。
这条是几条之中最难做正确的,不要使用底层的密码学库,比如OpenSSL或者BouncyCastle。
你应该停止使用RSA,并且切换到椭圆曲线类体制,原因是:
如果你必须使用RSA,一定要使用RSA-OAEP with SHA256,指数使用 65537
应该使用NaCl,Ed25519,或者RFC6979
应用场景:如果你在设计一种新的比特币,或者一个给Ruby Gems或者Vagrant imges文件签名的系统,或者数字版权保护系统(DRM),其中一系列的文件需要离线做认证; 或者你在设计一个加密消息传输层
上一条的内容在此处全部适用。
在10+年做付费软件安全评估的工作经历中,我只有屈指可数的几次,遇到使用RSA-PSS的用户,RSA-PSS是一个学术界的推荐算法。
过去10年,非对称签名最主要的应用场景是比特币,和前向安全的密钥协商(TLS协议里面的ECDHE)。 其中最主要的算法全都是基于椭圆曲线体制的。务必警惕新出现的使用RSA签名的系统,很有可能有问题。
在过去几年中,业界有一种趋势:放弃传统DSA签名,改为难以误用的确定性签名体制,其中的EdDSA(不要和ECDSA搞混了喂!)和RFC6979是最好的例子。这种趋势的主要是受到2010年索尼PlayStation 3的 ECDSA私钥被破解事件的影响,在这个案例中,索尼公司的码农错误地把一个随机数重复使用来做ECDSA签名,形成了漏洞,使得破解者据此直接把私钥算出来了。确定性签名体制在设计中不再依赖随机数生成器,因此彻底避开此类误用。所以你应该优先使用确定性签名体制。
应该使用NaCl,Curve25519,或者DH-2048
适用场景:如果你在设计加密消息传输系统,并且无法使用固定对称密码
这是很棘手的一条,主要考量如下:
DH(密钥协商)算法确实很难用,但是它很重要。
应该使用OpenSSL,或者Google的BoringSSL,或者直接使用 AWS的 ELB
此处网站安全,指的是让网站支持HTTPS协议。 如果你不能把这个任务交给Amazon的云服务去做,把难题留给Amazon去解决,那么OpenSSL目前仍然是正确选择。
应该使用TLS
适用场景:如果你以为自己理解了前面关于公钥加密的介绍。。。
通常,在你设计了自己的RSA协议之后的1至18个月,你肯定会发现,你犯了某个错误,使你的协议没有任何安全性。 比如Salt Stack,Salt Stack的协议使用了 e=1 的RSA 公钥。。。
听起来,TLS有下面这些黑历史:
但是,你仍然应该使用TLS做传输协议,因为:
应该使用Tarsnap
#名词解释
本文的内容比较新,相关中文资料极少,因此文中的名词对读者可能有点陌生,故byron这里介绍一下文中提到的一些名词:
http://nacl.cr.yp.to/ 是密码学学术权威 Daniel J. Bernstein教授 设计的一个密码学算法库,2008年发开始公布。NaCl的特点是:api简洁而易用,高性能,高安全性,主要用于网络通信,加密,解密,签名等,NaCl提供了构建高层密码学工具的核心功能。
https://download.libsodium.org/doc/ libsodium是对NaCl库的一个分支,进一步改进接口易用性,和可移植性。
https://www.imperialviolet.org/2014/02/27/tlssymmetriccrypto.html 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)。 在AEAD这种概念里,cipher+MAC 被 一个AEAD算法替换。 http://en.wikipedia.org/wiki/Authenticated_encryption
ChaCha20-poly1305是一种AEAD,提出者是Daniel J. Bernstein教授,针对移动互联网优化,目前Google对移动客户端的所有流量都使用ChaCha20-Poly1305
AES-GCM是一种AEAD,是目前TLS的主力算法,互联网上https流量的大部分依赖使用AES-GCM。
Chip | AES-128-GCM speed | ChaCha20-Poly1305 speed |
---|---|---|
OMAP 4460 | 24.1 MB/s | 75.3 MB/s |
Snapdragon S4 Pro | 41.5 MB/s | 130.9 MB/s |
Sandy Bridge Xeon (AESNI) | 900 MB/s | 500 MB/s |
关于AES-CBC,在AES-GCM流行之前,TLS主要依赖AES-CBC,而由于历史原因,TLS在设计之初固定选择了MAC-then-Encrypt结构,AES-CBC和MAC-then-encrypt结合,为选择密文攻击(CCA)创造了便利条件,TLS历史上有多个漏洞都和CBC模式有关:
http://en.wikipedia.org/wiki/SHA-2
http://cr.yp.to/ecdh.html Curve25519 是目前最高水平的 Diffie-Hellman函数,适用于广泛的场景,由Daniel J. Bernstein教授设计。由于NIST P-256的设计过程不透明,有来历不明的参数,被广泛怀疑有后门,所以设计了Curve25519,Curve25519的设计过程完全公开,没有任何来历不明的参数。 部署情况:http://ianix.com/pub/curve25519-deployment.html
http://ed25519.cr.yp.to/ Ed25519是一个数字签名算法,
前向安全性( Perfect Forward Secrecy ) http://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy.html 前向安全性指的是,如果攻击者抓取并保存流量,那么将来私钥泄露后,攻击者也无法利用泄露的私钥解密这些流量。
http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange 在任何一本密码学教材里面都会重点介绍的
针对Timing attack,http://en.wikipedia.org/wiki/Timing_attack (这种攻击真是脑洞大开!) 当一个算法的运行时间和输入数据有关的时候,可以根据运行时间这一信息,破解出密钥等。 典型的,比如要验证一个对称签名,如果你用了C库里面的memcmp(),那你就会被timing attack方式攻击。 因此,涉及到密码学数据的memcmp,必须要用运行时间和输入无关的函数,比如OpenSSL库里面的CRYPTO_memcmp()