加密
加密
Yii2 的安全组件类 \yii\base\Security
,提供了一系列方法来处理与安全性相关的常见任务,其中当然也包括加密相关的方法,如生成随机数据、加密和解密及确认数据完整性等。
生成伪随机数据
伪随机数据在很多情况下都很有用。例如,当通过电子邮件重置密码时,您需要生成一个令牌,将其保存到数据库中,并通过电子邮件发送给最终用户,这反过来又会允许他们证明该帐户的所有权。这个令牌是独一无二且难以猜测的,否则攻击者可能会预测令牌的值并重置用户的密码。
我们可以用 Yii 的安全组件来简单生成伪随机数据,即生成指定长度的随机字符串,该字符串匹配 [A-Za-z0-9_-]+
,对 URL 编码是透明的。代码如下:
$key = Yii::$app->security->generateRandomString();
生成随机字节
Yii 提供了 generateRandomKey
方法来生成随机字节,和 generateRandomString
方法类似,生成一个随机的串,参数为长度,默认为32位,区别在于它生成的可能不是 ASCII,代码如下:
$inputKey = Yii::$app->security->generateRandomKey();
密钥推导
HKDF 算法
使用标准 HKDF 算法从给定的输入键导出一个键。代码如下:
$key = Yii::$app->security->hkdf('sha256', $inputKey, $salt);
HKDF2 算法
使用标准的 PBKDF2 算法从给定的密码导出一个密钥。代码如下:
$key = Yii::$app->security->hkdf('sha256', $password, $salt, 100000);
加密和解密
Yii 提供了两种 加密/解密 数据的方式。数据通过加密功能传递,以便只有拥有密钥的人才能解密。例如,我们需要在数据库中存储一些信息,但我们需要确保只有拥有密钥的用户才能查看它(即使应用程序数据库已被泄露)。
密码方式
我们可以使用 \yii\base\Security::encryptByPassword()
方法,使用密码方式进行数据加密,该方法对一个密码,使用了 PBKDF2 和一个随机 salt 来获取用于加密和身份验证的键,该随机 salt 故意放慢速度以防止字典攻击。键的派生时间由 \yii\base\Security::$derivationIterations
属性决定,应该将其设置得尽可能高。具体代码如下:
// $data 和 $secretKey 从表单中获得
$encryptedData = Yii::$app->security->encryptByPassword($data, $secretKey);
// 将 $encryptedData 存储到数据库
注意: 尽可能避免使用密码加密。没有任何东西可以保护低质量或被破解的密码。
对应的,我们可以使用 \yii\base\Security:: decryptByPassword()
方法,来通过密码方式解密,即随后当用户想要读取数据时,代码如下:
// $secretKey 从用户输入获得,$encryptedData 来自数据库
$data = Yii::$app->security->decryptByPassword($encryptedData, $secretKey);
注意: 通过上面得到的编码后的数据不是 ASCII,可以通过 base64_encode() 和 base64_decode() 在外层包装下。
密钥方式
我们可以使用 \yii\base\Security::encryptByKey()
方法,使用密钥方式进行数据加密,该方法对一个密钥,使用了 HKDF 和 一个随机 salt 来获取用于加密和身份验证的键,相对于encryptByPassword()
来说非常快。密钥必须是适当随机的,可以使用 generateRandomKey()
来生成。代码如下:
// 生成密钥
$inputKey = Yii::$app->security->generateRandomKey();
// 密钥加密
$encryptedData = Yii::$app->security->encryptByKey($data, $inputKey);
对应的,我们也可以通过 \yii\base\Security::decryptByKey()
使用密钥来解密,代码如下:
//解密
$data = Yii::$app->security->decryptByKey($encryptedData, $inputKey);
注意: 该加密解密方法,存在着第三个参数,比如我们可以传用户的 ID 等,这样此信息将和 $inputKey 一起作为加密解密的钥匙。
以上两个加密的数据包含一个密钥消息验证码(MAC),因此不需要对输入或输出数据进行哈希处理。
确认数据完整性
在某些情况下,您需要验证您的数据未被第三方篡改,甚至以某种方式损坏。Yii 提供了一种简单的方法来确认数据完整性的。
用密钥和数据生成的哈希前缀数据,以便在数据被篡改后能够被检测到,代码如下:
// $secretKey 是我们的应用程序或用户密钥,$genuineData 是从可靠来源获得的
$data = Yii::$app->security->hashData($genuineData, $secretKey);
注意:
hashData()
的第三个参数代表生成的哈希值是否为原始二进制格式,如果为false
,则会生成小写十六进制数字。
检查数据完整性是否受到损害,代码如下:
// $secretKey 我们的应用程序或用户密钥,$data 从不可靠的来源获得
$data = Yii::$app->getSecurity()->validateData($data, $secretKey);
注意:
validateData()
函数的第三个参数应该与使用hashData()
生成数据时的值相同,它指示数据中的 hash 值是否是二进制格式,如果为false
,则表示 hash 值仅由小写十六进制数字组成,将生成十六进制数字。
注意:当这些方法执行任务时,不需要对
encryptByKey()
或encryptByPassword()
的输入或输出进行哈希处理。
时序攻击防护
在密码学中,时序攻击是一种侧信道攻击,攻击者试图通过分析加密算法的时间执行来推导出密码。Yii 提供了一个简单的防时序攻击的方法进行字符串比较,代码如下:
Yii::$app->security->compareString($expected, $actual);
BREACH 攻击防护
BREACH(Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext,中文为:通过自适应超文本压缩的浏览器侦察和外泄)攻击,是一个当使用 HTTP 压缩时,针对 HTTPS 的安全漏洞。
Yii 从 2.0.12 开始,提供了一组防护 BREACH 攻击的方法,将随机掩码应用于 token,并将用于结果的掩码前置,使字符串始终惟一。通过在每个请求上随机输出 token 来减少 BREACH 攻击。
给 token 增加掩码,以使其不可压缩,代码如下:
$maskedToken = Yii::$app->security->maskToken($token);
给之前的 token 解除掩码,代码如下:
$token = Yii::$app->security->unmaskToken($maskedToken);
注意:在 Yii2 的 csrf 功能上就使用了 maskToken。
💖喜欢本文档的,欢迎点赞、收藏、留言或转发,谢谢支持!
作者邮箱:zhuzixian520@126.com,github地址:github.com/zhuzixian520
推荐文章: