简单聊聊“常见场景的加密选择”

四种场景

密码加密

数据加密

对称签名

授权认证

密码加密

选择要素

安全性、不可逆、防彩虹表;算法的安全性通常依赖于算法速度足够慢,通常为 300ms ~1000ms,视场景;防彩虹表通常依赖于salt的随机性和长度

主流推荐

scrypt、bcrypt、pbkdf2

流行但不再推荐

sha1、sha1+salt、sha1+salt+ 多次哈希、sha256+salt

sha1 算法因为被攻破而不再推荐,目前推荐的是 sha256;salt 可以有效的抵御彩虹表攻击,能力取决于 salt 的随机性和长度;简单的多次哈希不会带来任何好处,通常会循环万次或更多来保证算法足够慢,也就是 pbkdf2 的方案

bcrypt vs pbkdf2

pbkdf2 是目前 NIST 官方推荐的标准。它约等于哈希函数 +salt+ 多次哈希。nodejs 也源生支持了这个算法。比对密码需要用原参数再计算一遍,所以需要保存 salt 和哈希次数。下面有一个 nodejs 的简单加密代码:

bcrypt 算法是基于 1993 提出的 Blowfish 算法优化而来。它是一种块加密算法。·也是目前大多数人认为最安全的密码加密算法。它的主要优势在于引入了一个代价因子,用来控制加密速度。算法 salt 会包含代价因子信息并被混入密文,比对密码不需要除密文外其他信息,所以用户可以随机更新代价因子调整加密速度,而不用做任何兼容处理。

nodejs 实现 https://github.com/dcodeIO/bcrypt.js/blob/master/src/bcrypt.js

数据加密

选择要素

加密性能 、防篡改(通常取决于使用的签名算法)

主流推荐

chacha20poly1305, aes-gcm

流行但不再推荐

chacha20poly1305 vs aes-gcm

chacha20-poly1305 = ChaCha20(流密码) + Poly1305(消息认证码)

是流密码,以字节为单位进行加密,安全性的关键体现在密钥流生成的过程,即所依赖的伪随机数生成器(PRNG)的强度。

nodejs 实现: https://github.com/calvinmetcalf/chacha20poly1305

aes-gcm = aes-ctr(计数器模式) + gmac(Galois消息认证码)

aes 是块密码,以块数据为单位进行加密。

nodejs 代码示例:

理论上 chacha20poly1305 优于 aes-gcm,但 aes-gcm 更成熟,使用更广泛。

在支持 aes-gcm 的 cpu 上,aes-gcm 性能优于 chacha20poly1305

ctr vs cbc

aes-cbc 模式

aes 的一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样来增强破解难度, 因此不能并行计算。

aes-ctr 计数器模式

在计数器模式下,我们不再对密文进行加密,而是对一个逐次累加的计数器进行加密,用加密后的比特序列与明文分组进行 XOR 得到密文,因此可以并行计算。

ctr 模式支持并行运算,性能更好。cbc 模式出现的更早,支持和运用更广泛。

对称签名

目前推荐的算法

sha256

哈希函数需要满足的条件,如果不满足,一般就认为不安全了

确定性:哈希函数的算法是确定性算法,算法执行过程不引入任何随机量。这意味着相同消息的哈希结果一定相同。

高效性:给定任意一个消息 m,可以快速计算 Hash(m) 。

目标抗碰撞性:给定任意一个消息 m0,很难找到另一个消息 m1,使得 hash(m0) = hash(m1).

广义抗碰撞性:很难找到两个消息 m0≠m1 ,使得 hash(m0) = hash(m1)。

sha1(160位,理论破解需2^80次运算) -> sha2 (256位,理论破解需2^128次运算)-> sha3

sha1的破解花费了 2^69 次运算,在 google 的云服务器上花费了几天时间,参考链接 https://www.zhihu.com/question/56234281

2010 年密码专家预测的 sha2 系列的安全期是 5-10 年

nodejs sha256 实现

有一个误区是 sha256 数字比 sha1 大很多,性能会慢很多。在安全要求不高的场景,选择sha1.

但实际上两者性能差距不大。sha1 稍快一些。

授权认证

推荐

jsonwebtoken

常见方案:对称加密(sha1, sha256, aes, des3)

jsonwebtoken 简介

jwt 是一个轻量级的认证规范,常用来在用户和服务器之间传递安全可靠的信息。

jwt 由三部分组成:header、payload、sign:

header 主要记录了使用的算法等基本信息,默认为 sha256,也支持使用非对称签名算法

payload 为用户信息和 jwt 定义的标准信息(如过期时间、签授方等),该部分为 -base64 编码,一般因只包含核心信息,避免 token 过长

signature 主要用于防篡改,也可以传入 algorithm:'none' 表示不签名

nodejs 实现: https://github.com/auth0/node-jsonwebtoken

需要注意的点

1.jwt 的 payload 是 base64 编码的,也就是明文传递的,所以不应该用 jwt 传递敏感信息。

2.jwt 对于同样的输入,默认是秒级唯一的,如果有更高的要求,可以在 payload 中传入 iat

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180504G1HH0T00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券