PHP 数据脱敏与加密的区别与实践
在 Web 开发中,保护用户隐私是开发者的基本责任。PHP 应用常需处理手机号、身份证号、邮箱等敏感数据,此时需明确区分数据脱敏与数据加密——二者目标不同,适用场景迥异。
核心区别
- 脱敏(Masking):不可逆的显示层处理,仅用于展示或日志,原始数据仍以明文/加密形式存储于数据库。如:
138****1234。 - 加密(Encryption):可逆的数学变换,需密钥解密还原原始值,用于安全存储与传输(如 AES)。加密后数据仍具业务可用性。
实践示例
✅ 安全脱敏(展示用)
<?php
function maskPhone(string $phone): string
{
return preg_replace('/^(\d{3})\d{4}(\d{4})$/', '$1****$2', $phone);
}
function maskIdCard(string $id): string
{
return substr($id, 0, 6) . str_repeat('*', 8) . substr($id, -4);
}
echo maskPhone('13812345678'); // 输出:138****5678
echo maskIdCard('110101199003072358'); // 输出:110101********2358
?>
✅ 可逆加密(存储用)
使用 PHP 内置 openssl_encrypt(AES-256-CBC),确保密钥安全保管:
<?php
class SecureCrypto
{
private const CIPHER = 'AES-256-CBC';
private string $key;
public function __construct(string $key)
{
// 建议从环境变量读取:$key = $_ENV['ENCRYPTION_KEY'] ?? '';
$this->key = hash('sha256', $key, true); // 衍生固定长度密钥
}
public function encrypt(string $data): string
{
$ivlen = openssl_cipher_iv_length(self::CIPHER);
$iv = openssl_random_pseudo_bytes($ivlen);
$encrypted = openssl_encrypt($data, self::CIPHER, $this->key, 0, $iv);
return base64_encode($iv . $encrypted);
}
public function decrypt(string $data): ?string
{
$decoded = base64_decode($data);
$ivlen = openssl_cipher_iv_length(self::CIPHER);
$iv = substr($decoded, 0, $ivlen);
$ciphertext = substr($decoded, $ivlen);
return openssl_decrypt($ciphertext, self::CIPHER, $this->key, 0, $iv);
}
}
$crypto = new SecureCrypto('my-secret-key-2024');
$encrypted = $crypto->encrypt('user@example.com');
echo "密文:" . $encrypted . "\n";
echo "解密:" . $crypto->decrypt($encrypted); // user@example.com
?>
⚠️ 注意:脱敏不替代加密!日志中脱敏手机号,但数据库中应加密存储;避免对已脱敏数据重复加密;密钥严禁硬编码,建议使用环境变量+密钥管理服务(如 AWS KMS)。
总结:脱敏是“遮眼”,加密是“锁箱”。合理组合二者——数据库加密存储 + 接口/日志脱敏输出——才能兼顾安全性与合规性(如《个人信息保护法》《GDPR》要求)。
```