PHP 数据库敏感数据加密存储方案
在用户注册、支付、身份认证等场景中,密码、身份证号、手机号、银行卡号等属于敏感数据,绝不可明文存储于数据库。PHP 提供了成熟的安全工具链,结合现代加密实践,可构建可靠的数据保护机制。
✅ 推荐方案:AES-256-GCM + 密钥分离
相比过时的 mcrypt 或简单哈希(如 MD5),推荐使用 PHP 7.2+ 原生支持的 openssl_encrypt() 配合 AES-256-GCM 模式——它同时提供机密性、完整性与认证(AEAD),并自动处理 nonce 和认证标签。
🔐 示例:加密/解密用户身份证号
<?php
// 1. 安全密钥管理(生产环境应从环境变量或密钥管理服务加载)
$key = hex2bin(getenv('APP_ENCRYPTION_KEY') ?: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef');
// 2. 加密函数(返回 base64 编码的 ciphertext|nonce|tag)
function encryptSensitive(string $plaintext, string $key): string
{
$ivlen = openssl_cipher_iv_length('aes-256-gcm');
$iv = openssl_random_pseudo_bytes($ivlen);
$tag = '';
$ciphertext = openssl_encrypt(
$plaintext,
'aes-256-gcm',
$key,
OPENSSL_RAW_DATA,
$iv,
$tag,
'',
16 // auth tag length
);
if ($ciphertext === false) {
throw new RuntimeException('Encryption failed: ' . openssl_error_string());
}
return base64_encode($ciphertext . $iv . $tag);
}
// 3. 解密函数
function decryptSensitive(string $encrypted, string $key): string
{
$data = base64_decode($encrypted);
$ivlen = openssl_cipher_iv_length('aes-256-gcm');
$taglen = 16;
$iv = substr($data, -$ivlen - $taglen, $ivlen);
$tag = substr($data, -$taglen);
$ciphertext = substr($data, 0, -$ivlen - $taglen);
$plaintext = openssl_decrypt(
$ciphertext,
'aes-256-gcm',
$key,
OPENSSL_RAW_DATA,
$iv,
$tag
);
if ($plaintext === false) {
throw new RuntimeException('Decryption failed: ' . openssl_error_string());
}
return $plaintext;
}
// ✅ 使用示例
$idCard = '11010119900307285X';
$encrypted = encryptSensitive($idCard, $key);
echo "加密后: {$encrypted}\n";
$decrypted = decryptSensitive($encrypted, $key);
echo "解密后: {$decrypted}\n"; // 输出: 11010119900307285X
?>
⚠️ 重要安全提醒:
- 密钥 绝不硬编码,使用
dotenv或系统环境变量管理; - 每个敏感字段建议使用独立密钥(或密钥派生);
- 数据库字段类型设为
TEXT(AES-GCM 加密后体积约增长 40–50 字节); - 避免对密码使用对称加密——应始终用
password_hash()+password_verify()进行单向哈希。
通过 AES-256-GCM,您不仅实现了强加密,还获得了防篡改能力——任何密文被修改都会导致解密失败。结合良好的密钥生命周期管理与最小权限数据库访问策略,即可构建符合《个人信息保护法》及 PCI DSS 等合规要求的数据存储体系。
安全不是功能,而是设计起点。
```