PHP 数据脱敏与加密的区别与实践
在 Web 开发中,保护用户隐私是开发者的基本责任。PHP 中常涉及两类敏感数据处理技术:**数据脱敏(Masking)** 和 **数据加密(Encryption)**。二者目标相似,但原理、场景和实现方式截然不同。
核心区别
- 脱敏:不可逆的“遮盖”操作,用于展示或日志等非业务场景,如将
13812345678显示为138****5678; - 加密:可逆的数学变换,需密钥解密,用于安全存储(如密码哈希)或传输(如 AES 加密),保障机密性与完整性。
实践示例
1. 简单脱敏函数(适用于手机号、身份证号)
<?php
function maskPhone(string $phone): string
{
if (strlen($phone) !== 11 || !preg_match('/^1[3-9]\d{9}$/', $phone)) {
return '***';
}
return substr($phone, 0, 3) . '****' . substr($phone, 7);
}
echo maskPhone('13812345678'); // 输出:138****5678
?>
2. 安全加密:使用 Sodium 扩展(PHP 7.2+ 内置)
推荐替代过时的 mcrypt,Sodium 提供现代、易用的加密 API:
<?php
// 生成密钥(生产环境请安全存储)
$key = sodium_crypto_secretbox_keygen();
// 加密
$message = '用户银行卡号:6228 4800 0000 0000 000';
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$ciphertext = sodium_crypto_secretbox($message, $nonce, $key);
// 解密(需相同 key + nonce)
$decrypted = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
if ($decrypted === false) {
throw new Exception('解密失败');
}
echo $decrypted; // 恢复原文
?>
3. 密码哈希(特殊加密场景)
密码永远不应“可逆”,应使用加盐哈希:
<?php
$password = 'user@123';
$hash = password_hash($password, PASSWORD_ARGON2ID); // 推荐 Argon2
var_dump(password_verify('user@123', $hash)); // true
// 验证时无需解密,仅比对哈希值
?>
⚠️ 注意:脱敏不等于安全!脱敏后数据仍可能被推理还原(如结合其他字段)。真实敏感字段(如密码、银行卡号)必须加密存储,并遵循《个人信息保护法》及 GDPR 原则——最小必要、目的限定、明确授权。
总结:脱敏是“看得见但看不懂”的呈现策略;加密是“看不见且拿不走”的保护机制。合理组合二者——前端展示用脱敏,后端存储用加密——方为 PHP 数据安全的最佳实践。
```